Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » General » Downloads
 
Add your own
alternative version

MVC4 Mobile Friendly Web Applications

, 13 Sep 2012
Mobile enable your ASP.NET MVC4 Web applications
MvcMobileFriendly.zip
MvcMobileFriendly
MvcDesktop.v11.suo
MvcDesktop
App_Start
Content
images
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
themes
base
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
minified
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
Controllers
favicon.ico
Filters
Global.asax
Images
accent.png
ajax-loader.gif
ajax-loader.png
bullet.png
heroAccent.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
orderedList0.png
orderedList1.png
orderedList2.png
orderedList3.png
orderedList4.png
orderedList5.png
orderedList6.png
orderedList7.png
orderedList8.png
orderedList9.png
Models
MvcDesktop.csproj.user
Properties
Scripts
Views
Account
Home
Shared
packages
DotNetOpenAuth.AspNet.4.0.3.12153
DotNetOpenAuth.AspNet.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.AspNet.dll
DotNetOpenAuth.Core.4.0.3.12153
DotNetOpenAuth.Core.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.Core.dll
DotNetOpenAuth.OAuth.Consumer.4.0.3.12153
DotNetOpenAuth.OAuth.Consumer.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.OAuth.Consumer.dll
DotNetOpenAuth.OAuth.Core.4.0.3.12153
DotNetOpenAuth.OAuth.Core.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.OAuth.dll
DotNetOpenAuth.OpenId.Core.4.0.3.12153
DotNetOpenAuth.OpenId.Core.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.OpenId.dll
DotNetOpenAuth.OpenId.RelyingParty.4.0.3.12153
DotNetOpenAuth.OpenId.RelyingParty.4.0.3.12153.nupkg
lib
net40-full
DotNetOpenAuth.OpenId.RelyingParty.dll
EntityFramework.5.0.0
Content
App.config.transform
Web.config.transform
EntityFramework.5.0.0.nupkg
lib
net40
EntityFramework.dll
net45
EntityFramework.dll
tools
EntityFramework.PowerShell.dll
EntityFramework.PowerShell.Utility.dll
EntityFramework.PS3.psd1
EntityFramework.psd1
EntityFramework.psm1
init.ps1
install.ps1
migrate.exe
jQuery.1.7.1.1
Content
Scripts
jQuery.1.7.1.1.nupkg
Tools
common.ps1
install.ps1
uninstall.ps1
jquery.mobile.1.1.1
content
Content
images
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
Scripts
jquery.mobile.1.1.1.nupkg
jQuery.UI.Combined.1.8.20.1
Content
Content
themes
base
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
minified
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
Scripts
jQuery.UI.Combined.1.8.20.1.nupkg
jQuery.Validation.1.9.0.1
Content
Scripts
jQuery.Validation.1.9.0.1.nupkg
knockoutjs.2.1.0
Content
Scripts
knockoutjs.2.1.0.nupkg
Microsoft.AspNet.Mvc.4.0.20710.0
lib
net40
System.Web.Mvc.dll
Microsoft.AspNet.Mvc.4.0.20710.0.nupkg
Microsoft.AspNet.Razor.2.0.20710.0
lib
net40
System.Web.Razor.dll
Microsoft.AspNet.Razor.2.0.20710.0.nupkg
Microsoft.AspNet.Web.Optimization.1.0.0
lib
net40
System.Web.Optimization.dll
Microsoft.AspNet.Web.Optimization.1.0.0.nupkg
Microsoft.AspNet.WebApi.4.0.20710.0
Microsoft.AspNet.WebApi.4.0.20710.0.nupkg
Microsoft.AspNet.WebApi.Client.4.0.20710.0
lib
net40
System.Net.Http.Formatting.dll
Microsoft.AspNet.WebApi.Client.4.0.20710.0.nupkg
Microsoft.AspNet.WebApi.Core.4.0.20710.0
content
web.config.transform
lib
net40
System.Web.Http.dll
Microsoft.AspNet.WebApi.Core.4.0.20710.0.nupkg
Microsoft.AspNet.WebApi.WebHost.4.0.20710.0
lib
net40
System.Web.Http.WebHost.dll
Microsoft.AspNet.WebApi.WebHost.4.0.20710.0.nupkg
Microsoft.AspNet.WebPages.2.0.20710.0
lib
net40
System.Web.Helpers.dll
System.Web.WebPages.Deployment.dll
System.Web.WebPages.dll
System.Web.WebPages.Razor.dll
Microsoft.AspNet.WebPages.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.Data.2.0.20710.0
lib
net40
WebMatrix.Data.dll
Microsoft.AspNet.WebPages.Data.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.OAuth.2.0.20710.0
lib
net40
Microsoft.Web.WebPages.OAuth.dll
Microsoft.AspNet.WebPages.OAuth.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.WebData.2.0.20710.0
lib
net40
WebMatrix.WebData.dll
Microsoft.AspNet.WebPages.WebData.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Ajax.2.0.20710.0
Content
Scripts
Microsoft.jQuery.Unobtrusive.Ajax.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Validation.2.0.20710.0
Content
Scripts
Microsoft.jQuery.Unobtrusive.Validation.2.0.20710.0.nupkg
Microsoft.Net.Http.2.0.20710.0
lib
net40
System.Net.Http.dll
System.Net.Http.WebRequest.dll
net45
_._
Microsoft.Net.Http.2.0.20710.0.nupkg
Microsoft.Web.Infrastructure.1.0.0.0
lib
net40
Microsoft.Web.Infrastructure.dll
Microsoft.Web.Infrastructure.1.0.0.0.nupkg
Modernizr.2.5.3
Content
Scripts
Modernizr.2.5.3.nupkg
Newtonsoft.Json.4.5.6
lib
net40
Newtonsoft.Json.dll
Newtonsoft.Json.4.5.6.nupkg
WebGrease.1.1.0
lib
Antlr3.Runtime.dll
WebGrease.dll
tools
WG.exe
WebGrease.1.1.0.nupkg
MvcMobileFriendlyV1_1-noexe.zip
MvcDesktop.v11.suo
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
favicon.ico
Global.asax
accent.png
ajax-loader.gif
ajax-loader.png
bullet.png
heroAccent.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
orderedList0.png
orderedList1.png
orderedList2.png
orderedList3.png
orderedList4.png
orderedList5.png
orderedList6.png
orderedList7.png
orderedList8.png
orderedList9.png
MvcDesktop.csproj.user
DotNetOpenAuth.AspNet.4.0.3.12153.nupkg
DotNetOpenAuth.Core.4.0.3.12153.nupkg
DotNetOpenAuth.OAuth.Consumer.4.0.3.12153.nupkg
DotNetOpenAuth.OAuth.Core.4.0.3.12153.nupkg
DotNetOpenAuth.OpenId.Core.4.0.3.12153.nupkg
DotNetOpenAuth.OpenId.RelyingParty.4.0.3.12153.nupkg
App.config.transform
Web.config.transform
EntityFramework.5.0.0.nupkg
EntityFramework.PS3.psd1
EntityFramework.psd1
EntityFramework.psm1
init.ps1
install.ps1
jQuery.1.7.1.1.nupkg
common.ps1
install.ps1
uninstall.ps1
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
jquery.mobile.1.1.1.nupkg
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
jQuery.UI.Combined.1.8.20.1.nupkg
jQuery.Validation.1.9.0.1.nupkg
knockoutjs.2.1.0.nupkg
Microsoft.AspNet.Mvc.4.0.20710.0.nupkg
Microsoft.AspNet.Razor.2.0.20710.0.nupkg
Microsoft.AspNet.Web.Optimization.1.0.0.nupkg
Microsoft.AspNet.WebApi.4.0.20710.0.nupkg
Microsoft.AspNet.WebApi.Client.4.0.20710.0.nupkg
web.config.transform
Microsoft.AspNet.WebApi.Core.4.0.20710.0.nupkg
Microsoft.AspNet.WebApi.WebHost.4.0.20710.0.nupkg
Microsoft.AspNet.WebPages.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.Data.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.OAuth.2.0.20710.0.nupkg
Microsoft.AspNet.WebPages.WebData.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Ajax.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Validation.2.0.20710.0.nupkg
_._
Microsoft.Net.Http.2.0.20710.0.nupkg
Microsoft.Web.Infrastructure.1.0.0.0.nupkg
Modernizr.2.5.3.nupkg
Newtonsoft.Json.4.5.6.nupkg
WebGrease.1.1.0.nupkg
MvcMobileFriendlyV1_1.zip
MvcDesktop.v11.suo
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
favicon.ico
Global.asax
accent.png
ajax-loader.gif
ajax-loader.png
bullet.png
heroAccent.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
orderedList0.png
orderedList1.png
orderedList2.png
orderedList3.png
orderedList4.png
orderedList5.png
orderedList6.png
orderedList7.png
orderedList8.png
orderedList9.png
MvcDesktop.csproj.user
DotNetOpenAuth.AspNet.4.0.3.12153.nupkg
DotNetOpenAuth.AspNet.dll
DotNetOpenAuth.Core.4.0.3.12153.nupkg
DotNetOpenAuth.Core.dll
DotNetOpenAuth.OAuth.Consumer.4.0.3.12153.nupkg
DotNetOpenAuth.OAuth.Consumer.dll
DotNetOpenAuth.OAuth.Core.4.0.3.12153.nupkg
DotNetOpenAuth.OAuth.dll
DotNetOpenAuth.OpenId.Core.4.0.3.12153.nupkg
DotNetOpenAuth.OpenId.dll
DotNetOpenAuth.OpenId.RelyingParty.4.0.3.12153.nupkg
DotNetOpenAuth.OpenId.RelyingParty.dll
App.config.transform
Web.config.transform
EntityFramework.5.0.0.nupkg
EntityFramework.dll
EntityFramework.dll
EntityFramework.PowerShell.dll
EntityFramework.PowerShell.Utility.dll
EntityFramework.PS3.psd1
EntityFramework.psd1
EntityFramework.psm1
init.ps1
install.ps1
migrate.exe
jQuery.1.7.1.1.nupkg
common.ps1
install.ps1
uninstall.ps1
ajax-loader.gif
ajax-loader.png
icons-18-black.png
icons-18-white.png
icons-36-black.png
icons-36-white.png
jquery.mobile.1.1.1.nupkg
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
jQuery.UI.Combined.1.8.20.1.nupkg
jQuery.Validation.1.9.0.1.nupkg
knockoutjs.2.1.0.nupkg
System.Web.Mvc.dll
Microsoft.AspNet.Mvc.4.0.20710.0.nupkg
System.Web.Razor.dll
Microsoft.AspNet.Razor.2.0.20710.0.nupkg
System.Web.Optimization.dll
Microsoft.AspNet.Web.Optimization.1.0.0.nupkg
Microsoft.AspNet.WebApi.4.0.20710.0.nupkg
System.Net.Http.Formatting.dll
Microsoft.AspNet.WebApi.Client.4.0.20710.0.nupkg
web.config.transform
System.Web.Http.dll
Microsoft.AspNet.WebApi.Core.4.0.20710.0.nupkg
System.Web.Http.WebHost.dll
Microsoft.AspNet.WebApi.WebHost.4.0.20710.0.nupkg
System.Web.Helpers.dll
System.Web.WebPages.Deployment.dll
System.Web.WebPages.dll
System.Web.WebPages.Razor.dll
Microsoft.AspNet.WebPages.2.0.20710.0.nupkg
WebMatrix.Data.dll
Microsoft.AspNet.WebPages.Data.2.0.20710.0.nupkg
Microsoft.Web.WebPages.OAuth.dll
Microsoft.AspNet.WebPages.OAuth.2.0.20710.0.nupkg
WebMatrix.WebData.dll
Microsoft.AspNet.WebPages.WebData.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Ajax.2.0.20710.0.nupkg
Microsoft.jQuery.Unobtrusive.Validation.2.0.20710.0.nupkg
System.Net.Http.dll
System.Net.Http.WebRequest.dll
_._
Microsoft.Net.Http.2.0.20710.0.nupkg
Microsoft.Web.Infrastructure.dll
Microsoft.Web.Infrastructure.1.0.0.0.nupkg
Modernizr.2.5.3.nupkg
Newtonsoft.Json.dll
Newtonsoft.Json.4.5.6.nupkg
Antlr3.Runtime.dll
WebGrease.dll
WG.exe
WebGrease.1.1.0.nupkg
/*!
** Unobtrusive validation support library for jQuery and jQuery Validate
** Copyright (C) Microsoft Corporation. All rights reserved.
*/

