Beispiel #1
0
        /// <summary>
        /// Creates a duration control.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="allowEmpty"></param>
        /// <param name="setup">The setup object for the duration control.</param>
        /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param>
        public DurationControl(TimeSpan?value, bool allowEmpty, DurationControlSetup setup = null, Action <TimeSpan?, Validator> validationMethod = null)
        {
            setup = setup ?? DurationControlSetup.Create();

            var textControl = new TextControl(
                value.HasValue ? Math.Floor(value.Value.TotalHours).ToString("0000") + ":" + value.Value.Minutes.ToString("00") : "",
                allowEmpty,
                setup: setup.IsReadOnly
                                               ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier)
                                               : TextControlSetup.Create(
                    placeholder: "h:m",
                    action: new SpecifiedValue <FormAction>(setup.Action),
                    valueChangedAction: setup.ValueChangedAction,
                    pageModificationValue: setup.PageModificationValue,
                    validationPredicate: setup.ValidationPredicate,
                    validationErrorNotifier: setup.ValidationErrorNotifier),
                validationMethod: validationMethod == null
                                                          ? (Action <string, Validator>)null
                                                          : (postBackValue, validator) => {
                if (tooLongOrInvalidCharacters(postBackValue))
                {
                    validator.NoteErrorAndAddMessage("Please enter a valid duration.");
                    setup.ValidationErrorNotifier?.Invoke();
                    return;
                }

                var errorHandler   = new ValidationErrorHandler("duration");
                var validatedValue = validator.GetNullableTimeSpan(errorHandler, parseTimeSpan(postBackValue), allowEmpty);
                if (errorHandler.LastResult != ErrorCondition.NoError)
                {
                    setup.ValidationErrorNotifier?.Invoke();
                    return;
                }

                validationMethod(validatedValue, validator);
            });

            Labeler = textControl.Labeler;

            PageComponent = new CustomPhrasingComponent(
                new DisplayableElement(
                    context => new DisplayableElementData(
                        setup.DisplaySetup,
                        () => new DisplayableElementLocalData(
                            "span",
                            focusDependentData: new DisplayableElementFocusDependentData(
                                includeIdAttribute: true,
                                jsInitStatements:
                                "{0}.blur( function() {{ {1} }} ).keypress( function( e ) {{ {2} }} ).focus( function() {{ {3} }} ).mouseup( function( e ) {{ {4} }} );"
                                .FormatWith(
                                    getTextControlExpression(context.Id),
                                    "ApplyTimeSpanFormat( this );",
                                    "if( !NumericalOnly( e, this ) ) e.preventDefault();",
                                    "this.value = this.value.replace( ':', '' ); this.select();",
                                    "e.preventDefault();"))),
                        classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty),
                        children: textControl.PageComponent.ToCollection())).ToCollection());

            Validation = textControl.Validation;
        }
 /// <summary>
 /// Creates an HTML block container. Do not pass null for HTML. This overload is useful when you've already loaded the HTML.
 /// </summary>
 /// <param name="html"></param>
 /// <param name="displaySetup"></param>
 /// <param name="classes">The classes on the container.</param>
 public HtmlBlockContainer(string html, DisplaySetup displaySetup = null, ElementClassSet classes = null)
 {
     this.html = html;
     children  = new DisplayableElement(
         context => new DisplayableElementData(
             displaySetup,
             () => new DisplayableElementLocalData("div"),
             classes: elementClass.Add(classes ?? ElementClassSet.Empty),
             children: new TrustedHtmlString(html).ToComponent().ToCollection())).ToCollection();
 }
Beispiel #3
0
        /// <summary>
        /// Creates a list error-display style.
        /// </summary>
        /// <param name="classes">The classes on the list container.</param>
        public ListErrorDisplayStyle(ElementClassSet classes = null)
        {
            componentGetter = (errorSources, errors, componentsFocusableOnError) => {
                if (!errors.Any())
                {
                    return(Enumerable.Empty <FlowComponent>().Materialize());
                }

                return(new DisplayableElement(
                           context => new DisplayableElementData(
                               null,
                               () => GetErrorFocusableElementLocalData(context, "div", componentsFocusableOnError ? errorSources : null, null),
                               classes: containerClass.Add(classes ?? ElementClassSet.Empty),
                               children: new StackList(
                                   from i in errors
                                   select new FontAwesomeIcon("fa-times-circle", "fa-lg").ToCollection <PhrasingComponent>()
                                   .Concat(" ".ToComponents())
                                   .Append(i.ToComponent())
                                   .Materialize()
                                   .ToComponentListItem()).ToCollection())).ToCollection());
            };
        }
        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()));
        }
Beispiel #5
0
        /// <summary>
        /// Creates a date-and-time control.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="allowEmpty"></param>
        /// <param name="setup">The setup object for the date-and-time control.</param>
        /// <param name="minValue">The earliest acceptable date.</param>
        /// <param name="maxValue">The latest acceptable date.</param>
        /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param>
        public DateAndTimeControl(
            LocalDateTime?value, bool allowEmpty, DateAndTimeControlSetup setup = null, LocalDate?minValue = null, LocalDate?maxValue = null,
            Action <LocalDateTime?, Validator> validationMethod = null)
        {
            setup = setup ?? DateAndTimeControlSetup.Create();

            var textControl = new TextControl(
                value.HasValue ? value.Value.ToDateTimeUnspecified().ToMonthDayYearString() + " " + value.Value.ToDateTimeUnspecified().ToHourAndMinuteString() : "",
                allowEmpty,
                setup: setup.IsReadOnly
                                               ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier)
                                               : TextControlSetup.Create(
                    autoFillTokens: setup.AutoFillTokens,
                    action: new SpecifiedValue <FormAction>(setup.Action),
                    valueChangedAction: setup.ValueChangedAction,
                    pageModificationValue: setup.PageModificationValue,
                    validationPredicate: setup.ValidationPredicate,
                    validationErrorNotifier: setup.ValidationErrorNotifier),
                validationMethod: validationMethod == null
                                                          ? (Action <string, Validator>)null
                                                          : (postBackValue, validator) => {
                var errorHandler   = new ValidationErrorHandler("date and time");
                var validatedValue = validator.GetNullableDateTime(
                    errorHandler,
                    postBackValue.ToUpper(),
                    TewlContrib.DateTimeTools.MonthDayYearFormats.Select(i => i + " " + TewlContrib.DateTimeTools.HourAndMinuteFormat).ToArray(),
                    allowEmpty,
                    minValue?.ToDateTimeUnspecified() ?? DateTime.MinValue,
                    maxValue?.PlusDays(1).ToDateTimeUnspecified() ?? DateTime.MaxValue);
                if (errorHandler.LastResult != ErrorCondition.NoError)
                {
                    setup.ValidationErrorNotifier?.Invoke();
                    return;
                }

                validationMethod(
                    validatedValue.HasValue ? (LocalDateTime?)LocalDateTime.FromDateTime(validatedValue.Value) : null,
                    validator);
            });

            Labeler = textControl.Labeler;

            PageComponent = new CustomPhrasingComponent(
                new DisplayableElement(
                    context => new DisplayableElementData(
                        setup.DisplaySetup,
                        () => new DisplayableElementLocalData(
                            "span",
                            focusDependentData: new DisplayableElementFocusDependentData(
                                includeIdAttribute: true,
                                jsInitStatements: "{0}.datetimepicker( {{ {1} }} );".FormatWith(
                                    getTextControlExpression(context.Id),
                                    StringTools.ConcatenateWithDelimiter(
                                        ", ",
                                        minValue.HasValue
                                                                                        ? "minDate: {0}".FormatWith("new Date( {0}, {1} - 1, {2} )".FormatWith(minValue.Value.Year, minValue.Value.Month, minValue.Value.Day))
                                                                                        : "",
                                        maxValue.HasValue
                                                                                        ? "maxDate: {0}".FormatWith("new Date( {0}, {1} - 1, {2} )".FormatWith(maxValue.Value.Year, maxValue.Value.Month, maxValue.Value.Day))
                                                                                        : "",
                                        "timeFormat: 'h:mmt'",
                                        "stepMinute: {0}".FormatWith(setup.MinuteInterval.Value))))),
                        classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty),
                        children: textControl.PageComponent.ToCollection()
                        .Concat(
                            setup.IsReadOnly
                                                                        ? Enumerable.Empty <PhrasingComponent>()
                                                                        : new EwfButton(
                                new CustomButtonStyle(
                                    children: new GenericPhrasingContainer(
                                        new FontAwesomeIcon("fa-calendar-o", "fa-stack-2x").ToCollection()
                                        .Append(new FontAwesomeIcon("fa-clock-o", "fa-stack-1x"))
                                        .Materialize(),
                                        classes: new ElementClass("fa-stack")).ToCollection()),
                                behavior: new CustomButtonBehavior(() => "{0}.datetimepicker( 'show' );".FormatWith(getTextControlExpression(context.Id))),
                                classes: new ElementClass("icon")).ToCollection())
                        .Materialize())).ToCollection());

            Validation = textControl.Validation;
        }
Beispiel #6
0
        /// <summary>
        /// BasicPage.master use only.
        /// </summary>
        public Section(
            DisplaySetup displaySetup, SectionStyle style, ElementClassSet classes, string heading, IReadOnlyCollection <FlowComponent> postHeadingComponents,
            IReadOnlyCollection <FlowComponent> content, bool?expanded, bool disableStatePersistence, IReadOnlyCollection <EtherealComponent> etherealContent)
        {
            children = new DisplayableElement(
                context => {
                var hiddenFieldId = new HiddenFieldId();
                var expandedPmv   = heading.Any() && expanded.HasValue && !disableStatePersistence ? new PageModificationValue <string>() : null;

                FlowComponent getHeadingButton()
                {
                    var headingComponents =
                        new DisplayableElement(
                            headingContext => new DisplayableElementData(
                                null,
                                () => new DisplayableElementLocalData("h1"),
                                classes: headingClass,
                                children: heading.ToComponents())).Concat(postHeadingComponents ?? Enumerable.Empty <FlowComponent>());

                    return(expanded.HasValue
                                                               ?
                           // We cannot use EwfButton because we have flow content.
                           ElementActivationBehavior.GetActivatableElement(
                               "div",
                               ElementClassSet.Empty,
                               Enumerable.Empty <Tuple <string, string> >().Materialize(),
                               ElementActivationBehavior.CreateButton(
                                   buttonBehavior: new CustomButtonBehavior(
                                       () => disableStatePersistence
                                                                                                     ? "$( '#{0}' ).toggleClass( '{1}', 200 );".FormatWith(
                                           context.Id,
                                           StringTools.ConcatenateWithDelimiter(
                                               " ",
                                               style == SectionStyle.Normal
                                                                                                                             ? new[] { normalClosedClass.ClassName, normalExpandedClass.ClassName }
                                                                                                                             : new[] { boxClosedClass.ClassName, boxExpandedClass.ClassName }))
                                                                                                     : hiddenFieldId.GetJsValueModificationStatements(
                                           "document.getElementById( '{0}' ).value === '{2}' ? '{1}' : '{2}'".FormatWith(
                                               hiddenFieldId.ElementId.Id,
                                               bool.FalseString,
                                               bool.TrueString)))),
                               new GenericFlowContainer(
                                   new GenericPhrasingContainer("Click to Expand".ToComponents(), classes: closeClass).ToCollection()
                                   .Append(new GenericPhrasingContainer("Click to Close".ToComponents(), classes: expandClass))
                                   .Concat(headingComponents)
                                   .Materialize(),
                                   classes: headingClass).ToCollection(),
                               Enumerable.Empty <EtherealComponent>().Materialize())
                                                               : new GenericFlowContainer(new GenericFlowContainer(headingComponents.Materialize(), classes: headingClass).ToCollection()));
                }

                content = content ?? Enumerable.Empty <FlowComponent>().Materialize();
                return(new DisplayableElementData(
                           displaySetup,
                           () => new DisplayableElementLocalData(
                               "section",
                               focusDependentData:
                               new DisplayableElementFocusDependentData(includeIdAttribute: heading.Any() && expanded.HasValue && disableStatePersistence)),
                           classes: allStylesBothStatesClass
                           .Add(
                               style == SectionStyle.Normal
                                                                        ? getSectionClasses(expanded, expandedPmv, normalClosedClass, normalExpandedClass)
                                                                        : getSectionClasses(expanded, expandedPmv, boxClosedClass, boxExpandedClass))
                           .Add(classes ?? ElementClassSet.Empty),
                           children: (heading.Any() ? getHeadingButton().ToCollection() : Enumerable.Empty <FlowComponent>()).Concat(
                               content.Any() ? new GenericFlowContainer(content, classes: contentClass).ToCollection() : Enumerable.Empty <FlowComponent>())
                           .Materialize(),
                           etherealChildren: (expandedPmv != null
                                                                            ? new EwfHiddenField(expanded.Value.ToString(), id: hiddenFieldId, pageModificationValue: expandedPmv).PageComponent
                                              .ToCollection()
                                                                            : Enumerable.Empty <EtherealComponent>()).Concat(etherealContent ?? Enumerable.Empty <EtherealComponent>())
                           .Materialize()));
            }).ToCollection();
        }
        /// <summary>
        /// Creates a time control.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="allowEmpty"></param>
        /// <param name="setup">The setup object for the time control.</param>
        /// <param name="minValue">The earliest allowed time.</param>
        /// <param name="maxValue">The latest allowed time. This can be earlier than <paramref name="minValue"/> to create a range spanning midnight.</param>
        /// <param name="minuteInterval">Allows the user to select values only in the given increments. Be aware that other values can still be sent from the
        /// browser via a crafted request.</param>
        /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param>
        public TimeControl(
            LocalTime?value, bool allowEmpty, TimeControlSetup setup = null, LocalTime?minValue = null, LocalTime?maxValue = null, int minuteInterval = 15,
            Action <LocalTime?, Validator> validationMethod          = null)
        {
            setup    = setup ?? TimeControlSetup.Create();
            minValue = minValue ?? LocalTime.Midnight;

            if (minuteInterval < 30)
            {
                var textControl = new TextControl(
                    value.HasValue ? new TimeSpan(value.Value.TickOfDay).ToTimeOfDayHourAndMinuteString() : "",
                    allowEmpty,
                    setup: setup.IsReadOnly
                                                       ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier)
                                                       : TextControlSetup.Create(
                        autoFillTokens: setup.AutoFillTokens,
                        action: new SpecifiedValue <FormAction>(setup.Action),
                        valueChangedAction: setup.ValueChangedAction,
                        pageModificationValue: setup.PageModificationValue,
                        validationPredicate: setup.ValidationPredicate,
                        validationErrorNotifier: setup.ValidationErrorNotifier),
                    validationMethod: validationMethod == null
                                                                  ? (Action <string, Validator>)null
                                                                  : (postBackValue, validator) => {
                    var errorHandler   = new ValidationErrorHandler("time");
                    var validatedValue = validator.GetNullableTimeOfDayTimeSpan(
                        errorHandler,
                        postBackValue.ToUpper(),
                        TewlContrib.DateTimeTools.HourAndMinuteFormat.ToCollection().ToArray(),
                        allowEmpty)
                                         .ToNewUnderlyingValue(v => LocalTime.FromTicksSinceMidnight(v.Ticks));
                    if (errorHandler.LastResult != ErrorCondition.NoError)
                    {
                        setup.ValidationErrorNotifier?.Invoke();
                        return;
                    }

                    var wrap = maxValue < minValue.Value;
                    if (!wrap
                                                                                      ? validatedValue < minValue.Value || validatedValue > maxValue
                                                                                      : validatedValue < minValue.Value && validatedValue > maxValue)
                    {
                        validator.NoteErrorAndAddMessage("The time is too early or too late.");
                        setup.ValidationErrorNotifier?.Invoke();
                        return;
                    }

                    validationMethod(validatedValue, validator);
                });

                Labeler = textControl.Labeler;

                PageComponent = new DisplayableElement(
                    context => new DisplayableElementData(
                        setup.DisplaySetup,
                        () => new DisplayableElementLocalData(
                            "div",
                            focusDependentData: new DisplayableElementFocusDependentData(
                                includeIdAttribute: true,
                                jsInitStatements: "{0}.timepicker( {{ {1} }} );".FormatWith(
                                    getTextControlExpression(context.Id),
                                    StringTools.ConcatenateWithDelimiter(
                                        ", ",
                                        "timeFormat: 'h:mmt'",
                                        "stepMinute: {0}".FormatWith(minuteInterval),
                                        "showButtonPanel: false")))),
                        classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty),
                        children: textControl.PageComponent.ToCollection()
                        .Concat(
                            setup.IsReadOnly
                                                                        ? Enumerable.Empty <PhrasingComponent>()
                                                                        : new EwfButton(
                                new CustomButtonStyle(children: new FontAwesomeIcon("fa-clock-o").ToCollection()),
                                behavior: new CustomButtonBehavior(() => "{0}.timepicker( 'show' );".FormatWith(getTextControlExpression(context.Id))),
                                classes: new ElementClass("icon")).ToCollection())
                        .Materialize()));

                Validation = textControl.Validation;
            }
            else
            {
                var items = from time in getTimes(minValue.Value, maxValue, minuteInterval)
                            let timeSpan = new TimeSpan(time.TickOfDay)
                                           select SelectListItem.Create <LocalTime?>(time, timeSpan.ToTimeOfDayHourAndMinuteString());

                var selectList = SelectList.CreateDropDown(
                    setup.IsReadOnly
                                                ? DropDownSetup.CreateReadOnly(
                        items,
                        placeholderText: "",
                        validationPredicate: setup.ValidationPredicate,
                        validationErrorNotifier: setup.ValidationErrorNotifier)
                                                : DropDownSetup.Create(
                        items,
                        placeholderText: "",
                        autoFillTokens: setup.AutoFillTokens,
                        action: new SpecifiedValue <FormAction>(setup.Action),
                        selectionChangedAction: setup.ValueChangedAction,
                        validationPredicate: setup.ValidationPredicate,
                        validationErrorNotifier: setup.ValidationErrorNotifier),
                    value,
                    placeholderIsValid: allowEmpty,
                    validationMethod: validationMethod);

                Labeler = selectList.Labeler;

                PageComponent = new GenericFlowContainer(
                    selectList.PageComponent.ToCollection(),
                    displaySetup: setup.DisplaySetup,
                    classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty));

                Validation = selectList.Validation;
            }
        }