/// <summary> /// Creates a condition that depends on this page-modification value. /// </summary> public static PageModificationValueCondition ToCondition(this PageModificationValue <bool> pageModificationValue, bool isTrueWhenValueSet = true) { return(new PageModificationValueCondition( statementGetter => pageModificationValue.AddJsModificationStatement( valueExpression => statementGetter(isTrueWhenValueSet ? valueExpression : "!( {0} )".FormatWith(valueExpression))), () => pageModificationValue.Value ^ !isTrueWhenValueSet)); }
/// <summary> /// Creates a setup object for a text control with auto-complete behavior. /// </summary> /// <param name="autoCompleteResource">The resource containing the auto-complete items. Do not pass null.</param> /// <param name="displaySetup"></param> /// <param name="widthOverride">The width of the control. This overrides any value that may be specified via CSS. If no width is specified via CSS and you /// pass null for this parameter, the width will be based on the maximum number of characters a user can input.</param> /// <param name="numberOfRows">The number of lines in the text control. Must be one or more.</param> /// <param name="classes">The classes on the control.</param> /// <param name="disableTrimming">Pass true to disable white-space trimming.</param> /// <param name="placeholder">The hint word or phrase that will appear when the control has an empty value. Do not pass null.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="checksSpellingAndGrammar">Pass true to enable spelling and grammar checking, false to disable it, and null for default behavior.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action. Currently has no /// effect for multiline controls.</param> /// <param name="triggersActionWhenItemSelected">Pass true to also trigger the action when the user selects an auto-complete item.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static TextControlSetup CreateAutoComplete( ResourceInfo autoCompleteResource, DisplaySetup displaySetup = null, ContentBasedLength widthOverride = null, int numberOfRows = 1, ElementClassSet classes = null, bool disableTrimming = false, string placeholder = "", string autoFillTokens = "", bool?checksSpellingAndGrammar = null, SpecifiedValue <FormAction> action = null, bool triggersActionWhenItemSelected = false, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new TextControlSetup( displaySetup, numberOfRows == 1 ? "text" : "", widthOverride, numberOfRows, false, classes, disableTrimming, false, placeholder, autoFillTokens, autoCompleteResource, checksSpellingAndGrammar, action, triggersActionWhenItemSelected, valueChangedAction, pageModificationValue, null, validationPredicate, validationErrorNotifier)); }
/// <summary> /// Creates a block-level radio button that is part of the group. /// </summary> /// <param name="isSelected"></param> /// <param name="validationMethod">The validation method. Do not pass null.</param> /// <param name="label"></param> /// <param name="action"></param> /// <param name="autoPostBack"></param> /// <param name="pageModificationValue"></param> /// <param name="nestedControlListGetter"></param> /// <returns></returns> public BlockCheckBox CreateBlockRadioButton( bool isSelected, Action <PostBackValue <bool>, Validator> validationMethod, string label = "", FormAction action = null, bool autoPostBack = false, PageModificationValue <bool> pageModificationValue = null, Func <IEnumerable <Control> > nestedControlListGetter = null) { BlockCheckBox checkBox = null; var validation = formValue.CreateValidation( (postBackValue, validator) => validationMethod(new PostBackValue <bool>(postBackValue.Value == checkBox, postBackValue.ChangedOnPostBack), validator)); checkBox = new BlockCheckBox( formValue, label, new BlockCheckBoxSetup(action: action, triggersActionWhenCheckedOrUnchecked: autoPostBack, nestedControlListGetter: nestedControlListGetter), () => checkBoxesAndSelectionStatesAndPageModificationValues.Where(i => i.Item3 != null) .Select(i => i.Item3.GetJsModificationStatements(i.Item1 == checkBox ? "true" : "false")), validation); checkBoxesAndSelectionStatesAndPageModificationValues.Add( Tuple.Create <CommonCheckBox, bool, PageModificationValue <bool> >(checkBox, isSelected, pageModificationValue)); if (pageModificationValue != null) { formValue.AddPageModificationValue(pageModificationValue, value => value == checkBox); } return(checkBox); }
/// <summary> /// Creates a setup object for an obscured (i.e. password) text control. /// </summary> /// <param name="displaySetup"></param> /// <param name="widthOverride">The width of the control. This overrides any value that may be specified via CSS. If no width is specified via CSS and you /// pass null for this parameter, the width will be based on the maximum number of characters a user can input.</param> /// <param name="classes">The classes on the control.</param> /// <param name="placeholder">The hint word or phrase that will appear when the control has an empty value. Do not pass null.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> /// <returns></returns> public static TextControlSetup CreateObscured( DisplaySetup displaySetup = null, ContentBasedLength widthOverride = null, ElementClassSet classes = null, string placeholder = "", string autoFillTokens = "", SpecifiedValue <FormAction> action = null, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new TextControlSetup( displaySetup, "password", widthOverride, null, false, classes, true, false, placeholder, autoFillTokens, null, null, action, null, valueChangedAction, pageModificationValue, null, validationPredicate, validationErrorNotifier)); }
/// <summary> /// Creates a setup object for a numeric-text control with auto-complete behavior. /// </summary> /// <param name="autoCompleteResource">The resource containing the auto-complete items. Do not pass null.</param> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control.</param> /// <param name="placeholder">The hint word or phrase that will appear when the control has an empty value. Do not pass null.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="triggersActionWhenItemSelected">Pass true to also trigger the action when the user selects an auto-complete item.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="numericPageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static NumericTextControlSetup CreateAutoComplete( ResourceInfo autoCompleteResource, DisplaySetup displaySetup = null, ElementClassSet classes = null, string placeholder = "", string autoFillTokens = "", SpecifiedValue <FormAction> action = null, bool triggersActionWhenItemSelected = false, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, PageModificationValue <long?> numericPageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new NumericTextControlSetup( new TextControlSetup( displaySetup, "text", null, null, false, classes, false, true, placeholder, autoFillTokens, autoCompleteResource, null, action, triggersActionWhenItemSelected, valueChangedAction, pageModificationValue, numericPageModificationValue, validationPredicate, validationErrorNotifier), validationErrorNotifier)); }
private ElementClassSet getSectionClasses( bool?expanded, PageModificationValue <string> expandedPmv, ElementClass closedClass, ElementClass expandedClass) { return(!expanded.HasValue ? expandedClass : expandedPmv == null ? expanded.Value ? expandedClass : closedClass : expandedPmv.ToCondition(bool.FalseString.ToCollection()) .ToElementClassSet(closedClass) .Add(expandedPmv.ToCondition(bool.TrueString.ToCollection()).ToElementClassSet(expandedClass))); }
/// <summary> /// Creates a free-form radio button list. /// </summary> /// <param name="allowNoSelection">Pass true to cause a selected item ID with the default value (or the empty string when the item ID type is string) to /// represent the state in which none of the radio buttons are selected. Note that this is not recommended by the Nielsen Norman Group; see /// http://www.nngroup.com/articles/checkboxes-vs-radio-buttons/ for more information.</param> /// <param name="selectedItemId"></param> /// <param name="disableSingleButtonDetection">Pass true to allow just a single radio button to be displayed for this list. Use with caution, as this /// violates the HTML specification.</param> /// <param name="itemIdPageModificationValue"></param> /// <param name="itemMatchPageModificationSetups"></param> public static FreeFormRadioList <ItemIdType> Create <ItemIdType>( bool allowNoSelection, ItemIdType selectedItemId, bool disableSingleButtonDetection = false, PageModificationValue <ItemIdType> itemIdPageModificationValue = null, IEnumerable <ListItemMatchPageModificationSetup <ItemIdType> > itemMatchPageModificationSetups = null) { return(new FreeFormRadioList <ItemIdType>( allowNoSelection, disableSingleButtonDetection, selectedItemId, itemIdPageModificationValue, itemMatchPageModificationSetups)); }
/// <summary> /// Creates a condition that depends on this page-modification value. /// </summary> public static PageModificationValueCondition ToCondition <T>( this PageModificationValue <T> pageModificationValue, IEnumerable <T> values, bool isTrueOnMatch = true) { values = values.ToImmutableArray(); return(new PageModificationValueCondition( statementGetter => pageModificationValue.AddJsModificationStatement( valueExpression => statementGetter( "[ {0} ].indexOf( {1} ) {2} -1".FormatWith( StringTools.ConcatenateWithDelimiter(", ", values.Select(i => "'" + i.ObjectToString(true) + "'").ToArray()), valueExpression, isTrueOnMatch ? "!=" : "=="))), () => values.Contains(pageModificationValue.Value) ^ !isTrueOnMatch)); }
internal DurationControlSetup( DisplaySetup displaySetup, bool isReadOnly, ElementClassSet classes, SpecifiedValue <FormAction> action, FormAction valueChangedAction, PageModificationValue <string> pageModificationValue, Func <bool, bool> validationPredicate, Action validationErrorNotifier) { DisplaySetup = displaySetup; IsReadOnly = isReadOnly; Classes = classes; Action = action != null ? action.Value : FormState.Current.FormControlDefaultAction; ValueChangedAction = valueChangedAction; PageModificationValue = pageModificationValue; ValidationPredicate = validationPredicate; ValidationErrorNotifier = validationErrorNotifier; }
/// <summary> /// Creates a setup object for a standard radio button. /// </summary> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the container.</param> /// <param name="highlightedWhenSelected"></param> /// <param name="action">The action that will occur when the user hits Enter on the radio button. Pass null to use the current default action.</param> /// <param name="pageModificationValue"></param> /// <param name="nestedContentGetter">A function that gets the content that will appear beneath the radio button.</param> /// <param name="nestedContentAlwaysDisplayed">Pass true to force the nested content to always be displayed instead of only when the button is selected. /// </param> public static FlowRadioButtonSetup Create( DisplaySetup displaySetup = null, ElementClassSet classes = null, bool highlightedWhenSelected = false, SpecifiedValue <FormAction> action = null, PageModificationValue <bool> pageModificationValue = null, Func <IReadOnlyCollection <FlowComponent> > nestedContentGetter = null, bool nestedContentAlwaysDisplayed = false) { return(new FlowRadioButtonSetup( displaySetup, classes, RadioButtonSetup.Create(action: action, pageModificationValue: pageModificationValue), highlightedWhenSelected, nestedContentGetter, nestedContentAlwaysDisplayed)); }
/// <summary> /// Creates a setup object for a standard duration control. /// </summary> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control container.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static DurationControlSetup Create( DisplaySetup displaySetup = null, ElementClassSet classes = null, SpecifiedValue <FormAction> action = null, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new DurationControlSetup( displaySetup, false, classes, action, valueChangedAction, pageModificationValue, validationPredicate, validationErrorNotifier)); }
/// <summary> /// Creates a display setup object for display that depends on this page-modification value. /// </summary> public static DisplaySetup ToDisplaySetup(this PageModificationValue <bool> pageModificationValue, bool componentsDisplayedWhenValueSet = true) { return (new DisplaySetup( Tuple.Create <Action <string>, Action <string> >( statements => pageModificationValue.AddJsModificationStatement( valueExpression => "if( {0} )".FormatWith(componentsDisplayedWhenValueSet ? valueExpression : "!( {0} )".FormatWith(valueExpression)) + " { " + statements + " }"), statements => pageModificationValue.AddJsModificationStatement( valueExpression => "if( {0} )".FormatWith(componentsDisplayedWhenValueSet ? "!( {0} )".FormatWith(valueExpression) : valueExpression) + " { " + statements + " }")), () => pageModificationValue.Value ^ !componentsDisplayedWhenValueSet)); }
/// <summary> /// Creates a generic phrasing container (i.e. span element) that depends on this page-modification value. /// </summary> public static IReadOnlyCollection <PhrasingComponent> ToGenericPhrasingContainer <ModificationValueType>( this PageModificationValue <ModificationValueType> pageModificationValue, Func <ModificationValueType, string> textSelector, Func <string, string> jsTextExpressionGetter) { return(new CustomPhrasingComponent( new DisplayableElement( context => { pageModificationValue.AddJsModificationStatement( valueExpression => "$( '#{0}' ).text( {1} );".FormatWith(context.Id, jsTextExpressionGetter(valueExpression))); return new DisplayableElementData( null, () => new DisplayableElementLocalData("span", focusDependentData: new DisplayableElementFocusDependentData(includeIdAttribute: true)), children: new TextNode(() => textSelector(pageModificationValue.Value)).ToCollection()); }).ToCollection()).ToCollection()); }
/// <summary> /// Creates a hidden field. /// </summary> /// <param name="value">Do not pass null.</param> /// <param name="id"></param> /// <param name="pageModificationValue"></param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> /// <param name="jsInitStatementGetter">A function that takes the field’s ID and returns the JavaScript statements that should be executed when the DOM is /// loaded. Do not return null.</param> public EwfHiddenField( string value, HiddenFieldId id = null, PageModificationValue <string> pageModificationValue = null, Action <PostBackValue <string>, Validator> validationMethod = null, Func <string, string> jsInitStatementGetter = null) { pageModificationValue = pageModificationValue ?? new PageModificationValue <string>(); var elementId = new ElementId(); var formValue = new FormValue <string>( () => value, () => elementId.Id, v => v, rawValue => rawValue != null ? PostBackValueValidationResult <string> .CreateValid(rawValue) : PostBackValueValidationResult <string> .CreateInvalid()); component = new ElementComponent( context => { elementId.AddId(context.Id); id?.AddId(context.Id); return(new ElementData( () => { var attributes = new List <Tuple <string, string> >(); attributes.Add(Tuple.Create("type", "hidden")); attributes.Add(Tuple.Create("name", context.Id)); attributes.Add(Tuple.Create("value", pageModificationValue.Value)); return new ElementLocalData( "input", focusDependentData: new ElementFocusDependentData( attributes: attributes, includeIdAttribute: id != null || pageModificationValue != null || jsInitStatementGetter != null, jsInitStatements: StringTools.ConcatenateWithDelimiter( " ", pageModificationValue != null ? "$( '#{0}' ).change( function() {{ {1} }} );".FormatWith( context.Id, pageModificationValue.GetJsModificationStatements("$( this ).val()")) : "", jsInitStatementGetter?.Invoke(context.Id) ?? ""))); })); }, formValue: formValue); formValue.AddPageModificationValue(pageModificationValue, v => v); if (validationMethod != null) { validation = formValue.CreateValidation(validationMethod); } }
internal DateAndTimeControlSetup( DisplaySetup displaySetup, bool isReadOnly, ElementClassSet classes, string autoFillTokens, int?minuteInterval, SpecifiedValue <FormAction> action, FormAction valueChangedAction, PageModificationValue <string> pageModificationValue, Func <bool, bool> validationPredicate, Action validationErrorNotifier) { DisplaySetup = displaySetup; IsReadOnly = isReadOnly; Classes = classes; AutoFillTokens = autoFillTokens; MinuteInterval = minuteInterval; Action = action != null ? action.Value : FormState.Current.FormControlDefaultAction; ValueChangedAction = valueChangedAction; PageModificationValue = pageModificationValue; ValidationPredicate = validationPredicate; ValidationErrorNotifier = validationErrorNotifier; }
// Web Forms compatibility. Remove when EnduraCode goal 790 is complete. public static void AddDisplayLink( this PageModificationValue <bool> pageModificationValue, IEnumerable <WebControl> controls, bool controlsDisplayedWhenValueSet = true) { controls = controls.ToImmutableArray(); foreach (var control in controls) { pageModificationValue.AddJsModificationStatement( valueExpression => "setElementDisplay( '{0}', {1} );".FormatWith( control.ClientID, controlsDisplayedWhenValueSet ? valueExpression : "!( {0} )".FormatWith(valueExpression))); } EwfPage.Instance.AddDisplayLink(new DisplayLinkAdapter(controls, () => pageModificationValue.Value ^ !controlsDisplayedWhenValueSet)); }
/// <summary> /// Creates an element-class set that depends on this page-modification value. /// </summary> public static ElementClassSet ToElementClassSet( this PageModificationValue <bool> pageModificationValue, ElementClassSet staticClassSet, bool classesPresentWhenValueSet = true) { if (staticClassSet.JsModificationStatementAdderAndInclusionPredicatePairsByClassName.Values.Any(i => i != null)) { throw new ApplicationException("At least one class already has dynamic behavior."); } return (new ElementClassSet( staticClassSet.JsModificationStatementAdderAndInclusionPredicatePairsByClassName.Keys.ToImmutableDictionary( i => i, i => Tuple.Create <Action <Func <string, string> >, Func <bool> >( statementGetter => pageModificationValue.AddJsModificationStatement( valueExpression => statementGetter(classesPresentWhenValueSet ? valueExpression : "!( {0} )".FormatWith(valueExpression))), () => pageModificationValue.Value ^ !classesPresentWhenValueSet)))); }
// Web Forms compatibility. Remove when EnduraCode goal 790 is complete. public static void AddDisplayLink <T>( this PageModificationValue <T> pageModificationValue, IEnumerable <T> values, IEnumerable <WebControl> controls, bool controlsDisplayedOnMatch = true) { values = values.ToImmutableArray(); controls = controls.ToImmutableArray(); foreach (var control in controls) { pageModificationValue.AddJsModificationStatement( valueExpression => "setElementDisplay( '{0}', [ {1} ].indexOf( {2} ) {3} -1 );".FormatWith( control.ClientID, StringTools.ConcatenateWithDelimiter(", ", values.Select(i => "'" + i.ObjectToString(true) + "'").ToArray()), valueExpression, controlsDisplayedOnMatch ? "!=" : "==")); } EwfPage.Instance.AddDisplayLink(new DisplayLinkAdapter(controls, () => values.Contains(pageModificationValue.Value) ^ !controlsDisplayedOnMatch)); }
/// <summary> /// Creates a setup object for a number control with auto-complete behavior. /// </summary> /// <param name="autoCompleteResource">The resource containing the auto-complete items. Do not pass null.</param> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control.</param> /// <param name="placeholder">The hint word or phrase that will appear when the control has an empty value. Do not pass null.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="triggersActionWhenItemSelected">Pass true to also trigger the action when the user selects an auto-complete item.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static NumberControlSetup CreateAutoComplete( ResourceInfo autoCompleteResource, DisplaySetup displaySetup = null, ElementClassSet classes = null, string placeholder = "", string autoFillTokens = "", SpecifiedValue <FormAction> action = null, bool triggersActionWhenItemSelected = false, FormAction valueChangedAction = null, PageModificationValue <decimal?> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new NumberControlSetup( displaySetup, false, false, TextControlSetup.ElementClass.Add(classes ?? ElementClassSet.Empty), placeholder, autoFillTokens, autoCompleteResource, action, triggersActionWhenItemSelected, valueChangedAction, pageModificationValue ?? new PageModificationValue <decimal?>(), validationPredicate, validationErrorNotifier)); }
/// <summary> /// Creates a setup object for a standard imprecise-number control. /// </summary> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static ImpreciseNumberControlSetup Create( DisplaySetup displaySetup = null, ElementClassSet classes = null, string autoFillTokens = "", SpecifiedValue <FormAction> action = null, FormAction valueChangedAction = null, PageModificationValue <decimal> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new ImpreciseNumberControlSetup( new NumberControlSetup( displaySetup, true, false, classes, "", autoFillTokens, null, action, null, valueChangedAction, pageModificationValue ?? new PageModificationValue <decimal>(), validationPredicate, validationErrorNotifier))); }
/// <summary> /// Creates a setup object for a standard radio list. /// </summary> /// <param name="items">The items in the list. There must be at least one.</param> /// <param name="displaySetup"></param> /// <param name="useHorizontalLayout">Pass true if you want the radio buttons to be laid out horizontally instead of vertically.</param> /// <param name="classes">The classes on the list container.</param> /// <param name="unlistedSelectedItemLabelGetter">A function that will be called if the selected item ID does not match any list item and is not the default /// value of the type. The function takes the selected item ID and returns the label of the unlisted selected item, which will appear before all other /// items in the list. The string " (invalid)" will be appended to the label.</param> /// <param name="disableSingleButtonDetection">Pass true to allow just a single radio button to be displayed for this list. Use with caution, as this /// violates the HTML specification.</param> /// <param name="action">The action that will occur when the user hits Enter on a radio button. Pass null to use the current default action.</param> /// <param name="selectionChangedAction">The action that will occur when the selection is changed. Pass null for no action.</param> /// <param name="itemIdPageModificationValue"></param> /// <param name="itemMatchPageModificationSetups"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static RadioListSetup <ItemIdType> Create <ItemIdType>( IEnumerable <SelectListItem <ItemIdType> > items, DisplaySetup displaySetup = null, bool useHorizontalLayout = false, ElementClassSet classes = null, Func <ItemIdType, string> unlistedSelectedItemLabelGetter = null, bool disableSingleButtonDetection = false, SpecifiedValue <FormAction> action = null, FormAction selectionChangedAction = null, PageModificationValue <ItemIdType> itemIdPageModificationValue = null, IReadOnlyCollection <ListItemMatchPageModificationSetup <ItemIdType> > itemMatchPageModificationSetups = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) => new RadioListSetup <ItemIdType>( displaySetup, useHorizontalLayout, false, classes, unlistedSelectedItemLabelGetter, items, FreeFormRadioListSetup.Create( disableSingleButtonDetection: disableSingleButtonDetection, selectionChangedAction: selectionChangedAction, itemIdPageModificationValue: itemIdPageModificationValue, itemMatchPageModificationSetups: itemMatchPageModificationSetups, validationPredicate: validationPredicate, validationErrorNotifier: validationErrorNotifier), action);
/// <summary> /// Creates a radio button list. /// </summary> /// <param name="items">The items in the list. There must be at least one.</param> /// <param name="selectedItemId">The ID of the selected item. This must either match a list item or be the default value of the type, unless an unlisted /// selected item label getter is passed.</param> /// <param name="useHorizontalLayout">Pass true if you want the radio buttons to be laid out horizontally instead of vertically.</param> /// <param name="unlistedSelectedItemLabelGetter">A function that will be called if the selected item ID does not match any list item and is not the default /// value of the type. The function takes the selected item ID and returns the label of the unlisted selected item, which will appear before all other /// items in the list. The string " (invalid)" will be appended to the label.</param> /// <param name="defaultValueItemLabel">The label of the default-value item, which will appear first, and only if none of the list items have an ID with the /// default value. Do not pass null. If you pass the empty string, no default-value item will appear and therefore none of the radio buttons will be /// selected if the selected item ID has the default value and none of the list items do.</param> /// <param name="disableSingleButtonDetection">Pass true to allow just a single radio button to be displayed for this list. Use with caution, as this /// violates the HTML specification.</param> /// <param name="action">The action that will occur when the user hits Enter on a radio button.</param> /// <param name="autoPostBack">Pass true if you want an action to occur when the selection changes.</param> /// <param name="itemIdPageModificationValue"></param> /// <param name="itemMatchPageModificationSetups"></param> public static SelectList <ItemIdType> CreateRadioList <ItemIdType>( IEnumerable <SelectListItem <ItemIdType> > items, ItemIdType selectedItemId, bool useHorizontalLayout = false, Func <ItemIdType, string> unlistedSelectedItemLabelGetter = null, string defaultValueItemLabel = "", bool disableSingleButtonDetection = false, FormAction action = null, bool autoPostBack = false, PageModificationValue <ItemIdType> itemIdPageModificationValue = null, IEnumerable <ListItemMatchPageModificationSetup <ItemIdType> > itemMatchPageModificationSetups = null) { return(new SelectList <ItemIdType>( useHorizontalLayout, null, unlistedSelectedItemLabelGetter, defaultValueItemLabel, null, null, items, disableSingleButtonDetection, selectedItemId, action, autoPostBack, itemIdPageModificationValue, itemMatchPageModificationSetups)); }
/// <summary> /// Creates a drop-down list. /// </summary> /// <param name="items">The items in the list. There must be at least one.</param> /// <param name="selectedItemId">The ID of the selected item. This must either match a list item or be the default value of the type, unless an unlisted /// selected item label getter is passed.</param> /// <param name="width">The width of the list. This overrides any value that may be specified via CSS. If no width is specified via CSS and you pass null /// for this parameter, the list will be just wide enough to show the selected item and will resize whenever the selected item is changed.</param> /// <param name="unlistedSelectedItemLabelGetter">A function that will be called if the selected item ID does not match any list item and is not the default /// value of the type. The function takes the selected item ID and returns the label of the unlisted selected item, which will appear before all other /// items in the list. The string " (invalid)" will be appended to the label.</param> /// <param name="defaultValueItemLabel">The label of the default-value item, which will appear first, and only if none of the list items have an ID with the /// default value. Do not pass null. If you pass the empty string, no default-value item will appear.</param> /// <param name="placeholderIsValid">Pass true if you would like the list to include a default-value placeholder that is considered a valid selection. /// This will only be included if none of the list items have an ID with the default value and the default-value item label is the empty string. If you pass /// false, the list will still include a default-value placeholder if the selected item ID has the default value and none of the list items do, but in this /// case the placeholder will not be considered a valid selection.</param> /// <param name="placeholderText">The default-value placeholder's text. Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the drop-down list.</param> /// <param name="autoPostBack">Pass true if you want an action to occur when the selection changes.</param> /// <param name="itemIdPageModificationValue"></param> /// <param name="itemMatchPageModificationSetups"></param> public static SelectList <ItemIdType> CreateDropDown <ItemIdType>( IEnumerable <SelectListItem <ItemIdType> > items, ItemIdType selectedItemId, System.Web.UI.WebControls.Unit?width = null, Func <ItemIdType, string> unlistedSelectedItemLabelGetter = null, string defaultValueItemLabel = "", bool placeholderIsValid = false, string placeholderText = "Please select", FormAction action = null, bool autoPostBack = false, PageModificationValue <ItemIdType> itemIdPageModificationValue = null, IEnumerable <ListItemMatchPageModificationSetup <ItemIdType> > itemMatchPageModificationSetups = null) { return(new SelectList <ItemIdType>( null, width, unlistedSelectedItemLabelGetter, defaultValueItemLabel, placeholderIsValid, placeholderText, items, null, selectedItemId, action, autoPostBack, itemIdPageModificationValue, itemMatchPageModificationSetups ?? ImmutableArray <ListItemMatchPageModificationSetup <ItemIdType> > .Empty)); }
private FlowComponent getComponent( DisplaySetup displaySetup, ElementClassSet classes, PageModificationValue <bool> pageModificationValue, Checkbox checkbox, bool highlightedWhenChecked, Func <IReadOnlyCollection <FlowComponent> > nestedContentGetter, bool nestedContentAlwaysDisplayed) { var nestedContent = nestedContentGetter?.Invoke() ?? Enumerable.Empty <FlowComponent>().Materialize(); return(new GenericFlowContainer( checkbox.PageComponent.ToCollection() .Concat( nestedContent.Any() ? new GenericFlowContainer( nestedContent, displaySetup: nestedContentAlwaysDisplayed?null: pageModificationValue.ToCondition().ToDisplaySetup(), classes: nestedContentClass).ToCollection() : Enumerable.Empty <FlowComponent>()) .Materialize(), displaySetup: displaySetup, classes: (highlightedWhenChecked ? pageModificationValue.ToCondition(isTrueWhenValueSet: false) .ToElementClassSet(unhighlightedClass) .Add(pageModificationValue.ToCondition().ToElementClassSet(highlightedClass)) : unhighlightedClass).Add(classes ?? ElementClassSet.Empty))); }
/// <summary> /// Creates a display setup object for display that depends on this page-modification value. /// </summary> public static DisplaySetup ToDisplaySetup <T>( this PageModificationValue <T> pageModificationValue, IEnumerable <T> values, bool componentsDisplayedOnMatch = true) { values = values.ToImmutableArray(); return (new DisplaySetup( Tuple.Create <Action <string>, Action <string> >( statements => pageModificationValue.AddJsModificationStatement( valueExpression => "if( [ {0} ].indexOf( {1} ) {2} -1 )".FormatWith( StringTools.ConcatenateWithDelimiter(", ", values.Select(i => "'" + i.ObjectToString(true) + "'").ToArray()), valueExpression, componentsDisplayedOnMatch ? "!=" : "==") + " { " + statements + " }"), statements => pageModificationValue.AddJsModificationStatement( valueExpression => "if( [ {0} ].indexOf( {1} ) {2} -1 )".FormatWith( StringTools.ConcatenateWithDelimiter(", ", values.Select(i => "'" + i.ObjectToString(true) + "'").ToArray()), valueExpression, componentsDisplayedOnMatch ? "==" : "!=") + " { " + statements + " }")), () => values.Contains(pageModificationValue.Value) ^ !componentsDisplayedOnMatch)); }
/// <summary> /// Creates a setup object for a standard URL control. /// </summary> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control.</param> /// <param name="placeholder">The hint word or phrase that will appear when the control has an empty value. Do not pass null.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static UrlControlSetup Create( DisplaySetup displaySetup = null, ElementClassSet classes = null, string placeholder = "", string autoFillTokens = "", SpecifiedValue <FormAction> action = null, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new UrlControlSetup( new TextControlSetup( displaySetup, "url", null, null, false, classes, false, false, placeholder, autoFillTokens, null, null, action, null, valueChangedAction, pageModificationValue, null, validationPredicate, validationErrorNotifier))); }
/// <summary> /// Creates a setup object for a standard date-and-time control. /// </summary> /// <param name="displaySetup"></param> /// <param name="classes">The classes on the control.</param> /// <param name="autoFillTokens">A list of auto-fill detail tokens (see /// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens), or "off" to instruct the browser to disable auto-fill /// (see https://stackoverflow.com/a/23234498/35349 for an explanation of why this could be ignored). Do not pass null.</param> /// <param name="minuteInterval">Affects the slider but does not prevent other values from passing validation.</param> /// <param name="action">The action that will occur when the user hits Enter on the control. Pass null to use the current default action.</param> /// <param name="valueChangedAction">The action that will occur when the value is changed. Pass null for no action.</param> /// <param name="pageModificationValue"></param> /// <param name="validationPredicate"></param> /// <param name="validationErrorNotifier"></param> public static DateAndTimeControlSetup Create( DisplaySetup displaySetup = null, ElementClassSet classes = null, string autoFillTokens = "", int minuteInterval = 15, SpecifiedValue <FormAction> action = null, FormAction valueChangedAction = null, PageModificationValue <string> pageModificationValue = null, Func <bool, bool> validationPredicate = null, Action validationErrorNotifier = null) { return(new DateAndTimeControlSetup( displaySetup, false, classes, autoFillTokens, minuteInterval, action, valueChangedAction, pageModificationValue, validationPredicate, validationErrorNotifier)); }
private PhrasingComponent getComponent( FormValue formValue, ElementId id, string radioButtonListItemId, DisplaySetup displaySetup, bool isReadOnly, ElementClassSet classes, PageModificationValue <bool> pageModificationValue, IReadOnlyCollection <PhrasingComponent> label, FormAction action, FormAction valueChangedAction, Func <string> jsClickStatementGetter) { return(new CustomPhrasingComponent( new DisplayableElement( labelContext => new DisplayableElementData( displaySetup, () => new DisplayableElementLocalData("label"), classes: elementClass.Add(classes ?? ElementClassSet.Empty), children: new DisplayableElement( context => { if (!isReadOnly) { action?.AddToPageIfNecessary(); valueChangedAction?.AddToPageIfNecessary(); } return new DisplayableElementData( null, () => { var attributes = new List <ElementAttribute>(); var radioButtonFormValue = formValue as FormValue <ElementId>; attributes.Add(new ElementAttribute("type", radioButtonFormValue != null ? "radio" : "checkbox")); if (radioButtonFormValue != null || !isReadOnly) { attributes.Add( new ElementAttribute( "name", radioButtonFormValue != null ? ((FormValue)radioButtonFormValue).GetPostBackValueKey() : context.Id)); } if (radioButtonFormValue != null) { attributes.Add(new ElementAttribute("value", radioButtonListItemId ?? context.Id)); } if (pageModificationValue.Value) { attributes.Add(new ElementAttribute("checked")); } if (isReadOnly) { attributes.Add(new ElementAttribute("disabled")); } var jsInitStatements = StringTools.ConcatenateWithDelimiter( " ", !isReadOnly ? SubmitButton.GetImplicitSubmissionKeyPressStatements(action, false) .Surround("$( '#{0}' ).keypress( function( e ) {{ ".FormatWith(context.Id), " } );") : "", jsClickStatementGetter().Surround("$( '#{0}' ).click( function() {{ ".FormatWith(context.Id), " } );")); return new DisplayableElementLocalData( "input", new FocusabilityCondition(!isReadOnly), isFocused => { if (isFocused) { attributes.Add(new ElementAttribute("autofocus")); } return new DisplayableElementFocusDependentData( attributes: attributes, includeIdAttribute: true, jsInitStatements: jsInitStatements); }); }, classes: elementClass, clientSideIdReferences: id.ToCollection()); }, formValue: formValue).ToCollection() .Concat(label.Any() ? new GenericPhrasingContainer(label, classes: elementClass).ToCollection() : Enumerable.Empty <FlowComponent>()) .Materialize())).ToCollection())); }
/// <summary> /// Creates a simple HTML editor. /// </summary> /// <param name="value">Do not pass null.</param> /// <param name="allowEmpty"></param> /// <param name="validationMethod">The validation method. Do not pass null.</param> /// <param name="setup">The setup object for the HTML editor.</param> /// <param name="maxLength"></param> public WysiwygHtmlEditor( string value, bool allowEmpty, Action <string, Validator> validationMethod, WysiwygHtmlEditorSetup setup = null, int?maxLength = null) { setup = setup ?? new WysiwygHtmlEditorSetup(); var id = new ElementId(); FormValue <string> formValue = null; formValue = new FormValue <string>( () => value, () => setup.IsReadOnly ? "" : id.Id, v => v, rawValue => { if (rawValue == null) { return(PostBackValueValidationResult <string> .CreateInvalid()); } // This hack prevents the NewLine that CKEditor seems to always add to the end of the textarea from causing // ValueChangedOnPostBack to always return true. if (rawValue.EndsWith(Environment.NewLine) && rawValue.Remove(rawValue.Length - Environment.NewLine.Length) == formValue.GetDurableValue()) { rawValue = formValue.GetDurableValue(); } return(PostBackValueValidationResult <string> .CreateValid(rawValue)); }); var modificationValue = new PageModificationValue <string>(); component = new ElementComponent( context => { id.AddId(context.Id); var displaySetup = setup.DisplaySetup ?? new DisplaySetup(true); var jsShowStatements = getJsShowStatements(context.Id, setup.CkEditorConfiguration); displaySetup.AddJsShowStatements(jsShowStatements); displaySetup.AddJsHideStatements("CKEDITOR.instances.{0}.destroy(); $( '#{0}' ).css( 'display', 'none' );".FormatWith(context.Id)); return(new ElementData( () => { var attributes = new List <Tuple <string, string> >(); if (setup.IsReadOnly) { attributes.Add(Tuple.Create("disabled", "disabled")); } else { attributes.Add(Tuple.Create("name", context.Id)); } if (!displaySetup.ComponentsDisplayed) { attributes.Add(Tuple.Create("style", "display: none")); } return new ElementLocalData( "textarea", attributes: attributes, includeIdAttribute: true, jsInitStatements: displaySetup.ComponentsDisplayed ? jsShowStatements : ""); }, children: new TextNode(() => EwfTextBox.GetTextareaValue(modificationValue.Value)).ToCollection())); }, formValue: formValue); validation = formValue.CreateValidation( (postBackValue, validator) => { if (setup.ValidationPredicate != null && !setup.ValidationPredicate(postBackValue.ChangedOnPostBack)) { return; } var errorHandler = new ValidationErrorHandler("HTML"); var validatedValue = maxLength.HasValue ? validator.GetString(errorHandler, postBackValue.Value, allowEmpty, maxLength.Value) : validator.GetString(errorHandler, postBackValue.Value, allowEmpty); if (errorHandler.LastResult != ErrorCondition.NoError) { setup.ValidationErrorNotifier(); return; } validationMethod(validatedValue, validator); }); formValue.AddPageModificationValue(modificationValue, v => v); }
/// <summary> /// Creates an in-line radio button that is part of the group. /// </summary> public EwfCheckBox CreateInlineRadioButton( bool isSelected, string label = "", FormAction action = null, bool autoPostBack = false, PageModificationValue <bool> pageModificationValue = null) { EwfCheckBox checkBox = null; checkBox = new EwfCheckBox( formValue, label, action, () => checkBoxesAndSelectionStatesAndPageModificationValues.Where(i => i.Item3 != null) .Select(i => i.Item3.GetJsModificationStatements(i.Item1 == checkBox ? "true" : "false"))) { AutoPostBack = autoPostBack }; checkBoxesAndSelectionStatesAndPageModificationValues.Add( Tuple.Create <CommonCheckBox, bool, PageModificationValue <bool> >(checkBox, isSelected, pageModificationValue)); if (pageModificationValue != null) { formValue.AddPageModificationValue(pageModificationValue, value => value == checkBox); } return(checkBox); }