/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global document: false, jQuery: false */

(function ($) {
    var $jQval = $.validator,
        adapters,
        data_validation = "unobtrusiveValidation";

    function setValidationValues(options, ruleName, value) {
        options.rules[ruleName] = value;
        if (options.message) {
            options.messages[ruleName] = options.message;
        }
    }

    function splitAndTrim(value) {
        return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
    }

    function escapeAttributeValue(value) {
        // As mentioned on http://api.jquery.com/category/selectors/
        return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
    }

    function getModelPrefix(fieldName) {
        return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
    }

    function appendModelPrefix(value, prefix) {
        if (value.indexOf("*.") === 0) {
            value = value.replace("*.", prefix);
        }
        return value;
    }

    function onError(error, inputElement) {  // 'this' is the form element
        var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
            replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;

        container.removeClass("field-validation-valid").addClass("field-validation-error");
        error.data("unobtrusiveContainer", container);

        if (replace) {
            container.empty();
            error.removeClass("input-validation-error").appendTo(container);
        }
        else {
            error.hide();
        }
    }

    function onErrors(event, validator) {  // 'this' is the form element
        var container = $(this).find("[data-valmsg-summary=true]"),
            list = container.find("ul");

        if (list && list.length && validator.errorList.length) {
            list.empty();
            container.addClass("validation-summary-errors").removeClass("validation-summary-valid");

            $.each(validator.errorList, function () {
                $("<li />").html(this.message).appendTo(list);
            });
        }
    }

    function onSuccess(error) {  // 'this' is the form element
        var container = error.data("unobtrusiveContainer"),
            replace = $.parseJSON(container.attr("data-valmsg-replace"));

        if (container) {
            container.addClass("field-validation-valid").removeClass("field-validation-error");
            error.removeData("unobtrusiveContainer");

            if (replace) {
                container.empty();
            }
        }
    }

    function onReset(event) {  // 'this' is the form element
        var $form = $(this);
        $form.data("validator").resetForm();
        $form.find(".validation-summary-errors")
            .addClass("validation-summary-valid")
            .removeClass("validation-summary-errors");
        $form.find(".field-validation-error")
            .addClass("field-validation-valid")
            .removeClass("field-validation-error")
            .removeData("unobtrusiveContainer")
            .find(">*")  // If we were using valmsg-replace, get the underlying error
                .removeData("unobtrusiveContainer");
    }

    function validationInfo(form) {
        var $form = $(form),
            result = $form.data(data_validation),
            onResetProxy = $.proxy(onReset, form);

        if (!result) {
            result = {
                options: {  // options structure passed to jQuery Validate's validate() method
                    errorClass: "input-validation-error",
                    errorElement: "span",
                    errorPlacement: $.proxy(onError, form),
                    invalidHandler: $.proxy(onErrors, form),
                    messages: {},
                    rules: {},
                    success: $.proxy(onSuccess, form)
                },
                attachValidation: function () {
                    $form
                        .unbind("reset." + data_validation, onResetProxy)
                        .bind("reset." + data_validation, onResetProxy)
                        .validate(this.options);
                },
                validate: function () {  // a validation function that is called by unobtrusive Ajax
                    $form.validate();
                    return $form.valid();
                }
            };
            $form.data(data_validation, result);
        }

        return result;
    }

    $jQval.unobtrusive = {
        adapters: [],

        parseElement: function (element, skipAttach) {
            /// <summary>
            /// Parses a single HTML element for unobtrusive validation attributes.
            /// </summary>
            /// <param name="element" domElement="true">The HTML element to be parsed.</param>
            /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
            /// validation to the form. If parsing just this single element, you should specify true.
            /// If parsing several elements, you should specify false, and manually attach the validation
            /// to the form when you are finished. The default is false.</param>
            var $element = $(element),
                form = $element.parents("form")[0],
                valInfo, rules, messages;

            if (!form) {  // Cannot do client-side validation without a form
                return;
            }

            valInfo = validationInfo(form);
            valInfo.options.rules[element.name] = rules = {};
            valInfo.options.messages[element.name] = messages = {};

            $.each(this.adapters, function () {
                var prefix = "data-val-" + this.name,
                    message = $element.attr(prefix),
                    paramValues = {};

                if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
                    prefix += "-";

                    $.each(this.params, function () {
                        paramValues[this] = $element.attr(prefix + this);
                    });

                    this.adapt({
                        element: element,
                        form: form,
                        message: message,
                        params: paramValues,
                        rules: rules,
                        messages: messages
                    });
                }
            });

            $.extend(rules, { "__dummy__": true });

            if (!skipAttach) {
                valInfo.attachValidation();
            }
        },

        parse: function (selector) {
            /// <summary>
            /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
            /// with the [data-val=true] attribute value and enables validation according to the data-val-*
            /// attribute values.
            /// </summary>
            /// <param name="selector" type="String">Any valid jQuery selector.</param>
            var $forms = $(selector)
                .parents("form")
                .andSelf()
                .add($(selector).find("form"))
                .filter("form");

            $(selector).find(":input[data-val=true]").each(function () {
                $jQval.unobtrusive.parseElement(this, true);
            });

            $forms.each(function () {
                var info = validationInfo(this);
                if (info) {
                    info.attachValidation();
                }
            });
        }
    };

    adapters = $jQval.unobtrusive.adapters;

    adapters.add = function (adapterName, params, fn) {
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
        /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
        /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
        /// mmmm is the parameter name).</param>
        /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
        /// attributes into jQuery Validate rules and/or messages.</param>
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
        if (!fn) {  // Called with no params, just a function
            fn = params;
            params = [];
        }
        this.push({ name: adapterName, params: params, adapt: fn });
        return this;
    };

    adapters.addBool = function (adapterName, ruleName) {
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
        /// the jQuery Validate validation rule has no parameter values.</summary>
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
        /// of adapterName will be used instead.</param>
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
        return this.add(adapterName, function (options) {
            setValidationValues(options, ruleName || adapterName, true);
        });
    };

    adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
        /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
        /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
        /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
        /// have a minimum value.</param>
        /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
        /// have a maximum value.</param>
        /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
        /// have both a minimum and maximum value.</param>
        /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
        /// contains the minimum value. The default is "min".</param>
        /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
        /// contains the maximum value. The default is "max".</param>
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
        return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
            var min = options.params.min,
                max = options.params.max;

            if (min && max) {
                setValidationValues(options, minMaxRuleName, [min, max]);
            }
            else if (min) {
                setValidationValues(options, minRuleName, min);
            }
            else if (max) {
                setValidationValues(options, maxRuleName, max);
            }
        });
    };

    adapters.addSingleVal = function (adapterName, attribute, ruleName) {
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
        /// the jQuery Validate validation rule has a single value.</summary>
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
        /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
        /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
        /// The default is "val".</param>
        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
        /// of adapterName will be used instead.</param>
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
        return this.add(adapterName, [attribute || "val"], function (options) {
            setValidationValues(options, ruleName || adapterName, options.params[attribute]);
        });
    };

    $jQval.addMethod("__dummy__", function (value, element, params) {
        return true;
    });

    $jQval.addMethod("regex", function (value, element, params) {
        var match;
        if (this.optional(element)) {
            return true;
        }

        match = new RegExp(params).exec(value);
        return (match && (match.index === 0) && (match[0].length === value.length));
    });

    $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
        var match;
        if (nonalphamin) {
            match = value.match(/\W/g);
            match = match && match.length >= nonalphamin;
        }
        return match;
    });

    adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern");
    adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
    adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
    adapters.add("equalto", ["other"], function (options) {
        var prefix = getModelPrefix(options.element.name),
            other = options.params.other,
            fullOtherName = appendModelPrefix(other, prefix),
            element = $(options.form).find(":input[name='" + escapeAttributeValue(fullOtherName) + "']")[0];

        setValidationValues(options, "equalTo", element);
    });
    adapters.add("required", function (options) {
        // jQuery Validate equates "required" with "mandatory" for checkbox elements
        if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
            setValidationValues(options, "required", true);
        }
    });
    adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
        var value = {
            url: options.params.url,
            type: options.params.type || "GET",
            data: {}
        },
            prefix = getModelPrefix(options.element.name);

        $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
            var paramName = appendModelPrefix(fieldName, prefix);
            value.data[paramName] = function () {
                return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val();
            };
        });

        setValidationValues(options, "remote", value);
    });
    adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
        if (options.params.min) {
            setValidationValues(options, "minlength", options.params.min);
        }
        if (options.params.nonalphamin) {
            setValidationValues(options, "nonalphamin", options.params.nonalphamin);
        }
        if (options.params.regex) {
            setValidationValues(options, "regex", options.params.regex);
        }
    });

    $(function () {
        $jQval.unobtrusive.parse(document);
    });
} (jQuery));

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Carl Randall
Architect AssemblySoft
United Kingdom United Kingdom
Carl Randall has specialized in Information Technology solutions for over 15 years. Specializing in full life-cycle development projects for both enterprise-wide systems, desktop applications and Internet based solutions.

Carl has been involved in .Net since it's inception and is currently a Microsoft Certified Professional Developer (Enterprise).

When not coding and designing, Carl enjoys playing table tennis, tennis, sailing and spending time by the beach - when the british weather permits Wink | ;)
Follow on   Twitter

| Advertise | Privacy | Mobile
Web02 | 2.8.140718.1 | Last Updated 13 Sep 2012
Article Copyright 2012 by Carl Randall
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid