I have saved a couple of code snippets lately and just wanted to add them to the blog too. This one enables “focus out” unobtrusive validation. I use this in a couple of forms on the site. Part of this gist also has a little code where I was messing around with “remote” validation to get it to work with the focus out validation – of course, I wasn’t thinking, just geeking out. The remote stuff is already baked in to jquery validation and I already had code to handle the focus out portion, so it wasn’t really worth the time, but I didn’t spend much on it. Anyway, the code:
window.Em = window.Em || {}; Em = { setFocusOutValidation: function (form) { var s = $.data(form, "validator").settings; s.onfocusout = function (element) { if ($(element).val().length > 0) { $(element).valid(); } }; s.showErrors = function (map, list) { this.defaultShowErrors(); if (list && list.length > 0) { for (prop in map) { $("#" + prop).focus(); } } Em.displayValidationSummaryErrors(list); }; return s; }, displayValidationSummaryErrors: function (list) { $("[data-valmsg-summary]") .removeClass("validation-summary-valid") .addClass("validation-summary-errors"); $("[data-valmsg-summary] ul").html(""); $.each(list, function (idx, data) { $("[data-valmsg-summary] ul").append($("<li></li>") .html(data.message)); }); } }
The focus out validation will check if the field is valid (also remotely) and if not, the focus will stay on the invalid field. Sometimes it can get a little wonky, but for the most part it works well. Typically when it doesn’t seem to “work” it is because the validation is setup backwards, like comparing a “new password” to the “confirm password”, rather than the other way around.
The next gist is a Telerik MVC grid extension I started messing with to handle filtering. Turns out I was making it harder than necessary, and there was already an extension method in the NopCommerce codebase. Oh well, here it is anyway:
public static IList<T> ApplyFilter<T>(this IList<T> list, FilterDescriptor filter) { // We wont allow filtering on anything but string type properties if (filter.MemberType != typeof(string)) throw new ArgumentException(@"Filtering is only allowed for properties with a type of 'string'."); var value = filter.Value.ToString(); switch (filter.Operator) { case FilterOperator.IsEqualTo: list = list.Where(x => { var propertyValue = x.GetType() .GetProperty(filter.Member) .GetValue(x, null); return String.Equals((string)propertyValue, value, StringComparison.InvariantCultureIgnoreCase); }).ToList(); break; case FilterOperator.IsNotEqualTo: list = list.Where(x => { var propertyValue = x.GetType() .GetProperty(filter.Member).GetValue(x, null); return String.Equals((string)propertyValue, value, StringComparison.InvariantCultureIgnoreCase) == false; }).ToList(); break; case FilterOperator.StartsWith: list = list.Where(x => { var propertyValue = x.GetType() .GetProperty(filter.Member).GetValue(x, null); return ((string)propertyValue).StartsWith(value, StringComparison.InvariantCultureIgnoreCase); }).ToList(); break; case FilterOperator.Contains: list = list.Where(x => { var propertyValue = x.GetType() .GetProperty(filter.Member).GetValue(x, null); return ((string)propertyValue).IndexOf(value, StringComparison.InvariantCultureIgnoreCase) > -1; }).ToList(); break; case FilterOperator.EndsWith: list = list.Where(x => { var propertyValue = x.GetType() .GetProperty(filter.Member).GetValue(x, null); return ((string)propertyValue).EndsWith(value, StringComparison.InvariantCultureIgnoreCase); }).ToList(); break; } return list; }
The last one is just a little quickie example of how to select data attributes with jQuery:
var d = $("input[data-toggle-class]"); $.each(d, function (idx, data) { console.log(idx, data); });
I was originally looking for a way to select a wildcard in the data attribute, but I couldn’t get it working. Anyway, this works fine – though I did not actually end up using it. 🙂