Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 36 additions & 22 deletions GridMvc.Site/Scripts/gridmvc.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,12 @@ GridMvc = (function ($) {
//determine widget container:
var widgetContainer = $(this).find(".grid-popup-widget");
//onRender target widget
if (typeof (widget.onRender) != 'undefined')
if (typeof (widget.onRender) != 'undefined') {
widget.onRender(widgetContainer, self.lang, columnType, filterDataObj, function (values) {
self.closeOpenedPopups();
self.applyFilterValues(filterUrl, columnName, values, false);
}, $.parseJSON(widgetData));
}
//adding 'clear filter' button if needed:
if ($(this).find(".grid-filter-btn").hasClass("filtered") && widget.showClearFilterButton()) {
var inner = $(this).find(".grid-popup-additional");
Expand Down Expand Up @@ -388,13 +389,16 @@ GridMvc.lang.en = {
applyFilterButtonText: "Apply",
filterSelectTypes: {
Equals: "Equals",
NotEquals: "Is not equal to",
StartsWith: "StartsWith",
Contains: "Contains",
EndsWith: "EndsWith",
GreaterThan: "Greater than",
LessThan: "Less than",
GreaterThanOrEquals: "Greater than or equals",
LessThanOrEquals: "Less than or equals"
LessThanOrEquals: "Less than or equals",
Null: "Is NULL",
NotNull: "Is not NULL"
},
code: 'en',
boolTrueLabel: "Yes",
Expand All @@ -403,7 +407,7 @@ GridMvc.lang.en = {
};
/***
* ============= FILTER WIDGETS =============
* Filter widget allows onRender custom filter user interface for different columns.
* Filter widget allows onRender custom filter user interface for different columns.
* For example if your added column is of type "DateTime" - widget can onRender calendar for picking filter value.
* This script provider base widget for default .Net types: System.String, System.Int32, System.Decimal etc.
* If you want to provide custom filter functionality - you can assign your own widget type for column and write widget for this types.
Expand Down Expand Up @@ -458,9 +462,12 @@ TextFilterWidget = (function ($) {
<label>' + this.lang.filterTypeLabel + '</label>\
<select class="grid-filter-type form-control">\
<option value="1" ' + (this.value.filterType == "1" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Equals + '</option>\
<option value="9" ' + (this.value.filterType == "9" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.NotEquals + '</option>\
<option value="2" ' + (this.value.filterType == "2" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Contains + '</option>\
<option value="3" ' + (this.value.filterType == "3" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.StartsWith + '</option>\
<option value="4" ' + (this.value.filterType == "4" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.EndsWith + '</option>\
<option value="10" ' + (this.value.filterType == "10" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Null + '</option>\
<option value="11" ' + (this.value.filterType == "11" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.NotNull + '</option>\
</select>\
</div>\
<div class="form-group">\
Expand Down Expand Up @@ -517,7 +524,7 @@ NumberFilterWidget = (function ($) {

numberFilterWidget.prototype.onShow = function () {
var textBox = this.container.find(".grid-filter-input");
if (textBox.length <= 0) return;
if (textBox.length <= 0) return;
textBox.focus();
};

Expand All @@ -538,6 +545,8 @@ NumberFilterWidget = (function ($) {
<option value="1" ' + (this.value.filterType == "1" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Equals + '</option>\
<option value="5" ' + (this.value.filterType == "5" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.GreaterThan + '</option>\
<option value="6" ' + (this.value.filterType == "6" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.LessThan + '</option>\
<option value="10" ' + (this.value.filterType == "10" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Null + '</option>\
<option value="11" ' + (this.value.filterType == "11" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.NotNull + '</option>\
</select>\
</div>\
<div class="form-group">\
Expand Down Expand Up @@ -626,10 +635,15 @@ DateTimeFilterWidget = (function ($) {
<option value="1" ' + (this.value.filterType == "1" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Equals + '</option>\
<option value="5" ' + (this.value.filterType == "5" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.GreaterThan + '</option>\
<option value="6" ' + (this.value.filterType == "6" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.LessThan + '</option>\
<option value="10" ' + (this.value.filterType == "10" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.Null + '</option>\
<option value="11" ' + (this.value.filterType == "11" ? "selected=\"selected\"" : "") + '>' + this.lang.filterSelectTypes.NotNull + '</option>\
</select>\
</div>' +
(this.datePickerIncluded ?
'<div class="grid-filter-datepicker"></div>'
'<div class="grid-filter-datepicker"></div>\
<div class="grid-filter-buttons">\
<input type="button" class="btn btn-primary grid-apply" value="' + this.lang.applyFilterButtonText + '" />\
</div>'
:
'<div class="form-group">\
<label>' + this.lang.filterValueLabel + '</label>\
Expand All @@ -642,25 +656,25 @@ DateTimeFilterWidget = (function ($) {
//if window.jQueryUi included:
if (this.datePickerIncluded) {
var datePickerOptions = this.data || {};
datePickerOptions.format = datePickerOptions.format || "yyyy-mm-dd";
datePickerOptions.format = datePickerOptions.format || "yy-mm-dd";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little bit of a shame to go from an unambiguous default to an ambiguous one.
10-11-12 could be a lot of dates 2010-11-12 is the 12th of november

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jQuery is special. yy-mm-dd is 2010-11-12. yyyy-mm-dd is 20102010-11-12.

datePickerOptions.language = datePickerOptions.language || this.lang.code;
datePickerOptions.onSelect = function (date, ev) {
var type = $context.container.find(".grid-filter-type").val();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want some validation that type is one of the date comparisons here? Or are we confident that onSelect will only fire when it is?

var date = ev.input.datepicker("getDate");
var newValue = $.datepicker.formatDate(datePickerOptions.format, date);
var filterValues = [{ filterType: type, filterValue: newValue }];
$context.cb(filterValues);
}

var $context = this;
var dateContainer = this.container.find(".grid-filter-datepicker");
dateContainer.datepicker(datePickerOptions).on('changeDate', function (ev) {
var type = $context.container.find(".grid-filter-type").val();
//if (type == "1") {
// var tomorrow = new Date(ev.getTime());
// tomorrow.setDate(ev.getDate() + 1);
// var filterValues = [{ filterType: type, filterValue: ev.format() }];
//}
//else{
var filterValues = [{ filterType: type, filterValue: ev.format() }];
//}
$context.cb(filterValues);
});
if (this.value.filterValue)
dateContainer.datepicker('update', this.value.filterValue);
dateContainer.datepicker(datePickerOptions);
if (this.value.filterValue) {
var date = $.datepicker.parseDate(datePickerOptions.format);
if (date) {
dateContainer.datepicker('update', this.value.filterValue);
}
}
}
};

Expand Down Expand Up @@ -713,7 +727,7 @@ BooleanFilterWidget = (function ($) {
this.container.append(html);
};

booleanFilterWidget.prototype.registerEvents = function () {
booleanFilterWidget.prototype.registerEvents = function () {
var $context = this;
var applyBtn = this.container.find(".grid-filter-choose");
applyBtn.click(function () {
Expand All @@ -733,4 +747,4 @@ BooleanFilterWidget = (function ($) {
$(".grid-mvc").gridmvc();
});
});
})(window.jQuery);
})(window.jQuery);
2 changes: 1 addition & 1 deletion GridMvc.Site/Scripts/gridmvc.min.js

Large diffs are not rendered by default.

45 changes: 21 additions & 24 deletions GridMvc/Filtering/DefaultColumnFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,20 @@ public DefaultColumnFilter(Expression<Func<T, TData>> expression)
public IQueryable<T> ApplyFilter(IQueryable<T> items, ColumnFilterValue value)
{
if (value == ColumnFilterValue.Null)
throw new ArgumentNullException("value");
throw new ArgumentNullException(nameof(value));

var pi = (PropertyInfo) ((MemberExpression) _expression.Body).Member;
PropertyInfo pi = (PropertyInfo)((MemberExpression)_expression.Body).Member;
Expression<Func<T, bool>> expr = GetFilterExpression(pi, value);
if (expr == null)
return items;
return items.Where(expr);
return expr == null ? items : items.Where(expr);
}

#endregion

private Expression<Func<T, bool>> GetFilterExpression(PropertyInfo pi, ColumnFilterValue value)
{
//detect nullable
bool isNullable = pi.PropertyType.IsGenericType &&
pi.PropertyType.GetGenericTypeDefinition() == typeof (Nullable<>);
var isNullable = pi.PropertyType.IsGenericType &&
pi.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
//get target type:
Type targetType = isNullable ? Nullable.GetUnderlyingType(pi.PropertyType) : pi.PropertyType;

Expand All @@ -49,29 +47,28 @@ private Expression<Func<T, bool>> GetFilterExpression(PropertyInfo pi, ColumnFil
ParameterExpression entityParam = _expression.Parameters[0];
//support nullable types:
Expression firstExpr = isNullable
? Expression.Property(_expression.Body, pi.PropertyType.GetProperty("Value"))
: _expression.Body;
? Expression.Property(_expression.Body, pi.PropertyType.GetProperty("Value"))
: _expression.Body;

Expression binaryExpression = filterType.GetFilterExpression(firstExpr, value.FilterValue, value.FilterType);
if (binaryExpression == null) return null;

if (targetType == typeof (string))
{
//check for strings, they may be NULL
//It's ok for ORM, but throw exception in linq to objects. Additional check string on null
Expression nullExpr = Expression.NotEqual(_expression.Body, Expression.Constant(null));
binaryExpression = Expression.AndAlso(nullExpr, binaryExpression);
}
else if (isNullable)
{
//add additional filter condition for check items on NULL with invoring "HasValue" method.
//for example: result of this expression will like - c=> c.HasValue && c.Value = 3
MemberExpression hasValueExpr = Expression.Property(_expression.Body,
pi.PropertyType.GetProperty("HasValue"));
binaryExpression = Expression.AndAlso(hasValueExpr, binaryExpression);
if (value.FilterType != GridFilterType.Null) {
if (targetType == typeof(string)) {
//check for strings, they may be NULL
//It's ok for ORM, but throw exception in linq to objects. Additional check string on null
Expression nullExpr = Expression.NotEqual(_expression.Body, Expression.Constant(null));
binaryExpression = Expression.AndAlso(nullExpr, binaryExpression);
} else if (isNullable) {
//add additional filter condition for check items on NULL with invoring "HasValue" method.
//for example: result of this expression will like - c=> c.HasValue && c.Value = 3
MemberExpression hasValueExpr = Expression.Property(_expression.Body,
pi.PropertyType.GetProperty("HasValue"));
binaryExpression = Expression.AndAlso(hasValueExpr, binaryExpression);
}
}
//return filter expression
return Expression.Lambda<Func<T, bool>>(binaryExpression, entityParam);
}
}
}
}
7 changes: 5 additions & 2 deletions GridMvc/Filtering/GridFilterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public enum GridFilterType
GreaterThan = 5,
LessThan = 6,
GreaterThanOrEquals = 7,
LessThanOrEquals = 8
LessThanOrEquals = 8,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mix of tabs and spaces, could we please keep this consistant within a file.

NotEqual = 9,
Null = 10,
NotNull = 11
}
}
}
16 changes: 7 additions & 9 deletions GridMvc/Filtering/QueryStringFilterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,25 @@ public QueryStringFilterSettings(HttpContext context)

#endregion

private ColumnFilterValue CreateColumnData(string queryParameterValue)
private static ColumnFilterValue CreateColumnData(string queryParameterValue)
{
if (string.IsNullOrEmpty(queryParameterValue))
return ColumnFilterValue.Null;

string[] data = queryParameterValue.Split(new[] {FilterDataDelimeter}, StringSplitOptions.RemoveEmptyEntries);
if (data.Length != 3)
var data = queryParameterValue.Split(new[] {FilterDataDelimeter}, StringSplitOptions.RemoveEmptyEntries);
if (data.Length > 3 || data.Length < 2) {
return ColumnFilterValue.Null;
}
GridFilterType type;
if (!Enum.TryParse(data[1], true, out type))
type = GridFilterType.Equals;

return new ColumnFilterValue {ColumnName = data[0], FilterType = type, FilterValue = data[2]};
return new ColumnFilterValue {ColumnName = data[0], FilterType = type, FilterValue = data.Length == 3 ? data[2] : ""};
}

#region IGridFilterSettings Members

public IFilterColumnCollection FilteredColumns
{
get { return _filterValues; }
}
public IFilterColumnCollection FilteredColumns => _filterValues;

public bool IsInitState
{
Expand All @@ -75,4 +73,4 @@ public bool IsInitState

#endregion
}
}
}
11 changes: 6 additions & 5 deletions GridMvc/Filtering/Types/DateTimeFilterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ namespace GridMvc.Filtering.Types
/// </summary>
internal sealed class DateTimeFilterType : FilterTypeBase
{
public override Type TargetType
{
public override Type TargetType {
get { return typeof(DateTime); }
}

Expand Down Expand Up @@ -42,13 +41,15 @@ public override Expression GetFilterExpression(Expression leftExpr, string value
/// <returns></returns>
public override GridFilterType GetValidType(GridFilterType type)
{
switch (type)
{
switch (type) {
case GridFilterType.Equals:
case GridFilterType.GreaterThan:
case GridFilterType.GreaterThanOrEquals:
case GridFilterType.LessThan:
case GridFilterType.LessThanOrEquals:
case GridFilterType.NotEqual:
case GridFilterType.NotNull:
case GridFilterType.Null:
return type;
default:
return GridFilterType.Equals;
Expand All @@ -63,4 +64,4 @@ public override object GetTypedValue(string value)
return date;
}
}
}
}
31 changes: 2 additions & 29 deletions GridMvc/Filtering/Types/DecimalFilterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,7 @@ namespace GridMvc.Filtering.Types
/// <summary>
/// Object contains some logic for filtering decimal columns
/// </summary>
internal sealed class DecimalFilterType : FilterTypeBase
internal sealed class DecimalFilterType : NumberFilterType<Decimal>
{
public override Type TargetType
{
get { return typeof (Decimal); }
}

public override GridFilterType GetValidType(GridFilterType type)
{
switch (type)
{
case GridFilterType.Equals:
case GridFilterType.GreaterThan:
case GridFilterType.LessThan:
case GridFilterType.GreaterThanOrEquals:
case GridFilterType.LessThanOrEquals:
return type;
default:
return GridFilterType.Equals;
}
}

public override object GetTypedValue(string value)
{
decimal dec;
if (!decimal.TryParse(value, out dec))
return null;
return dec;
}
}
}
}
31 changes: 2 additions & 29 deletions GridMvc/Filtering/Types/DoubleFilterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,7 @@ namespace GridMvc.Filtering.Types
/// <summary>
/// Object contains some logic for filtering Double columns
/// </summary>
internal sealed class DoubleFilterType : FilterTypeBase
internal sealed class DoubleFilterType : NumberFilterType<Double>
{
public override Type TargetType
{
get { return typeof (Double); }
}

public override GridFilterType GetValidType(GridFilterType type)
{
switch (type)
{
case GridFilterType.Equals:
case GridFilterType.GreaterThan:
case GridFilterType.LessThan:
case GridFilterType.GreaterThanOrEquals:
case GridFilterType.LessThanOrEquals:
return type;
default:
return GridFilterType.Equals;
}
}

public override object GetTypedValue(string value)
{
double db;
if (!double.TryParse(value, out db))
return null;
return db;
}
}
}
}
Loading