|
|
@@ -12,6 +12,7 @@ using System.Globalization;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Linq.Expressions;
|
|
|
+using System.Reflection;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
@@ -246,6 +247,200 @@ namespace GreenTree.Strohrmann.ERP.Web.Extension
|
|
|
return new HtmlString(htmlString);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Return HTML markup for the <paramref name="valueExpression"/>, using a display template for a search selection field.
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TModel">Model type.</typeparam>
|
|
|
+ /// <typeparam name="TValue">Model value type.</typeparam>
|
|
|
+ /// <param name="htmlHelper">HtmlHelper context.</param>
|
|
|
+ /// <param name="valueExpression">Expression for the requested model value.</param>
|
|
|
+ /// <param name="textExpression">Expression for the requested model text.</param>
|
|
|
+ /// <param name="searchActionUrl">POST action URL that returns a model enumeration as JSON result.</param>
|
|
|
+ /// <param name="htmlAttributesValue">Additional HTML attributes for the value input.</param>
|
|
|
+ /// <param name="htmlAttributesText">Additional HTML attributes for the text input.</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static IHtmlContent SearchFor<TModel, TValue>(
|
|
|
+ this IHtmlHelper<TModel> htmlHelper,
|
|
|
+ Expression<Func<TModel, TValue>> valueExpression,
|
|
|
+ Expression<Func<TModel, string>> textExpression,
|
|
|
+ string searchActionUrl,
|
|
|
+ object htmlAttributesValue = null,
|
|
|
+ object htmlAttributesText = null)
|
|
|
+ {
|
|
|
+ var attributesText = htmlAttributesText == null
|
|
|
+ ? new string[0]
|
|
|
+ : htmlAttributesText.GetType().GetProperties()
|
|
|
+ .Where(p => p.Name != "name")
|
|
|
+ .Select(p => String.Format("{0}='{1}'", p.Name.Replace("_", "-"), p.GetValue(htmlAttributesText)))
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
+ var attributesValue = htmlAttributesValue == null
|
|
|
+ ? new string[0]
|
|
|
+ : htmlAttributesValue.GetType().GetProperties()
|
|
|
+ .Where(p => p.Name != "name")
|
|
|
+ .Select(p => String.Format("{0}='{1}'", p.Name.Replace("_", "-"), p.GetValue(htmlAttributesValue)))
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
+ var id = RandomId();
|
|
|
+
|
|
|
+ var valFunc = valueExpression.Compile();
|
|
|
+
|
|
|
+ var funcVal = htmlHelper.ViewData.Model == null
|
|
|
+ ? default
|
|
|
+ : valFunc(htmlHelper.ViewData.Model);
|
|
|
+
|
|
|
+ var isDefaultValue = funcVal == null || (funcVal != null && funcVal.ToString() == default(TValue).ToString());
|
|
|
+
|
|
|
+ var textFunc = textExpression.Compile();
|
|
|
+
|
|
|
+ var funcText = htmlHelper.ViewData.Model == null
|
|
|
+ ? default
|
|
|
+ : textFunc(htmlHelper.ViewData.Model);
|
|
|
+
|
|
|
+ var memberInfoText = textExpression.Body.NodeType == ExpressionType.MemberAccess
|
|
|
+ ? ((MemberExpression)textExpression.Body).Member
|
|
|
+ : null;
|
|
|
+
|
|
|
+ var nameText = memberInfoText == null
|
|
|
+ ? Guid.NewGuid().ToShortString()
|
|
|
+ : memberInfoText.Name;
|
|
|
+
|
|
|
+ if (htmlAttributesText != null && htmlAttributesText.GetType().GetProperty("name") != null)
|
|
|
+ nameText = htmlAttributesText.GetType().GetProperty("name").GetValue(htmlAttributesText).ToString();
|
|
|
+
|
|
|
+ var memberInfoValue = valueExpression.Body.NodeType == ExpressionType.MemberAccess
|
|
|
+ ? ((MemberExpression)valueExpression.Body).Member
|
|
|
+ : null;
|
|
|
+
|
|
|
+ var nameValue = memberInfoValue == null
|
|
|
+ ? Guid.NewGuid().ToShortString()
|
|
|
+ : memberInfoValue.Name;
|
|
|
+
|
|
|
+ if (htmlAttributesValue != null && htmlAttributesValue.GetType().GetProperty("name") != null)
|
|
|
+ nameValue = htmlAttributesValue.GetType().GetProperty("name").GetValue(htmlAttributesValue).ToString();
|
|
|
+
|
|
|
+ var scriptBuilder = new StringBuilder();
|
|
|
+ scriptBuilder.AppendFormat(
|
|
|
+ "<script type='text/javascript'>\n" +
|
|
|
+ "$(document).ready(function() {{\n" +
|
|
|
+ " $(\"#text_{0}\").on('keypress', function (e) {{\n" +
|
|
|
+ " if (e.keyCode == 13)\n" +
|
|
|
+ " {{\n" +
|
|
|
+ " search_{0}();\n" +
|
|
|
+ " e.preventDefault();\n" +
|
|
|
+ " }};\n" +
|
|
|
+ " }});\n" +
|
|
|
+ " $(\"#text_{0}\").on('keydown', function (e) {{\n" +
|
|
|
+ " if (e.keyCode == 8 && $(\"#value_{0}\").val() != '') {{\n" +
|
|
|
+ " $(\"#text_{0}\").val('');\n" +
|
|
|
+ " $(\"#value_{0}\").val('');\n" +
|
|
|
+ " $(\"#text_{0}\").next().children('.fa-check-circle').fadeOut('fast', function() {{\n" +
|
|
|
+ " $(\"#text_{0}\").next().children(\".fa-ellipsis-h\").fadeIn('fast');\n" +
|
|
|
+ " }});\n" +
|
|
|
+ " e.preventDefault();\n" +
|
|
|
+ " }};\n" +
|
|
|
+ " }});\n" +
|
|
|
+ "}});\n" +
|
|
|
+ "\n" +
|
|
|
+ "function search_{0}()\n" +
|
|
|
+ "{{\n" +
|
|
|
+ " $.ajax({{\n" +
|
|
|
+ " method: 'POST',\n" +
|
|
|
+ " url: '{1}',\n" +
|
|
|
+ " data:\n" +
|
|
|
+ " {{\n" +
|
|
|
+ " SearchTerm: $('#text_{0}').val()\n" +
|
|
|
+ " }},\n" +
|
|
|
+ " success: function(data) {{\n" +
|
|
|
+ " $(\"#searchModal_{0}\").find('.list-group').empty();\n" +
|
|
|
+ " if (data.length > 0)\n" +
|
|
|
+ " {{\n" +
|
|
|
+ " $(data).each(function(index, elem) {{\n" +
|
|
|
+ " $(\"#searchModal_{0}\").find('.list-group').append(\n" +
|
|
|
+ " \"<a href='#' class='list-group-item list-group-item-info list-group-item-action'" +
|
|
|
+ " data-toggle='list' data-val='{{0}}' data-text='{{1}}' ondblclick='select_{0}()'>{{1}}</a>\"\n" +
|
|
|
+ " .format(elem.searchId, elem.searchText));\n" +
|
|
|
+ " }});\n" +
|
|
|
+ " }}\n" +
|
|
|
+ " else\n" +
|
|
|
+ " {{\n" +
|
|
|
+ " $(\"#searchModal_{0}\").find('.list-group').append(\n" +
|
|
|
+ " \"'<button type='button' class='list-group-item'>Keine Treffer</button>'\");\n" +
|
|
|
+ " }}\n" +
|
|
|
+ " $(\"#searchModal_{0}\").modal('show');\n" +
|
|
|
+ " }},\n" +
|
|
|
+ " error: function(msg) {{\n" +
|
|
|
+ " \n" +
|
|
|
+ " }}\n" +
|
|
|
+ " }});\n" +
|
|
|
+ "}}\n" +
|
|
|
+ "\n" +
|
|
|
+ "function select_{0}()\n" +
|
|
|
+ "{{\n" +
|
|
|
+ " $(\"#searchModal_{0}\").modal('hide');\n" +
|
|
|
+ " var val = $(\"#searchModal_{0}\").find('a.active').attr('data-val');\n" +
|
|
|
+ " var text = $(\"#searchModal_{0}\").find('a.active').attr('data-text');\n" +
|
|
|
+ " $(\"#value_{0}\").val(val);\n" +
|
|
|
+ " $(\"#text_{0}\").val(text);\n" +
|
|
|
+ " $(\"#text_{0}\").next().children('.fa-ellipsis-h').fadeOut('fast', function() {{\n" +
|
|
|
+ " $(\"#text_{0}\").next().children('.fa-check-circle').fadeIn('fast');\n" +
|
|
|
+ " $(\"#text_{0}\").focus();\n" +
|
|
|
+ " }});\n" +
|
|
|
+ "}}" +
|
|
|
+ "</script>",
|
|
|
+ id,
|
|
|
+ searchActionUrl
|
|
|
+ );
|
|
|
+
|
|
|
+ var contentBuilder = new StringBuilder();
|
|
|
+ contentBuilder.AppendFormat(
|
|
|
+ "<div class='input-group'>\n" +
|
|
|
+ "<div class='input-group-prepend'>\n" +
|
|
|
+ "<button class='btn btn-info fas fa-search' type='button' onclick='search_{0}()'></button>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "<input id='text_{0}' type='text' name='{1}' value='{2}' class='form-control' placeholder='Suchbegriff'\n" +
|
|
|
+ " aria-label='Suchbegriff' aria-describedby='basic-addon1' {5} />\n" +
|
|
|
+ "<div class='input-group-append'>\n" +
|
|
|
+ " <span class='input-group-text bg-success text-white rounded-right fas fa-cust-lh fa-check-circle' {7}></span>\n" +
|
|
|
+ " <span class='input-group-text rounded-right fas fa-cust-lh fa-ellipsis-h' {8}></span>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "\n" +
|
|
|
+ "<input id='value_{0}' type='hidden' name='{3}' value='{4}' {6} />\n" +
|
|
|
+ "\n" +
|
|
|
+ "<div id='searchModal_{0}' class='modal fade'>\n" +
|
|
|
+ "<div class='modal-dialog'>\n" +
|
|
|
+ "<div class='modal-content'>\n" +
|
|
|
+ "<div class='modal-header'>\n" +
|
|
|
+ "<h4 class='modal-title'>Suchergebnisse</h4>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "<div class='modal-body overflow-auto' style='max-height: 400px'>\n" +
|
|
|
+ "<div class='list-group'>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "<div class='modal-footer'>\n" +
|
|
|
+ "<div class='btn btn-secondary' data-dismiss='modal'>Schließen</div>\n" +
|
|
|
+ "<div class='btn btn-success' onclick='select_{0}()'>Auswählen</div>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "</div>\n" +
|
|
|
+ "</div>",
|
|
|
+ id,
|
|
|
+ nameText,
|
|
|
+ funcText,
|
|
|
+ nameValue,
|
|
|
+ funcVal,
|
|
|
+ String.Join(" ", attributesText),
|
|
|
+ String.Join(" ", attributesValue),
|
|
|
+ (htmlHelper.ViewData.Model == null || isDefaultValue ? "style='display: none'" : String.Empty),
|
|
|
+ (htmlHelper.ViewData.Model == null || isDefaultValue ? String.Empty : "style='display: none'")
|
|
|
+ );
|
|
|
+
|
|
|
+ var htmlString = String.Format("{0}\n{1}", scriptBuilder.ToString(), contentBuilder.ToString());
|
|
|
+
|
|
|
+ return new HtmlString(htmlString);
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
|
|
|
#region Helper
|