/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(object model) { YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, FieldType.Normal); tag.MergeAttribute("name", FieldNamePrefix, true); tag.MergeAttribute("type", "hidden"); tag.MergeAttribute("value", model == null ? "" : model.ToString()); return(Task.FromResult(tag.ToString(YTagRenderMode.StartTag))); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(Guid?model) { HtmlBuilder hb = new HtmlBuilder(); // dropdown List <SelectionItem <string> > list; list = ( from p in await PageDefinition.GetDesignedPagesAsync() orderby p.Url select new SelectionItem <string> { Text = p.Url, Value = p.PageGuid.ToString(), }).ToList <SelectionItem <string> >(); list.Insert(0, new SelectionItem <string> { Text = __ResStr("select", "(select)"), Value = null }); string ddList = await DropDownListComponent.RenderDropDownListAsync(this, (model ?? Guid.Empty).ToString(), list, null); // link YTagBuilder tag = new YTagBuilder("a"); PageDefinition page = null; if (model != null) { page = await PageDefinition.LoadAsync((Guid)model); } tag.MergeAttribute("href", (page != null ? page.EvaluatedCanonicalUrl : "")); tag.MergeAttribute("target", "_blank"); tag.MergeAttribute("rel", "nofollow noopener noreferrer"); tag.Attributes.Add(Basics.CssTooltip, __ResStr("linkTT", "Click to preview the page in a new window - not all pages can be displayed correctly and may require additional parameters")); tag.InnerHtml = tag.InnerHtml + ImageHTML.BuildKnownIcon("#PagePreview", sprites: Info.PredefSpriteIcons); string linkTag = tag.ToString(YTagRenderMode.Normal); hb.Append($@" <div id='{DivId}' class='yt_pageselection t_edit'> <div class='t_select'> {ddList.ToString()} </div> <div class='t_link'> {linkTag} </div> <div class='t_description'> </div> </div>"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.PageSelectionEditComponent('{DivId}');"); return(hb.ToString()); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(TimeOfDay model) { // we're reusing Time component await Manager.AddOnManager.AddTemplateFromUIHintAsync("Time"); HtmlBuilder hb = new HtmlBuilder(); hb.Append($"<div id='{ControlId}' class='yt_time t_edit'>"); Dictionary <string, object> hiddenAttributes = new Dictionary <string, object>(HtmlAttributes) { { "__NoTemplate", true } }; hb.Append(await HtmlHelper.ForEditComponentAsync(Container, PropertyName, null, "Hidden", HtmlAttributes: hiddenAttributes, Validation: Validation)); YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, FieldType.Anonymous); tag.Attributes.Add("name", "dtpicker"); if (model != null) { DateTime dt = model.AsDateTime(); tag.MergeAttribute("value", Formatting.FormatTime(dt)); } hb.Append(tag.ToString(YTagRenderMode.StartTag)); hb.Append($"</div>"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.TimeEditComponent('{ControlId}');"); return(hb.ToString()); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(string model) { HtmlBuilder sb = new HtmlBuilder(); YTagBuilder tagLabel = new YTagBuilder("label"); FieldSetup(tagLabel, FieldType.Anonymous); if (string.IsNullOrEmpty(model)) // we're distinguishing between "" and " " { tagLabel.InnerHtml = " "; } else { tagLabel.SetInnerText(model); } sb.Append(tagLabel.ToString(YTagRenderMode.Normal)); string helpLink; if (TryGetSiblingProperty <string>($"{PropertyName}_HelpLink", out helpLink) && !string.IsNullOrWhiteSpace(helpLink)) { YTagBuilder tagA = new YTagBuilder("a"); tagA.Attributes.Add("href", Utility.UrlEncodePath(helpLink)); tagA.Attributes.Add("target", "_blank"); tagA.MergeAttribute("rel", "noopener noreferrer"); tagA.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule("yt_extlabel_img")); tagA.InnerHtml = ImageHTML.BuildKnownIcon("#Help"); sb.Append(tagA.ToString(YTagRenderMode.Normal)); } return(Task.FromResult(sb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(string model) { UseSuppliedIdAsControlId(); HtmlBuilder hb = new HtmlBuilder(); hb.Append($"<div id='{ControlId}' class='yt_ssn t_edit'>"); Dictionary <string, object> hiddenAttributes = new Dictionary <string, object>(HtmlAttributes) { { "__NoTemplate", true } }; hb.Append(await HtmlHelper.ForEditComponentAsync(Container, PropertyName, null, "Hidden", HtmlAttributes: hiddenAttributes, Validation: Validation)); YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, FieldType.Anonymous); tag.Attributes.Add("name", "ssninput"); if (model != null) { tag.MergeAttribute("value", model); } hb.Append(tag.ToString(YTagRenderMode.StartTag)); hb.Append($"</div>"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.SSNEditComponent('{ControlId}');"); return(hb.ToString()); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(Decimal?model) { HtmlBuilder hb = new HtmlBuilder(); YTagBuilder tag = new YTagBuilder("input"); tag.AddCssClass("yt_decimal"); tag.AddCssClass("t_edit"); FieldSetup(tag, Validation ? FieldType.Validated : FieldType.Normal); string id = MakeId(tag); // handle min/max float min = 0, max = 99999999.99F; RangeAttribute rangeAttr = PropData.TryGetAttribute <RangeAttribute>(); if (rangeAttr != null) { min = Convert.ToSingle(rangeAttr.Minimum); max = Convert.ToSingle(rangeAttr.Maximum); } string format = PropData.GetAdditionalAttributeValue("Format", "0.00"); if (model != null) { tag.MergeAttribute("value", ((decimal)model).ToString(format)); } hb.Append($@" {tag.ToString(YTagRenderMode.StartTag)}"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.DecimalEditComponent('{id}', {{ Min: {min}, Max: {max} }});"); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(object model) { string text; if (model is MultiString) { text = (MultiString)model; } else { text = (string)model; } int emHeight = PropData.GetAdditionalAttributeValue("EmHeight", 10); HtmlBuilder hb = new HtmlBuilder(); YTagBuilder tag = new YTagBuilder("textarea"); tag.AddCssClass("yt_textareasourceonly"); tag.AddCssClass("t_edit"); tag.AddCssClass("k-textbox"); // USE KENDO style FieldSetup(tag, Validation ? FieldType.Validated : FieldType.Normal); tag.Attributes.Add("id", ControlId); tag.Attributes.Add("rows", emHeight.ToString()); // handle StringLengthAttribute as maxlength StringLengthAttribute lenAttr = PropData.TryGetAttribute <StringLengthAttribute>(); if (lenAttr != null) { #if DEBUG if (tag.Attributes.ContainsKey("maxlength")) { throw new InternalError($"Both StringLengthAttribute and maxlength specified - {FieldName}"); } #endif int maxLength = lenAttr.MaximumLength; if (maxLength > 0 && maxLength <= 8000) { tag.MergeAttribute("maxlength", maxLength.ToString()); } } #if DEBUG if (lenAttr == null && !tag.Attributes.ContainsKey("maxlength")) { throw new InternalError($"No max string length given using StringLengthAttribute or maxlength - {FieldName}"); } #endif tag.SetInnerText(text); hb.Append(tag.ToString(YTagRenderMode.Normal)); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.TextAreaSourceOnlyEditComponent('{ControlId}');"); return(Task.FromResult(hb.ToString())); }
internal string GetModuleLink(Guid?model, bool force = false) { if (!force) { if (model == null || model == Guid.Empty) { return(""); } } YTagBuilder tag = new YTagBuilder("a"); tag.MergeAttribute("href", ModuleDefinition.GetModulePermanentUrl(model ?? Guid.Empty)); tag.MergeAttribute("target", "_blank"); tag.MergeAttribute("rel", "nofollow noopener noreferrer"); tag.Attributes.Add(Basics.CssTooltip, __ResStr("linkTT", "Click to preview the module in a new window - not all modules can be displayed correctly and may require additional parameters")); tag.InnerHtml = tag.InnerHtml + ImageHTML.BuildKnownIcon("#ModulePreview", sprites: Info.PredefSpriteIcons); return(tag.ToString(YTagRenderMode.Normal)); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(string model) { HtmlBuilder hb = new HtmlBuilder(); bool copy = PropData.GetAdditionalAttributeValue <bool>("Copy", true); bool rdonly = PropData.GetAdditionalAttributeValue <bool>("ReadOnly", false); YTagBuilder tag = new YTagBuilder("input"); tag.AddCssClass(TemplateClass); // adding k-textbox to the control makes it look like a kendo maskedtext box without the overhead of actually calling kendoMaskedTextBox tag.AddCssClass("k-textbox"); tag.AddCssClass("t_display"); tag.AddCssClass("k-state-disabled"); // USE KENDO style FieldSetup(tag, FieldType.Anonymous); tag.MergeAttribute("type", "text"); tag.MergeAttribute("value", model ?? ""); if (copy || rdonly) { tag.MergeAttribute("readonly", "readonly"); } else { tag.MergeAttribute("disabled", "disabled"); } hb.Append(tag.ToString(YTagRenderMode.StartTag)); if (copy) { await Manager.AddOnManager.AddAddOnNamedAsync(Package.AreaName, "clipboardjs.com.clipboard");// add clipboard support hb.Append(ImageHTML.BuildKnownIcon("#TextCopy", sprites: Info.PredefSpriteIcons, title: __ResStr("ttCopy", "Copy to Clipboard"), cssClass: "yt_text_copy")); } //Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.TextDisplayComponent('{ControlId}');"); return(hb.ToString()); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(object model) { YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, FieldType.Normal); tag.MergeAttribute("type", "hidden"); if (HtmlAttributes.ContainsKey("--NoTemplate")) { HtmlAttributes.Remove("--NoTemplate"); } else if (HtmlAttributes.ContainsKey("__NoTemplate")) { HtmlAttributes.Remove("__NoTemplate"); } else { tag.AddCssClass("yt_hidden"); } if (model != null && model.GetType().IsEnum) { model = (int)model; } tag.MergeAttribute("value", model == null ? "" : model.ToString()); StringLengthAttribute lenAttr = PropData.TryGetAttribute <StringLengthAttribute>(); #if NOTYET if (lenAttr == null) { throw new InternalError($"No max string length given using StringLengthAttribute - {FieldName}"); } #endif if (lenAttr != null && lenAttr.MaximumLength > 0 && lenAttr.MaximumLength <= 8000) { tag.MergeAttribute("maxlength", lenAttr.MaximumLength.ToString()); } return(Task.FromResult(tag.ToString(YTagRenderMode.StartTag))); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(string model) { HtmlBuilder hb = new HtmlBuilder(); int tileSize = PropData.GetAdditionalAttributeValue("TileSize", 16); string palette = PropData.GetAdditionalAttributeValue("Palette", "basic"); int columns = PropData.GetAdditionalAttributeValue("Columns", 6); bool preview = PropData.GetAdditionalAttributeValue("Preview", true); YTagBuilder tag = new YTagBuilder("input"); tag.AddCssClass("yt_colorpicker"); tag.AddCssClass("t_edit"); FieldSetup(tag, Validation ? FieldType.Validated : FieldType.Normal); tag.MergeAttribute("id", ControlId); if (model != null) { tag.MergeAttribute("value", model); } hb.Append(tag.ToString(YTagRenderMode.StartTag)); ScriptBuilder sb = new ScriptBuilder(); sb.Append($@"(new YetaWF_ComponentsHTML.ColorPickerEditComponent('{ControlId}', {{ palette: '{JE(palette)}', tileSize: {tileSize}, preview: {JE(preview)}, messages: {{ previewInput: '{JE(__ResStr("editColor", "Edit the color using hex values or names"))}', cancel: '{JE(__ResStr("cancel", "Cancel"))}', apply: '{JE(__ResStr("apply", "Apply"))}' }} }}));"); Manager.ScriptManager.AddLast(sb.ToString()); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(int?model) { HtmlBuilder hb = new HtmlBuilder(); YTagBuilder tag = new YTagBuilder("input"); string id = MakeId(tag); tag.AddCssClass(TemplateClass); tag.AddCssClass("t_edit"); tag.AddCssClass("yt_intvalue_base"); FieldSetup(tag, Validation ? FieldType.Validated : FieldType.Normal); tag.MergeAttribute("maxlength", "20"); if (model != null) { tag.MergeAttribute("value", ((int)model).ToString()); } // handle min/max int min = 0, max = 999999999; RangeAttribute rangeAttr = PropData.TryGetAttribute <RangeAttribute>(); if (rangeAttr != null) { min = (int)rangeAttr.Minimum; max = (int)rangeAttr.Maximum; } string noEntry = PropData.GetAdditionalAttributeValue <string>("NoEntry", null); int step = PropData.GetAdditionalAttributeValue <int>("Step", 1); hb.Append($@" {tag.ToString(YTagRenderMode.StartTag)}"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.IntValueEditComponent('{id}', {{ Min: {min}, Max: {max}, Step: {step}, NoEntryText: '{JE(noEntry??"")}' }});"); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(DateTime?model) { UseSuppliedIdAsControlId(); HtmlBuilder hb = new HtmlBuilder(); hb.Append($"<div id='{ControlId}' class='yt_datetime t_edit'>"); Dictionary <string, object> hiddenAttributes = new Dictionary <string, object>(HtmlAttributes) { { "__NoTemplate", true } }; hb.Append(await HtmlHelper.ForEditComponentAsync(Container, PropertyName, null, "Hidden", HtmlAttributes: hiddenAttributes, Validation: Validation)); YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, FieldType.Anonymous); tag.Attributes.Add("name", "dtpicker"); // handle min/max date DateTimeSetup setup = new DateTimeSetup { Min = new DateTime(1900, 1, 1), Max = new DateTime(2199, 12, 31), }; MinimumDateAttribute minAttr = PropData.TryGetAttribute <MinimumDateAttribute>(); if (minAttr != null) { setup.Min = minAttr.MinDate; } MaximumDateAttribute maxAttr = PropData.TryGetAttribute <MaximumDateAttribute>(); if (maxAttr != null) { setup.Max = maxAttr.MaxDate; } if (model != null) { tag.MergeAttribute("value", Formatting.FormatDateTime((DateTime)model));// shows date using user's timezone } hb.Append(tag.ToString(YTagRenderMode.StartTag)); hb.Append($"</div>"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.DateTimeEditComponent('{ControlId}', {Utility.JsonSerialize(setup)});"); return(hb.ToString()); }
/// <summary> /// Adds HTML attributes and name= attribute to a tag. /// </summary> /// <param name="tag">The tag to which attributes are added.</param> /// <param name="fieldType">The type of the field.</param> /// <remarks>This is used for the main tag of a template. /// /// Also adds validation attributes depending on the field's type.</remarks> public void FieldSetup(YTagBuilder tag, FieldType fieldType) { if (HtmlAttributes != null) { tag.MergeAttributes(HtmlAttributes, false); } switch (fieldType) { case FieldType.Anonymous: break; case FieldType.Normal: tag.MergeAttribute("name", FieldName, false); break; case FieldType.Validated: tag.MergeAttribute("name", FieldName, false); // error state AddErrorClass(tag); // client side validation AddValidation(tag); break; } }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(Decimal?model) { HtmlBuilder hb = new HtmlBuilder(); hb.Append($"<div id='{ControlId}' class='yt_currency t_edit y_inline'>"); YTagBuilder tag = new YTagBuilder("input"); FieldSetup(tag, Validation ? FieldType.Validated : FieldType.Normal); bool rdonly = PropData.GetAdditionalAttributeValue <bool>("ReadOnly", false); bool disabled = PropData.GetAdditionalAttributeValue <bool>("Disabled", false); if (disabled) { tag.Attributes.Add("disabled", "disabled"); } CurrencySetup setup = new CurrencySetup { Min = 0, Max = 999999999.99, ReadOnly = rdonly, }; // handle min/max RangeAttribute rangeAttr = PropData.TryGetAttribute <RangeAttribute>(); if (rangeAttr != null) { setup.Min = (double)rangeAttr.Minimum; setup.Max = (double)rangeAttr.Maximum; } if (model != null) { tag.MergeAttribute("value", Formatting.FormatAmount((decimal)model)); } hb.Append(tag.ToString(YTagRenderMode.StartTag)); hb.Append($"</div>"); Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.CurrencyEditComponent('{ControlId}', {Utility.JsonSerialize(setup)});"); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(string model) { HtmlBuilder hb = new HtmlBuilder(); int tileSize = PropData.GetAdditionalAttributeValue("TileSize", 24); YTagBuilder tag = new YTagBuilder("div"); tag.AddCssClass("yt_colorpicker"); tag.AddCssClass("t_display"); FieldSetup(tag, FieldType.Anonymous); string style = $"width:{tileSize}px;height:{tileSize}px"; if (model != null) { style += $";background-color:{model}"; } tag.MergeAttribute("style", style); hb.Append(tag.ToString(YTagRenderMode.Normal)); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Returns the client-side validation message for a component with the specified field name. /// </summary> /// <param name="fieldName">The HTML field name.</param> /// <param name="htmlHelper">An instance of a YHtmlHelper.</param> /// <returns>Returns the client-side validation message for the component with the specified field name.</returns> public static string BuildValidationMessage(this YHtmlHelper htmlHelper, string fieldName) { var modelState = htmlHelper.ModelState[fieldName]; string error = null; bool hasError = false; if (modelState == null) { // no errors } else { IEnumerable <string> errors = (from e in modelState.Errors select e.ErrorMessage); hasError = errors.Any(); if (hasError) { error = errors.First(); } } YTagBuilder tagBuilder = new YTagBuilder("span"); tagBuilder.MergeAttribute("data-v-for", fieldName); tagBuilder.AddCssClass(hasError ? "v-error" : "v-valid"); if (hasError) { // we're building the same client side in validation.ts, make sure to keep in sync // <img src="${$YetaWF.htmlAttrEscape(YConfigs.Forms.CssWarningIconUrl)}" name=${name} class="${YConfigs.Forms.CssWarningIcon}" ${YConfigs.Basics.CssTooltip}="${$YetaWF.htmlAttrEscape(val.M)}"/> YTagBuilder tagImg = new YTagBuilder("img"); tagImg.Attributes.Add("src", Forms.CssWarningIconUrl); tagImg.Attributes.Add("name", fieldName); tagImg.AddCssClass(Forms.CssWarningIcon); tagImg.Attributes.Add(Basics.CssTooltip, error); tagBuilder.InnerHtml = tagImg.ToString(); } return(tagBuilder.ToString(YTagRenderMode.Normal)); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(string model) { HtmlBuilder hb = new HtmlBuilder(); hb.Append("<div class='yt_image t_display'>"); string imageType = PropData.GetAdditionalAttributeValue <string>("ImageType", null); int width = PropData.GetAdditionalAttributeValue("Width", 0); int height = PropData.GetAdditionalAttributeValue("Height", 0); if (string.IsNullOrWhiteSpace(imageType) && model != null && (model.IsAbsoluteUrl() || model.StartsWith("/") || model.StartsWith("data:"))) { if (width != 0 || height != 0) { throw new InternalError("Can't use Width or Height with external Urls"); } YTagBuilder img = new YTagBuilder("img"); img.Attributes.Add("src", model); if (!img.Attributes.ContainsKey("alt")) { img.Attributes.Add("alt", __ResStr("altImage", "Image")); } hb.Append(img.ToString(YTagRenderMode.Normal)); } else { if (string.IsNullOrWhiteSpace(imageType)) { throw new InternalError("No ImageType specified"); } bool showMissing = PropData.GetAdditionalAttributeValue("ShowMissing", true); if (string.IsNullOrWhiteSpace(model) && !showMissing) { return(Task.FromResult <string>(null)); } string alt = null; if (HtmlAttributes.ContainsKey("alt")) { alt = (string)HtmlAttributes["alt"]; } string imgTag = ImageComponentBase.RenderImage(imageType, width, height, model, Alt: alt); bool linkToImage = PropData.GetAdditionalAttributeValue("LinkToImage", false); if (linkToImage) { YTagBuilder link = new YTagBuilder("a"); string imgUrl = ImageHTML.FormatUrl(imageType, null, model); link.MergeAttribute("href", imgUrl); link.MergeAttribute("target", "_blank"); link.MergeAttribute("rel", "noopener noreferrer"); link.InnerHtml = imgTag; hb.Append(link.ToString(YTagRenderMode.Normal)); } else { hb.Append(imgTag); } } hb.Append("</div>"); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Renders a text input control. /// </summary> /// <param name="component">The current component being rendered.</param> /// <param name="model">The model.</param> /// <param name="templateCssClass">The CSS class to add to the template (starting with yt_).</param> /// <returns>The component rendered as HTML.</returns> public static async Task <string> RenderTextAsync(YetaWFComponent component, string model, string templateCssClass) { await IncludeExplicitAsync(); HtmlBuilder hb = new HtmlBuilder(); component.UseSuppliedIdAsControlId(); YTagBuilder tag = new YTagBuilder("input"); if (!string.IsNullOrWhiteSpace(templateCssClass)) { tag.AddCssClass(templateCssClass); } tag.AddCssClass("yt_text_base"); // adding k-textbox to the control makes it look like a kendo maskedtext box without the overhead of actually calling kendoMaskedTextBox tag.AddCssClass("k-textbox"); tag.AddCssClass("t_edit"); component.FieldSetup(tag, component.Validation ? FieldType.Validated : FieldType.Normal); tag.Attributes.Add("id", component.ControlId); //string id = null; //if (!string.IsNullOrWhiteSpace(mask)) { // id = component.MakeId(tag); //} if (Manager.CurrentModule != null && Manager.CurrentModule.FormAutoComplete) { tag.MergeAttribute("autocomplete", "on", replaceExisting: false); } else { tag.MergeAttribute("autocomplete", "new-password", replaceExisting: false); } bool copy = component.PropData.GetAdditionalAttributeValue <bool>("Copy", false); //string mask = component.PropData.GetAdditionalAttributeValue<string>("Mask", null); // handle StringLengthAttribute as maxlength StringLengthAttribute lenAttr = component.PropData.TryGetAttribute <StringLengthAttribute>(); if (lenAttr != null) { #if DEBUG if (tag.Attributes.ContainsKey("maxlength")) { throw new InternalError("Both StringLengthAttribute and maxlength specified - {0}", component.FieldName); } #endif int maxLength = lenAttr.MaximumLength; if (maxLength > 0 && maxLength <= 8000) { tag.MergeAttribute("maxlength", maxLength.ToString()); } } #if DEBUG if (lenAttr == null && !tag.Attributes.ContainsKey("maxlength")) { throw new InternalError("No max string length given using StringLengthAttribute or maxlength - {0}", component.FieldName); } #endif // text tag.MergeAttribute("type", "text"); tag.MergeAttribute("value", model ?? ""); hb.Append($@"{tag.ToString(YTagRenderMode.StartTag)}"); if (copy) { await Manager.AddOnManager.AddAddOnNamedAsync(component.Package.AreaName, "clipboardjs.com.clipboard");// add clipboard support hb.Append(ImageHTML.BuildKnownIcon("#TextCopy", sprites: Info.PredefSpriteIcons, title: __ResStr("ttCopy", "Copy to Clipboard"), cssClass: "yt_text_copy")); } //if (!string.IsNullOrWhiteSpace(mask)) { // // if there is a Mask we need to use the KendoMaskedTextBox // await KendoUICore.AddFileAsync("kendo.maskedtextbox.min.js"); // ScriptBuilder sb = new ScriptBuilder(); // sb.Append("$('#{0}').kendoMaskedTextBox({{ mask: '{1}' }});\n", id, Utility.JserEncode(mask)); // Manager.ScriptManager.AddLastDocumentReady(sb); //} //Manager.ScriptManager.AddLast($@"new YetaWF_ComponentsHTML.TextEditComponent('{component.ControlId}');"); return(hb.ToString()); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public Task <string> RenderAsync(string model) { if (string.IsNullOrWhiteSpace(model)) { return(Task.FromResult <string>(null)); } HtmlBuilder hb = new HtmlBuilder(); hb.Append("<div class='yt_url t_display'>"); string hrefUrl; if (!TryGetSiblingProperty($"{PropertyName}_Url", out hrefUrl)) { hrefUrl = model; } if (string.IsNullOrWhiteSpace(hrefUrl)) { // no link YTagBuilder tag = new YTagBuilder("span"); FieldSetup(tag, FieldType.Anonymous); string cssClass = PropData.GetAdditionalAttributeValue("CssClass", ""); if (!string.IsNullOrWhiteSpace(cssClass)) { tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(cssClass)); } tag.SetInnerText(model); hb.Append(tag.ToString(YTagRenderMode.Normal)); } else { // link YTagBuilder tag = new YTagBuilder("a"); FieldSetup(tag, FieldType.Anonymous); string cssClass = PropData.GetAdditionalAttributeValue("CssClass", ""); if (!string.IsNullOrWhiteSpace(cssClass)) { tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(cssClass)); } tag.MergeAttribute("href", hrefUrl); tag.MergeAttribute("target", "_blank"); tag.MergeAttribute("rel", "nofollow noopener noreferrer"); string text; if (!TryGetSiblingProperty($"{PropertyName}_Text", out text)) { text = model; } tag.SetInnerText(text); string tooltip = null; TryGetSiblingProperty($"{PropertyName}_ToolTip", out tooltip); if (!string.IsNullOrWhiteSpace(tooltip)) { tag.MergeAttribute(Basics.CssTooltip, tooltip); } // image if (PropData.GetAdditionalAttributeValue("ShowImage", true)) { tag.InnerHtml = tag.InnerHtml + ImageHTML.BuildKnownIcon("#UrlRemote", sprites: Info.PredefSpriteIcons); } hb.Append(tag.ToString(YTagRenderMode.Normal)); } hb.Append("</div>"); return(Task.FromResult(hb.ToString())); }
/// <summary> /// Called by the framework when the component needs to be rendered as HTML. /// </summary> /// <param name="model">The model being rendered by the component.</param> /// <returns>The component rendered as HTML.</returns> public async Task <string> RenderAsync(string model) { HtmlBuilder hb = new HtmlBuilder(); UrlTypeEnum type = PropData.GetAdditionalAttributeValue("UrlType", UrlTypeEnum.Remote); UrlUI ui = new UrlUI { UrlType = type, _Local = model, _Remote = model, }; hb.Append($@" <div id='{ControlId}' class='yt_url t_edit'>"); YTagBuilder tag = new YTagBuilder("input"); tag.AddCssClass("t_hidden"); tag.Attributes["type"] = "hidden"; FieldSetup(tag, FieldType.Validated); tag.MergeAttribute("value", model); hb.Append(tag.ToString(YTagRenderMode.StartTag)); using (Manager.StartNestedComponent(FieldName)) { hb.Append($@" {await HtmlHelper.ForEditAsync(ui, nameof(ui.UrlType), Validation: false)} "); if ((type & UrlTypeEnum.Local) != 0) { hb.Append($@" <div class='t_local'> {await HtmlHelper.ForEditAsync(ui, nameof(ui._Local), Validation: false)} </div>"); } if ((type & UrlTypeEnum.Remote) != 0) { hb.Append($@" <div class='t_remote'> {await HtmlHelper.ForEditAsync(ui, nameof(ui._Remote), Validation: false)} </div>"); } } // link tag = new YTagBuilder("a"); tag.MergeAttribute("href", Utility.UrlEncodePath(model)); tag.MergeAttribute("target", "_blank"); tag.MergeAttribute("rel", "nofollow noopener noreferrer"); tag.InnerHtml = tag.InnerHtml + ImageHTML.BuildKnownIcon("#UrlRemote", sprites: Info.PredefSpriteIcons); string link = tag.ToString(YTagRenderMode.Normal); UrlEditSetup setup = new UrlEditSetup { Type = type, Url = model, }; hb.Append($@" <div class='t_link'> {link} </div> </div>"); Manager.ScriptManager.AddLast($"new YetaWF_ComponentsHTML.UrlEditComponent('{ControlId}', {Utility.JsonSerialize(setup)});"); return(hb.ToString()); }
/// <summary> /// Renders the beginning <form> tag with the specified attributes. /// </summary> /// <param name="HtmlAttributes">The HTML attributes to add to the <form> tag.</param> /// <param name="SaveReturnUrl">Defines whether the return URL is saved when the form is submitted.</param> /// <param name="ValidateImmediately">Defines whether client-side validation is immediate (true) or delayed until form submission (false).</param> /// <param name="ActionName">Overrides the default action name.</param> /// <param name="ControllerName">Overrides the default controller name.</param> /// <param name="Pure">TODO: Purpose unclear.</param> /// <param name="Method">The method used to submit the form (get/post)</param> /// <returns>Returns the HTML with the generated <form> tag.</returns> protected async Task <string> RenderBeginFormAsync(object HtmlAttributes = null, bool SaveReturnUrl = false, bool ValidateImmediately = false, string ActionName = null, string ControllerName = null, string Method = "post") { await YetaWFCoreRendering.Render.AddFormsAddOnsAsync(); await Manager.AddOnManager.AddAddOnNamedAsync("YetaWF_Core", "Forms");// standard css, validation strings await Manager.AddOnManager.AddAddOnNamedAsync("YetaWF_ComponentsHTML", "Forms"); Manager.ScriptManager.AddLast("$YetaWF.Forms", "$YetaWF.Forms;");// need to evaluate for side effect to initialize forms Manager.NextUniqueIdPrefix(); if (string.IsNullOrWhiteSpace(ActionName)) { ActionName = GetViewName(); } if (!ActionName.EndsWith(YetaWFViewExtender.PartialSuffix)) { ActionName += YetaWFViewExtender.PartialSuffix; } if (string.IsNullOrWhiteSpace(ControllerName)) { ControllerName = ModuleBase.Controller; } IDictionary <string, object> rvd = YHtmlHelper.AnonymousObjectToHtmlAttributes(HtmlAttributes); if (SaveReturnUrl) { rvd.Add(Basics.CssSaveReturnUrl, ""); } string css = null; if (Manager.CurrentSite.FormErrorsImmed) { css = CssManager.CombineCss(css, "yValidateImmediately"); } css = CssManager.CombineCss(css, Forms.CssFormAjax); rvd.Add("class", css); YTagBuilder tagBuilder = new YTagBuilder("form"); tagBuilder.MergeAttributes(rvd, true); if (ModuleBase.FormAutoComplete) { tagBuilder.Attributes.Add("autocomplete", "on"); } else { tagBuilder.Attributes.Add("autocomplete", "new-password"); } string id = null; if (tagBuilder.Attributes.ContainsKey("id")) { id = (string)tagBuilder.Attributes["id"]; } else { id = Manager.UniqueId(); tagBuilder.Attributes.Add("id", id); } string formAction; #if MVC6 System.IServiceProvider services = HtmlHelper.ActionContext.HttpContext.RequestServices; IUrlHelper urlHelper = services.GetRequiredService <IUrlHelperFactory>().GetUrlHelper(HtmlHelper.ActionContext); formAction = urlHelper.Action(action: ActionName, controller: ControllerName, new { area = HtmlHelper.RouteData.Values["area"] }); #else formAction = UrlHelper.GenerateUrl(null /* routeName */, ActionName, ControllerName, null, RouteTable.Routes, HtmlHelper.RequestContext, true /* includeImplicitMvcValues */); #endif tagBuilder.MergeAttribute("action", formAction, true); tagBuilder.MergeAttribute("method", Method, true); // show errors if already present if (!HtmlHelper.ModelState.IsValid) { Manager.ScriptManager.AddLast($@" var f = $YetaWF.getElementById('{id}'); if ($YetaWF.Forms.hasErrors(f)) $YetaWF.Forms.showErrors(f); "); } return(tagBuilder.ToString(YTagRenderMode.StartTag)); }
internal static async Task <string> RenderActionAsync(ModuleAction action, ModuleAction.RenderModeEnum mode, string id, ModuleAction.RenderEngineEnum RenderEngine = ModuleAction.RenderEngineEnum.KendoMenu, int BootstrapSmartMenuLevel = 0, bool HasSubmenu = false) { // check if we're in the right mode if (!await action.RendersSomethingAsync()) { return(null); } await Manager.AddOnManager.AddTemplateFromUIHintAsync("ActionIcons");// this is needed because we're not used by templates if (!string.IsNullOrWhiteSpace(action.ConfirmationText) && (action.Style != ModuleAction.ActionStyleEnum.Post && action.Style != ModuleAction.ActionStyleEnum.Nothing)) { throw new InternalError("When using ConfirmationText, the Style property must be set to Post"); } if (!string.IsNullOrWhiteSpace(action.PleaseWaitText) && (action.Style != ModuleAction.ActionStyleEnum.Normal && action.Style != ModuleAction.ActionStyleEnum.Post)) { throw new InternalError("When using PleaseWaitText, the Style property must be set to Normal or Post"); } if (action.CookieAsDoneSignal && action.Style != ModuleAction.ActionStyleEnum.Normal) { throw new InternalError("When using CookieAsDoneSignal, the Style property must be set to Normal"); } ModuleAction.ActionStyleEnum style = action.Style; if (style == ModuleAction.ActionStyleEnum.OuterWindow) { if (!Manager.IsInPopup) { style = ModuleAction.ActionStyleEnum.Normal; } } if (style == ModuleAction.ActionStyleEnum.Popup || style == ModuleAction.ActionStyleEnum.PopupEdit) { if (Manager.IsInPopup) { style = ModuleAction.ActionStyleEnum.NewWindow; } } if (style == ModuleAction.ActionStyleEnum.Popup || style == ModuleAction.ActionStyleEnum.PopupEdit || style == ModuleAction.ActionStyleEnum.ForcePopup) { await YetaWFCoreRendering.Render.AddPopupsAddOnsAsync(); } bool newWindow = false, outerWindow = false; bool popup = false, popupEdit = false; bool nothing = false, post = false; switch (style) { default: case ModuleAction.ActionStyleEnum.Normal: break; case ModuleAction.ActionStyleEnum.NewWindow: newWindow = true; break; case ModuleAction.ActionStyleEnum.Popup: case ModuleAction.ActionStyleEnum.ForcePopup: popup = Manager.CurrentSite.AllowPopups; break; case ModuleAction.ActionStyleEnum.PopupEdit: popup = Manager.CurrentSite.AllowPopups; popupEdit = Manager.CurrentSite.AllowPopups; break; case ModuleAction.ActionStyleEnum.OuterWindow: outerWindow = true; break; case ModuleAction.ActionStyleEnum.Nothing: nothing = true; break; case ModuleAction.ActionStyleEnum.Post: post = true; break; } YTagBuilder tag = new YTagBuilder("a"); if (!string.IsNullOrWhiteSpace(action.Tooltip)) { tag.MergeAttribute(Basics.CssTooltip, action.Tooltip); } if (!string.IsNullOrWhiteSpace(action.Name)) { tag.MergeAttribute("data-name", action.Name); } if (!action.Displayed) { tag.MergeAttribute("style", "display:none"); } if (HasSubmenu) { if (RenderEngine == ModuleAction.RenderEngineEnum.BootstrapSmartMenu) { tag.AddCssClass("dropdown-toggle"); tag.Attributes.Add("data-toggle", "dropdown-toggle"); } tag.Attributes.Add("aria-haspopup", "true"); tag.Attributes.Add("aria-expanded", "false"); } if (RenderEngine == ModuleAction.RenderEngineEnum.BootstrapSmartMenu) { tag.AddCssClass(BootstrapSmartMenuLevel <= 1 ? "nav-link" : "dropdown-item"); } if (!string.IsNullOrWhiteSpace(id)) { tag.Attributes.Add("id", id); } if (!string.IsNullOrWhiteSpace(action.CssClass)) { tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(action.CssClass)); } string extraClass; switch (mode) { default: case ModuleAction.RenderModeEnum.Button: extraClass = "y_act_button"; break; case ModuleAction.RenderModeEnum.ButtonIcon: extraClass = "y_act_buttonicon"; break; case ModuleAction.RenderModeEnum.ButtonOnly: extraClass = "y_act_buttononly"; break; case ModuleAction.RenderModeEnum.IconsOnly: extraClass = "y_act_icon"; break; case ModuleAction.RenderModeEnum.LinksOnly: extraClass = "y_act_link"; break; case ModuleAction.RenderModeEnum.NormalLinks: extraClass = "y_act_normlink"; break; case ModuleAction.RenderModeEnum.NormalMenu: extraClass = "y_act_normmenu"; break; } tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(extraClass)); string url = action.GetCompleteUrl(OnPage: true); if (!string.IsNullOrWhiteSpace(url)) { tag.MergeAttribute("href", Utility.UrlEncodePath(url)); if (Manager.CurrentPage != null) { string currUrl = Manager.CurrentPage.EvaluatedCanonicalUrl; if (!string.IsNullOrWhiteSpace(currUrl) && currUrl != "/") // this doesn't work on home page because everything matches { if (action.Url == currUrl) { tag.AddCssClass("t_currenturl"); } if (currUrl.StartsWith(action.Url)) { tag.AddCssClass("t_currenturlpart"); } } } } else { tag.MergeAttribute("href", "javascript:void(0);"); } if (!string.IsNullOrWhiteSpace(action.ConfirmationText)) { if (action.Category == ModuleAction.ActionCategoryEnum.Delete) { // confirm deletions? if (UserSettings.GetProperty <bool>("ConfirmDelete")) { tag.MergeAttribute(Basics.CssConfirm, action.ConfirmationText); } } else { // confirm actions? if (UserSettings.GetProperty <bool>("ConfirmActions")) { tag.MergeAttribute(Basics.CssConfirm, action.ConfirmationText); } } } if (!string.IsNullOrWhiteSpace(action.PleaseWaitText)) { tag.MergeAttribute(Basics.CssPleaseWait, action.PleaseWaitText); } if (action.CookieAsDoneSignal) { tag.Attributes.Add(Basics.CookieDoneCssAttr, ""); } if (action.SaveReturnUrl) { tag.Attributes.Add(Basics.CssSaveReturnUrl, ""); if (!action.AddToOriginList) { tag.Attributes.Add(Basics.CssDontAddToOriginList, ""); } } if (!string.IsNullOrWhiteSpace(action.ExtraData)) { tag.Attributes.Add(Basics.CssExtraData, action.ExtraData); } if (action.NeedsModuleContext) { tag.Attributes.Add(Basics.CssAddModuleContext, ""); } if (post) { tag.Attributes.Add(Basics.PostAttr, ""); } if (action.DontFollow || action.CookieAsDoneSignal || post || nothing) { tag.MergeAttribute("rel", "nofollow"); // this is so bots don't follow this assuming it's a simple page (Post actions can't be retrieved with GET/HEAD anyway) } if (outerWindow) { tag.Attributes.Add(Basics.CssOuterWindow, ""); } if (!nothing) { tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(Basics.CssActionLink)); } if (newWindow) { tag.MergeAttribute("target", "_blank"); tag.MergeAttribute("rel", "noopener noreferrer"); } if (popup) { tag.AddCssClass(Manager.AddOnManager.CheckInvokedCssModule(Basics.CssPopupLink)); if (popupEdit) { tag.Attributes.Add(Basics.CssAttrDataSpecialEdit, ""); } } if (mode == ModuleAction.RenderModeEnum.Button || mode == ModuleAction.RenderModeEnum.ButtonIcon || mode == ModuleAction.RenderModeEnum.ButtonOnly) { tag.Attributes.Add(Basics.CssAttrActionButton, ""); } bool hasText = false, hasImg = false; string innerHtml = ""; if (mode != ModuleAction.RenderModeEnum.LinksOnly && mode != ModuleAction.RenderModeEnum.ButtonOnly && !string.IsNullOrWhiteSpace(action.ImageUrlFinal)) { string text = mode == ModuleAction.RenderModeEnum.NormalMenu ? action.MenuText : action.LinkText; if (RenderEngine == ModuleAction.RenderEngineEnum.KendoMenu) { innerHtml += ImageHTML.BuildKnownIcon(action.ImageUrlFinal, alt: text, cssClass: Basics.CssNoTooltip + " k-image"); // k-image is needed to align <i> and <img> correctly } else { innerHtml += ImageHTML.BuildKnownIcon(action.ImageUrlFinal, alt: text, cssClass: Basics.CssNoTooltip); } hasImg = true; } if (mode != ModuleAction.RenderModeEnum.IconsOnly && mode != ModuleAction.RenderModeEnum.ButtonIcon) { string text = mode == ModuleAction.RenderModeEnum.NormalMenu ? action.MenuText : action.LinkText; if (!string.IsNullOrWhiteSpace(text)) { innerHtml += Utility.HtmlEncode(text); hasText = true; } } if (hasText) { if (hasImg) { tag.AddCssClass("y_act_textimg"); } else { tag.AddCssClass("y_act_text"); } } else { if (hasImg) { tag.AddCssClass("y_act_img"); } } if (HasSubmenu && RenderEngine == ModuleAction.RenderEngineEnum.BootstrapSmartMenu) { innerHtml += " <span class='caret'></span>"; } tag.AddCssClass(Globals.CssModuleNoPrint); tag.InnerHtml = innerHtml; return(tag.ToString(YTagRenderMode.Normal)); }