using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Web.Mvc; using System.Web.Mvc.Html; using Kendo.Mvc.UI; using Kendo.Mvc.UI.Fluent; using Kreta.Resources; namespace Kreta.Web.Helpers { public static class ComboBoxExtensions { public const string GroupTemplate = "#if(data.First){ #
#: data.GroupName #
#}# #: data.Text #"; public static ComboBoxBuilder KretaComboBox(this HtmlHelper helper, string id, string url = null, string dataTextField = "Text", string datavalueField = "Value", string placeholder = "", string groupName = null, Type groupType = null, bool isServerFiltering = true, bool isAutoComplete = false, bool useGroup = false, IDictionary htmlAttributes = null, string onChangeFunction = null, bool selectFirstItem = false) { if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } SetUnknownValueMessage(htmlAttributes); var combobox = helper.Kendo().ComboBox() .Name(id) .DataTextField(dataTextField) .DataValueField(datavalueField); if (isAutoComplete) { combobox.Filter(FilterType.Contains); } if (!string.IsNullOrWhiteSpace(placeholder)) { combobox.Placeholder(placeholder); } if (groupName != null) { combobox .DataSource(source => { source.Custom() .ServerFiltering(isServerFiltering) .Transport(transport => { transport.Read( read => read.Url(url)); }) .Group(g => g.Add(groupName, groupType)); }); return combobox; } combobox .DataSource(source => { source.Custom() .ServerFiltering(isServerFiltering) .Transport(transport => { transport.Read( read => read.Url(url)); }); }) .HtmlAttributes(htmlAttributes); if (useGroup) { combobox.Template(GroupTemplate); } if (selectFirstItem) { combobox.SelectedIndex(0); } SetDefaultEvents(combobox, onChangeFunction); return combobox; } public static ComboBoxBuilder KretaComboBox( this HtmlHelper helper, string id, IEnumerable selectList, IDictionary htmlAttributes = null, string onChangeFunction = null, string labelText = null, bool showUnknownValueMessage = true, bool isSingleElementSet = true) { if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } if (!htmlAttributes.ContainsKey("data-labelmsg")) { htmlAttributes.Add("data-labelmsg", labelText); } if (showUnknownValueMessage) { SetUnknownValueMessage(htmlAttributes); } var combobox = helper.Kendo().ComboBox() .Name(id) .BindTo(selectList) .Placeholder(CommonResource.PleaseChoose) .HtmlAttributes(htmlAttributes); SetDefaultEvents(combobox, onChangeFunction, isSingleElementSet: isSingleElementSet); return combobox; } public static ComboBoxBuilder KretaGroupableComboBox( this HtmlHelper helper, string id, string url, bool isGrouped = false, IDictionary htmlAttributes = null, bool showUnknownValueMessage = true) { if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } if (showUnknownValueMessage) { SetUnknownValueMessage(htmlAttributes); } var combobox = helper.Kendo().ComboBox() .Name(id) .Placeholder(CommonResource.PleaseChoose) .HtmlAttributes(htmlAttributes) .DataTextField("Text") .DataValueField("Value") .DataSource(source => source.Read(read => { read.Url(url); })); if (isGrouped) { combobox.DataSource(source => source .Custom() .Group(g => g.Add("GroupName", typeof(string)))); } SetDefaultEvents(combobox); return combobox; } public static ComboBoxBuilder KretaComboBoxCascade(this HtmlHelper helper, string id, string url, string cascadeFrom, IDictionary htmlAttributes = null, string placeholder = "") { if (string.IsNullOrWhiteSpace(placeholder)) { placeholder = CommonResource.PleaseChoose; } if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } SetUnknownValueMessage(htmlAttributes); htmlAttributes.Add("data-labelmsg", id); var combobox = helper.Kendo().ComboBox() .Name(id) .Placeholder(placeholder) .HtmlAttributes(htmlAttributes) .DataTextField("Text") .DataValueField("Value") .AutoBind(autoBind: false) .CascadeFrom(cascadeFrom) .DataSource(source => { source.Custom() .ServerFiltering(enabled: true) .Transport(transport => { transport.Read(read => read.Url(url).Data($"function(){{ return KretaComboBoxHelper.getCascadeData('#{cascadeFrom}'); }}")); }); }); SetDefaultEvents(combobox); return combobox; } public static ComboBoxBuilder KretaComboBoxFor(this HtmlHelper helper, Expression> expression, IEnumerable selectList, IDictionary htmlAttributes = null, bool isAutoComplete = false, bool isCustomAllowed = false, string onChangeFunction = null, bool isSingleElementSet = true, bool showPlaceHolder = true) { var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } SetUnknownValueMessage(htmlAttributes); if (metadata.IsRequired) { htmlAttributes.Add("data-rule-required", "true"); htmlAttributes.Add("title", string.Format(CommonResource.Required, metadata.DisplayName)); htmlAttributes.Add("data-labelmsg", metadata.DisplayName + " *"); } else { htmlAttributes.Add("data-labelmsg", metadata.DisplayName); } var modSelectList = new List(); var list = selectList.ToList(); for (var i = 0; i < list.Count; i++) { if (!string.IsNullOrWhiteSpace(list[i].Value)) { modSelectList.Add(list[i]); } } if (metadata.IsRequired && modSelectList.Count == 1) { modSelectList[0].Selected = true; } var combobox = helper.Kendo().ComboBoxFor(expression) .BindTo(modSelectList) .HtmlAttributes(htmlAttributes); if (showPlaceHolder) { combobox.Placeholder(CommonResource.PleaseChoose); } if (isAutoComplete) { combobox.Filter(FilterType.Contains); } SetDefaultEvents(combobox, onChangeFunction, isCustomAllowed, isSingleElementSet: isSingleElementSet); return combobox; } public static ComboBoxBuilder KretaComboBoxFor( this HtmlHelper helper, Expression> expression, string url, string dataTextField = "Text", string datavalueField = "Value", IDictionary htmlAttributes = null, bool usePlaceHolder = true, bool useGroup = false, bool isServerFiltering = true, bool isCustomAllowed = false, string dataFunction = null, string serverFilteringFrom = null, bool isAutoComplete = false, string onChangeFunction = null, bool isSingleElementSet = true, bool showUnknownValueMessage = true) { var fieldName = ExpressionHelper.GetExpressionText(expression); var fullBindingName = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName); var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } if (showUnknownValueMessage) { SetUnknownValueMessage(htmlAttributes); } var attributes = Mapper.GetUnobtrusiveValidationAttributes(helper, expression, htmlAttributes, metadata); foreach (var key in attributes.Keys) { try { var keyItem = new KeyValuePair(key, attributes[key].ToString()); if (!htmlAttributes.Contains(keyItem)) { htmlAttributes.Add(keyItem); } } catch { } } var validationAttributes = helper.GetUnobtrusiveValidationAttributes(fullBindingName, metadata); var isRequiredIf = RequiredIfReflector.RequiredIf(helper, validationAttributes); if (metadata.IsRequired) { if (!htmlAttributes.ContainsKey("data-rule-required")) { htmlAttributes.Add("data-rule-required", "true"); } if (!htmlAttributes.ContainsKey("data-labelmsg")) { htmlAttributes.Add("data-labelmsg", metadata.DisplayName + " *"); } if (!htmlAttributes.ContainsKey("title")) { htmlAttributes.Add("title", string.Format(CommonResource.Required, metadata.DisplayName)); } } else if (isRequiredIf) { if (!htmlAttributes.ContainsKey("data-labelmsg")) { htmlAttributes.Add("data-labelmsg", metadata.DisplayName + " *"); } } else { try { htmlAttributes.Add("data-labelmsg", metadata.DisplayName); } catch { } } var dataFunctionHasValue = !string.IsNullOrWhiteSpace(dataFunction); var combobox = helper.Kendo() .ComboBoxFor(expression) .HtmlAttributes(htmlAttributes) .DataTextField(dataTextField) .DataValueField(datavalueField) .AutoBind(autoBind: false) .DataSource(source => { source.Custom() .ServerFiltering(isServerFiltering) .Transport(transport => { transport.Read( read => { if (dataFunctionHasValue) { read.Url(url).Data(dataFunction); // A dataFunction egy js function, ami egy modelt ad hozzá az api kéréshez } else if (isServerFiltering && !string.IsNullOrWhiteSpace(serverFilteringFrom)) { read.Url(url).Data($"function(){{ return KretaComboBoxHelper.getServerFilteringData('#{serverFilteringFrom}'); }}"); } else { read.Url(url); } }); }); }); if (useGroup) { combobox.Template(GroupTemplate); } if (usePlaceHolder) { combobox.Placeholder(CommonResource.PleaseChoose); } if (isAutoComplete) { combobox.Filter(FilterType.Contains); } SetDefaultEvents(combobox, onChangeFunction, isCustomAllowed, isSingleElementSet: isSingleElementSet); return combobox; } public static ComboBoxBuilder KretaCascadeComboBoxFor( this HtmlHelper helper, Expression> expression, string url, string cascadeFrom, string dataTextField = "Text", string datavalueField = "Value", IDictionary htmlAttributes = null, bool usePlaceHolder = true, bool useGroup = false, bool isServerFiltering = true, bool isAutoComplete = false, bool isCustomAllowed = false, string onChangeFunction = null, bool isSingleElementSet = true) { var fieldName = ExpressionHelper.GetExpressionText(expression); var fullBindingName = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName); var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); if (htmlAttributes == null) { htmlAttributes = new Dictionary(); } SetUnknownValueMessage(htmlAttributes); var attributes = Mapper.GetUnobtrusiveValidationAttributes(helper, expression, htmlAttributes, metadata); foreach (var key in attributes.Keys) { if (!htmlAttributes.ContainsKey(key)) { htmlAttributes.Add(key, attributes[key].ToString()); } } var validationAttributes = helper.GetUnobtrusiveValidationAttributes(fullBindingName, metadata); var isRequiredIf = RequiredIfReflector.RequiredIf(helper, validationAttributes); htmlAttributes.Add("data-labelmsg", (metadata.IsRequired || isRequiredIf) ? metadata.DisplayName + " *" : metadata.DisplayName); var combobox = helper.Kendo() .ComboBoxFor(expression) .HtmlAttributes(htmlAttributes) .DataTextField(dataTextField) .DataValueField(datavalueField) .AutoBind(autoBind: false) .CascadeFrom(cascadeFrom) .DataSource(source => { source.Custom() .ServerFiltering(isServerFiltering) .Transport(transport => { transport.Read(read => read.Url(url).Data(string.Format("function(){{ return KretaComboBoxHelper.getCascadeData('#{0}'); }}", cascadeFrom))); }); }); if (useGroup) { combobox.Template(GroupTemplate); } if (usePlaceHolder) { combobox.Placeholder(CommonResource.PleaseChoose); } if (isAutoComplete) { combobox.Filter(FilterType.Contains); } SetDefaultEvents(combobox, onChangeFunction, isCustomAllowed, isSingleElementSet); return combobox; } public static MvcHtmlString RenderSearchPanel(this ComboBoxBuilder helper, bool withClear = false) { var labelMsg = ""; foreach (var item in helper.ToComponent().HtmlAttributes) { if (string.Equals(item.Key, "data-labelmsg", StringComparison.OrdinalIgnoreCase) && item.Value != null) { labelMsg = item.Value.ToString(); } } var id = helper.ToComponent().Id; var sb = new StringBuilder(); sb.Append("
"); sb.Append(""); sb.Append("
"); sb.Append(helper.ToHtmlString()); sb.Append("
"); if (withClear) { sb.Append(""); } return new MvcHtmlString(sb.ToString()); } public static MvcHtmlString RenderSearchPanelSideBar(this ComboBoxBuilder helper, string labelMsg = null, bool withClear = false) { if (string.IsNullOrWhiteSpace(labelMsg)) { foreach (var item in helper.ToComponent().HtmlAttributes) { if (string.Equals(item.Key, "data-labelmsg", StringComparison.OrdinalIgnoreCase) && item.Value != null) { labelMsg = item.Value.ToString(); } } } var id = helper.ToComponent().Id; var sb = new StringBuilder(); sb.Append("
"); sb.Append("
"); sb.Append(""); sb.Append("
"); sb.Append("
"); sb.Append(helper.ToHtmlString()); sb.Append("
"); sb.Append("
"); if (withClear) { sb.Append(""); } return new MvcHtmlString(sb.ToString()); } public static MvcHtmlString RenderWithClearButton(this ComboBoxBuilder helper) { var controlId = helper.ToComponent().Id; var output = new StringBuilder(); output.Append(helper.ToHtmlString()); output.Append(""); return new MvcHtmlString(output.ToString()); } public static MvcHtmlString RenderWithName(this ComboBoxBuilder helper, int labelWidth = 6, int inputWidth = 6, bool allSizeSame = false, string customClass = "", string customLabelDivClass = "", string customLabelClass = "", string tooltipResource = null, bool addOffset = false, bool isCustomRequired = false, string labelMsg = null, bool changeEventOverride = true, bool withClear = false) { if (string.IsNullOrWhiteSpace(labelMsg)) { foreach (var item in helper.ToComponent().HtmlAttributes) { if (string.Equals(item.Key, "data-labelmsg", StringComparison.OrdinalIgnoreCase) && item.Value != null) { labelMsg = item.Value.ToString(); } } } if (isCustomRequired) { labelMsg += " *"; } var sb = new StringBuilder(); if (string.IsNullOrWhiteSpace(tooltipResource)) { AddRenderWithNameBeginingFrame(sb, labelWidth, inputWidth, allSizeSame, helper.ToComponent().Name, labelMsg, customClass, customLabelDivClass, customLabelClass, addOffset); } else { AddRenderWithNameTooltipBeginingFrame(sb, labelWidth, inputWidth, allSizeSame, helper.ToComponent().Name, labelMsg, customClass, customLabelDivClass, customLabelClass, tooltipResource); } sb.Append(helper.ToHtmlString()); AddRenderWithNameCloseingFrame(sb, helper.ToComponent().Id, withClear); if (changeEventOverride) { AddDefaultChangeEventIfOverrided(helper, sb); } return new MvcHtmlString(sb.ToString()); } public static MvcHtmlString RenderWithoutName(this ComboBoxBuilder helper, int inputWidth = 12, bool allSizeSame = false, string customClass = "", bool withClear = false) { var sb = new StringBuilder(); AddRenderWithNameBeginingFrame(sb, 0, inputWidth, allSizeSame, helper.ToComponent().Name, string.Empty, customClass, string.Empty, string.Empty); sb.Append(helper.ToHtmlString()); AddRenderWithNameCloseingFrame(sb, helper.ToComponent().Id, withClear); AddDefaultChangeEventIfOverrided(helper, sb); return new MvcHtmlString(sb.ToString()); } public static MvcHtmlString RenderIntoOneColWithName(this ComboBoxBuilder helper, int inputWidth = 6, bool allSizeSame = false, string customClass = "", string customLabelDivClass = "", string customLabelClass = "", string tooltipResource = null, Dictionary customHtmlAttributes = null, bool withClear = false) { var labelMsg = ""; foreach (var item in helper.ToComponent().HtmlAttributes) { if (string.Equals(item.Key, "data-labelmsg", StringComparison.OrdinalIgnoreCase) && item.Value != null) { labelMsg = item.Value.ToString(); } } var sb = new StringBuilder(); AddRenderIntoOneColWithNameBeginingFrame(sb, inputWidth, allSizeSame, labelMsg, customClass, customLabelDivClass, customLabelClass, tooltipResource, customHtmlAttributes); sb.Append(helper.ToHtmlString()); if (!string.IsNullOrWhiteSpace(tooltipResource)) { sb.AppendFormat("{0}", tooltipResource); } sb.Append(""); AddRenderWithNameCloseingFrame(sb, helper.ToComponent().Id, withClear); AddDefaultChangeEventIfOverrided(helper, sb); return new MvcHtmlString(sb.ToString()); } private static void AddRenderIntoOneColWithNameBeginingFrame(StringBuilder sb, int inputWidth, bool allSizeSame, string labelMsg, string customClass, string customLabelDivClass, string customLabelClass, string tooltipResource = null, Dictionary customHtmlAttributes = null) { var customHtmlAttr = ""; if (customHtmlAttributes != null) { customHtmlAttr = string.Join(" ", customHtmlAttributes.Select(x => $"{x.Key}=\"{x.Value}\"")); } var needTooltip = !string.IsNullOrWhiteSpace(tooltipResource); sb.Append("
"); } private static void AddRenderWithNameBeginingFrame(StringBuilder sb, int labelWidth, int inputWidth, bool allSizeSame, string controlName, string labelMsg, string customClass, string customLabelDivClass, string customLabelClass, bool addOffset = false) { //TODO: ez a replace sor az OM-127 miatt került be, de az OM-2315 esetén hibát okoz nested objectek esetén controlName = controlName.Replace(".", "_"); if (labelWidth > 0 && !string.IsNullOrWhiteSpace(labelMsg)) { sb.AppendFormat("
", BootsrapHelper.GetSizeClasses(labelWidth, allSizeSame), customClass, customLabelDivClass); sb.AppendFormat("", customLabelClass, controlName, labelMsg); sb.Append("
"); } sb.AppendFormat("
", BootsrapHelper.GetSizeClasses(inputWidth, allSizeSame, addOffset), customClass); } private static void AddRenderWithNameTooltipBeginingFrame(StringBuilder sb, int labelWidth, int inputWidth, bool allSizeSame, string controlName, string labelMsg, string customClass, string customLabelDivClass, string customLabelClass, string tooltipResource) { sb.AppendFormat("
", BootsrapHelper.GetSizeClasses(labelWidth, allSizeSame), customClass, customLabelDivClass); sb.AppendFormat(""); sb.AppendFormat("
", BootsrapHelper.GetSizeClasses(inputWidth, allSizeSame), customClass); } private static void AddRenderWithNameCloseingFrame(StringBuilder sb, string id, bool withClear = false) { sb.Append("
"); if (withClear) { sb.Append(""); } } private static void AddListAutoWidthScript(StringBuilder sb, string id) { sb.AppendFormat("var combo = $('#{0}').data('kendoComboBox');", id); sb.Append("if(combo){ combo.list.width('auto'); }"); } private static void SetUnknownValueMessage(IDictionary htmlAttributes) { htmlAttributes.Add("data-msg-unknownvalue", CommonResource.UnknownValue); } private static void SetDefaultEvents(ComboBoxBuilder combobox, string onChangeFunction = null, bool isCustomAllowed = false, bool isSingleElementSet = true) { combobox.Events(e => e.Open("KretaComboBoxHelper.onOpenDropdown")); if (!isCustomAllowed) { var onChangeFunctions = onChangeFunction == null ? "KretaComboBoxHelper.onChange" : @"function(e){ KretaComboBoxHelper.onChange(e); " + onChangeFunction + "; }"; combobox.Events(e => { e.DataBound(isSingleElementSet ? "KretaComboBoxHelper.onDataBound" : "KretaComboBoxHelper.onDataBoundWithoutSetSingleElement"); e.Change(onChangeFunctions); }); } } public static MvcHtmlString RenderWithName(this ComboBoxBuilder helper, string label, int labelWidth = 6, int inputWidth = 6, bool allSizeSame = false, string tooltipResource = null, bool withClear = false) { var sb = new StringBuilder(); if (string.IsNullOrWhiteSpace(tooltipResource)) { AddRenderWithNameBeginingFrame(sb, labelWidth, inputWidth, allSizeSame, helper.ToComponent().Name, label, string.Empty, string.Empty, string.Empty); } else { AddRenderWithNameTooltipBeginingFrame(sb, labelWidth, inputWidth, allSizeSame, helper.ToComponent().Name, label, string.Empty, string.Empty, string.Empty, tooltipResource); } sb.Append(helper.ToHtmlString()); AddRenderWithNameCloseingFrame(sb, helper.ToComponent().Id, withClear); AddDefaultChangeEventIfOverrided(helper, sb); return new MvcHtmlString(sb.ToString()); } private static void AddDefaultChangeEventIfOverrided(ComboBoxBuilder helper, StringBuilder sb) { if (helper.ToComponent().Events.TryGetValue("change", out var eventValueObject)) { var eventValue = (Kendo.Mvc.ClientHandlerDescriptor)eventValueObject; if (!eventValue.HandlerName.Contains("KretaComboBoxHelper.onChange")) { var elementId = helper.ToComponent().Id; var str = ""; sb.Append(str); } } } } }