-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
507 additions
and
540 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
|
||
namespace FlexLabs.Web | ||
{ | ||
public sealed class AutoDropDownListAttribute : Attribute | ||
{ | ||
/// <summary> | ||
/// Defines the settings to initialise the DropDownList with | ||
/// </summary> | ||
/// <param name="optionsFieldName">The field in the model class that contains the IEnumerable<SelectListItem></param> | ||
public AutoDropDownListAttribute(String optionsFieldName) | ||
{ | ||
OptionsFieldName = optionsFieldName; | ||
} | ||
|
||
public String OptionsFieldName { get; private set; } | ||
public String OptionsLabel { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace FlexLabs.Web | ||
{ | ||
public sealed class AutoTextBoxAttribute : Attribute | ||
{ | ||
/// <summary> | ||
/// A string that is used to format the input | ||
/// </summary> | ||
public String Format { get; set; } | ||
public String Type { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
|
||
namespace FlexLabs.Web.Html | ||
{ | ||
internal static class ExpressionHelper | ||
{ | ||
public static MemberInfo GetMemberInfo(Expression expression) | ||
{ | ||
if (expression == null) | ||
return null; | ||
|
||
if (expression is LambdaExpression) | ||
return GetMemberInfo((expression as LambdaExpression).Body); | ||
|
||
switch (expression.NodeType) | ||
{ | ||
case ExpressionType.ArrayIndex: | ||
var binaryExpression = expression as BinaryExpression; | ||
return GetMemberInfo(binaryExpression.Left); | ||
|
||
case ExpressionType.MemberAccess: | ||
var memberExpression = expression as MemberExpression; | ||
return memberExpression.Member; | ||
|
||
default: | ||
return null; | ||
} | ||
} | ||
|
||
public static TAttribute GetAttribute<TAttribute>(MemberInfo memberInfo) | ||
where TAttribute: Attribute | ||
{ | ||
var attributes = memberInfo.GetCustomAttributes(typeof(TAttribute), false); | ||
if (attributes.Length > 0) | ||
return attributes[0] as TAttribute; | ||
|
||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq.Expressions; | ||
using System.Web.Mvc; | ||
using System.Web.Mvc.Html; | ||
|
||
namespace FlexLabs.Web.Html | ||
{ | ||
public static class EditorHelpers | ||
{ | ||
public static MvcHtmlString AutoEditorFieldFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, String templateName = null, Object additionalViewData = null) | ||
{ | ||
var label = html.LabelFor(expression); | ||
var validation = html.ValidationMessageFor(expression); | ||
|
||
MvcHtmlString editor = null; | ||
var member = ExpressionHelper.GetMemberInfo(expression); | ||
|
||
if (editor == null && ExpressionHelper.GetAttribute<AutoDropDownListAttribute>(member) != null) | ||
editor = html.AutoDropDownListFor(expression); | ||
if (editor == null && ExpressionHelper.GetAttribute<AutoTextBoxAttribute>(member) != null) | ||
editor = html.AutoTextBoxFor(expression); | ||
if (editor == null) | ||
editor = html.EditorFor(expression, templateName, additionalViewData); | ||
|
||
return MvcHtmlString.Create(label.ToString() + editor.ToString() + validation.ToString()); | ||
} | ||
|
||
public static MvcHtmlString AutoDropDownListFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Object htmlAttributes = null) | ||
{ | ||
var member = ExpressionHelper.GetMemberInfo(expression); | ||
var attr = ExpressionHelper.GetAttribute<AutoDropDownListAttribute>(member); | ||
if (attr == null) | ||
throw new InvalidOperationException("Missing AutoDropDownListAttribute on property"); | ||
|
||
var field = member.DeclaringType.GetField(attr.OptionsFieldName); | ||
if (field == null) | ||
throw new MissingFieldException($"Could not find field {attr.OptionsFieldName} on type {member.DeclaringType}"); | ||
if (!typeof(IEnumerable<SelectListItem>).IsAssignableFrom(field.FieldType)) | ||
throw new Exception($"Field {attr.OptionsFieldName} is not of type IEnumerable<SelectListItem>"); | ||
|
||
var model = html.ViewData.Model; | ||
var options = field.GetValue(model) as IEnumerable<SelectListItem>; | ||
return html.DropDownListFor(expression, options, attr.OptionsLabel, htmlAttributes); | ||
} | ||
|
||
public static MvcHtmlString AutoTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Object htmlAttributes = null) | ||
{ | ||
var member = ExpressionHelper.GetMemberInfo(expression); | ||
var attr = ExpressionHelper.GetAttribute<AutoTextBoxAttribute>(member); | ||
if (attr == null) | ||
throw new InvalidOperationException("Missing AutoTextBoxAttribute on property"); | ||
|
||
var attributes = htmlAttributes != null | ||
? (IDictionary<String, Object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) | ||
: new Dictionary<String, Object>(StringComparer.OrdinalIgnoreCase); | ||
|
||
if (attr.Type != null && !attributes.ContainsKey("type")) | ||
attributes["type"] = attr.Type; | ||
|
||
return html.TextBoxFor(expression, attr.Format, attributes); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using FlexLabs.Web.TablePager; | ||
using System; | ||
using System.Web.Mvc; | ||
using System.Web.Mvc.Html; | ||
|
||
namespace FlexLabs.Web.Html | ||
{ | ||
public static class PagingExtensions | ||
{ | ||
public static MvcHtmlString EnableFormSorting<TModel>(this HtmlHelper<TModel> html) | ||
where TModel : ITableModel | ||
{ | ||
var model = html.ViewData.Model; | ||
String result = String.Empty; | ||
|
||
if (model.SortBy != null) | ||
{ | ||
var sortBy = new TagBuilder("input"); | ||
sortBy.MergeAttribute("type", "hidden"); | ||
sortBy.MergeAttribute("name", "SortBy"); | ||
sortBy.MergeAttribute("value", model.SortBy.ToString()); | ||
result += sortBy.ToString(TagRenderMode.SelfClosing); | ||
} | ||
|
||
if (model.SortAsc != null) | ||
{ | ||
var sortAsc = new TagBuilder("input"); | ||
sortAsc.MergeAttribute("type", "hidden"); | ||
sortAsc.MergeAttribute("name", "SortAsc"); | ||
sortAsc.MergeAttribute("value", model.SortAsc.ToString()); | ||
result += sortAsc.ToString(TagRenderMode.SelfClosing); | ||
} | ||
|
||
if (model.FirstItemID != null) | ||
{ | ||
var firstItemID = new TagBuilder("input"); | ||
firstItemID.MergeAttribute("type", "hidden"); | ||
firstItemID.MergeAttribute("name", "FirstItemID"); | ||
firstItemID.MergeAttribute("value", model.FirstItemID.ToString()); | ||
result += firstItemID.ToString(TagRenderMode.SelfClosing); | ||
} | ||
|
||
return MvcHtmlString.Create(result); | ||
} | ||
|
||
public static MvcHtmlString PageSizer<TModel>(this HtmlHelper<TModel> html, String lavel = "Page Size: ", Int32[] pageSizes = null, Int32? currentSize = null) | ||
where TModel : ITableModel | ||
{ | ||
var label = html.LabelFor(m => m.PageSize); | ||
var editor = html.DropDownListFor(m => m.PageSize, TableModel.GetPageSizes(pageSizes, currentSize), new { onchange = "$(this).closest('form').submit();" }); | ||
var validation = html.ValidationMessageFor(m => m.PageSize); | ||
|
||
return MvcHtmlString.Create(label.ToString() + editor.ToString() + validation.ToString()); | ||
} | ||
|
||
public static MvcHtmlString Pager<TModel>(this HtmlHelper<TModel> html, PagedListData pageData, String label = "Page: ") | ||
where TModel : ITableModel | ||
{ | ||
var labelTag = new TagBuilder("label"); | ||
labelTag.SetInnerText(label); | ||
|
||
var ulTag = new TagBuilder("ul"); | ||
|
||
if (!pageData.CanSeeFirstPage()) | ||
ulTag.InnerHtml += PagerLink(1); | ||
|
||
foreach (var page in pageData.PageRange) | ||
{ | ||
if (page == pageData.PageNumber) | ||
ulTag.InnerHtml += $"<li class=\"page-current\">{page}</li>"; | ||
else | ||
ulTag.InnerHtml += PagerLink(page); | ||
} | ||
|
||
if (!pageData.CanSeeLastPage()) | ||
ulTag.InnerHtml += PagerLink(pageData.PageCount); | ||
|
||
var divTag = new TagBuilder("div"); | ||
divTag.AddCssClass("table-pager"); | ||
divTag.InnerHtml += labelTag.ToString(); | ||
divTag.InnerHtml += ulTag; | ||
return MvcHtmlString.Create(divTag.ToString()); | ||
} | ||
|
||
private static String PagerLink(Int32 pageNumber) | ||
{ | ||
return $"<li><button type=\"submit\" name=\"page\" value=\"{pageNumber}\">{pageNumber}</button></li>"; | ||
} | ||
|
||
public static MvcHtmlString Pager<TModel>(this HtmlHelper<TModel> html, String label = "Page: ") | ||
where TModel : ITableModel | ||
{ | ||
if (html.ViewData.Model?.PageItems?.PageCount == 0) | ||
return null; | ||
|
||
var pageItems = html.ViewData.Model.PageItems; | ||
var pageData = new PagedListData(pageItems.PageNumber, pageItems.PageSize, pageItems.PageCount, pageItems.TotalItemCount); | ||
return Pager(html, pageData, label); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using FlexLabs.Web.TablePager; | ||
using System.Collections.Generic; | ||
using System.Web.Mvc; | ||
|
||
namespace FlexLabs.Web.Html | ||
{ | ||
public static class TableExtensions | ||
{ | ||
public static MvcHtmlString TableHeader(this HtmlHelper html, IEnumerable<ITableHeader> headers) | ||
{ | ||
return TableHeader(html, new[] { headers }); | ||
} | ||
|
||
public static MvcHtmlString TableHeader(this HtmlHelper html, IEnumerable<IEnumerable<ITableHeader>> headersSet) | ||
{ | ||
var theadTag = new TagBuilder("thead"); | ||
|
||
foreach (var headers in headersSet) | ||
{ | ||
var rowTag = new TagBuilder("tr"); | ||
foreach (var iheader in headers) | ||
{ | ||
var thTag = new TagBuilder("th"); | ||
if (iheader.CssClass != null) | ||
thTag.AddCssClass(iheader.CssClass); | ||
if (iheader.ColSpan.HasValue) | ||
thTag.MergeAttribute("colspan", iheader.ColSpan.ToString()); | ||
if (iheader.RowSpan.HasValue) | ||
thTag.MergeAttribute("rowspan", iheader.RowSpan.ToString()); | ||
|
||
if (iheader is CustomTableHeader) | ||
{ | ||
thTag.InnerHtml = (iheader as CustomTableHeader).Content(html.ViewData.Model).ToString(); | ||
} | ||
else | ||
{ | ||
var header = iheader as TableHeader; | ||
if (header.Value != null) | ||
{ | ||
var buttonTag = new TagBuilder("button"); | ||
buttonTag.MergeAttribute("type", "submit"); | ||
buttonTag.MergeAttribute("name", "changeSort"); | ||
buttonTag.MergeAttribute("value", header.Value.ToString()); | ||
if (header.ToolTip != null) | ||
buttonTag.MergeAttribute("title", header.ToolTip); | ||
buttonTag.SetInnerText(header.Title); | ||
thTag.InnerHtml = buttonTag.ToString(); | ||
} | ||
else if (header.ToolTip != null) | ||
{ | ||
var span = new TagBuilder("span"); | ||
span.MergeAttribute("title", header.ToolTip); | ||
span.SetInnerText(header.Title); | ||
thTag.InnerHtml = span.ToString(); | ||
} | ||
else | ||
{ | ||
thTag.SetInnerText(header.Title); | ||
} | ||
} | ||
|
||
rowTag.InnerHtml += thTag.ToString(); | ||
} | ||
theadTag.InnerHtml += rowTag.ToString(); | ||
} | ||
|
||
return MvcHtmlString.Create(theadTag.ToString()); | ||
} | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
Oops, something went wrong.