2012-06-16 14 views
24

Estoy usando Asp.net MVC 3 y Twitter Bootstrap. Lo que quiero es integrarlos a ambos. El gran problema para mí son las formas. Estoy utilizando el HtmlHelper y es un problema, cuando se trata de la validación, lo quiero para generar HTML así:Integrando Twitter Bootstrap con Asp.net MVC 3 formas

<div class="control-group error"> 
    <label for="field" class="control-label">OMG this label is so awesome: </label> 
    <div class="controls"> 
     <input type="text" name="field" id="field" value="yeah" /> 
     <span class="help-inline">Eventually some error :C</span> 
    </div> 
</div> 

Aquí está mi código HtmlHelper:

@Html.LabelFor(x => x.Field) 
@Html.EditorFor(x => x.Field) 
@Html.ValidationMessagesFor(x => x.Field) 

El problema es que quiero que el error de clase en div externo se establezca solo si realmente hay un error en este campo. Otro problema es que no sé cómo aplicar la etiqueta span para errores. Podría escribir mi método en HtmlHelper, pero me haría reimplementar casi toda la funcionalidad de LabelFor, EditorFor y ValidationMessageFor. ¿Hay una manera más simple de hacer esto? ¿Y qué hay de la validación discreta?

+0

¿Recibió a ninguna parte con esto? Estoy intentando esto también – baynezy

+0

No he encontrado nada en internet al respecto. Probablemente termine haciendo esto yo solo. – Agares

+2

Voy a hacerlo yo mismo. Una vez que tenga algo en GitHub, publicaré el enlace aquí. – baynezy

Respuesta

22

me encontré con el mismo desafío y con un poco de ayuda para las etiquetas (véase más adelante), esto es lo que tengo:

<div class="control-group @if (!ViewData.ModelState.IsValidField("Name")) { @Html.Raw("error"); }"> 
    @Html.LabelFor(model => model.Name, new {@class = "control-label"}) 
    <div class="controls"> 
     @Html.EditorFor(model => model.Name) 
     @Html.ValidationMessageFor(model => model.Name, null, new {@class = "help-inline"}) 
    </div> 
</div> 

Html.LabelFor aplicación: https://stackoverflow.com/a/6722082

no probé con el unobstrusive validación, pero parece que solo tienes que activarlo.

Si usted está buscando un error mundial, usted debe usar algo como:

@if (ViewData.ModelState.IsValid == false) { 
    <div class="alert alert-error"><button class="close" dismiss="alert">x</button><!-- some text--></div> 
} 

Hay una ejemplo vivo (en francés) aquí: http://ws.sherbrow.fr/auth

El conjunto El código fuente del proyecto debería estar disponible pronto (ver mi perfil o preguntarme directamente).

6

Me tomé la libertad y creé un método de extensión que encapsula el código de Sherbrow para representar la clase de error cuando el campo no es válido. Este método de extensión tiene la ventaja de que es fuertemente tipado y más corto para escribir:

public static MvcHtmlString ModelStateFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
    { 
     var modelMetadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 

     if (html.ViewData.ModelState.IsValidField(modelMetadata.PropertyName)) 
     { 
      return MvcHtmlString.Empty; 
     } 

     return new MvcHtmlString("error"); 
    } 
+0

Bien, ¿por qué no haces una edición de mi respuesta incluyendo tu código y reemplazando la prueba de la clase de error? – Sherbrow

0

Hay un article on BrainDonor que he aplicado con éxito simplemente utilizando el LabelFor principal, EditorFor y ValidationFor. He colocado este es un js de todo el sitio, luego solo asegúrate de tener el div del grupo de control y está bien.

0

Puede integrar la validación MVC3 con el marco de Bootstrap, añadiendo la siguiente javascript para su página (Vista)

<script> 
$(document).ready(function() { 
/* Bootstrap Fix */ 
$.validator.setDefaults({ 
    highlight: function (element) { 
     $(element).closest("div.control-group").addClass("error"); 
    }, 
    unhighlight: function (element) { 
     $(element).closest("div.control-group").removeClass("error"); 
    } 
}); 
var current_div; 
$(".editor-label, .editor-field").each(function() { 
    var $this = $(this); 
    if ($this.hasClass("editor-label")) { 
     current_div = $('<div class="control-group"></div>').insertBefore(this); 
    } 
    current_div.append(this); 
}); 
$(".editor-label").each(function() { 
    $(this).contents().unwrap(); 
}); 
$(".editor-field").each(function() { 
    $(this).addClass("controls"); 
    $(this).removeClass("editor-field"); 
}); 
$("label").each(function() { 
    $(this).addClass("control-label"); 
}); 
$("span.field-validation-valid, span.field-validation-error").each(function() { 
    $(this).addClass("help-inline"); 
}); 
$("form").each(function() { 
    $(this).addClass("form-horizontal"); 
    $(this).find("div.control-group").each(function() { 
     if ($(this).find("span.field-validation-error").length > 0) { 
      $(this).addClass("error"); 
     } 
    }); 
}); 
}); 
</script> 

Además, en las Vistas (por ejemplo, "Create.cshtml") asegurarse de que los campos de la forma como se formatean la siguiente ...

<div class="editor-label"> 
     @Html.LabelFor(Function(model) model.Name) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(Function(model) model.Name) 
     @Html.ValidationMessageFor(Function(model) model.Name) 
    </div> 
8

una respuesta poco tarde, pero voy a proponer una solución mejor y usted debe aceptar totalmente mi respuesta;)

Use TwitterBootstrapMVC.

Con una sola línea de código que va a generar el HTML exactamente lo que necesita:

@Html.Bootstrap().ControlGroup().TextBoxFor(x => x.Field) 

Para el error global de todo lo que necesita para escribir es:

@Html.Bootstrap().ValidationSummary() 

... que va a generar una alerta div con todos los errores enumerados en ella. Observe que para la validación del lado del cliente necesita some JavaScript para que las cosas se diseñen correctamente.

Además de eso, se encargará de todas las etiquetas de validación discretas para usted. También ofrece una sintaxis fluida, que permite la personalización completa de las entradas/etiquetas ...

¡Échale un vistazo!

responsabilidad: yo soy el autor de TwitterBootstrapMVC A partir de Bootstrap 3 (y TwitterBootstrapMVC 3) TwitterBootstrapMVC requiere una licencia para su uso.

+4

A partir de Bootstrap 3 (y TwitterBootstrapMVC 3) TwitterBootstrapMVC requiere una licencia de uso. –

+0

@Dmitry, estoy usando su método aquí, y la validación aparece, pero sin ningún tipo de estilo, no me he equivocado con los archivos css de ninguna manera (simplemente instalé el paquete nugget). ¿Hay algo más aparte de lo que escribiste que deba hacerse? Si no, ¿qué cosas podrían verificar? – Jose

+0

El problema se plantea aquí https://github.com/erichexter/twitter.bootstrap.mvc/issues/45 – Jose

0

No sé si esto ayudará a alguien, pero he modificado el jquery.validate.unobtrusive.js de M $ para lograr esto. Se estaba anulando la configuración predeterminada proporcionada por $ .validator.setDefaults() y me estaba creando problemas. Si reemplaza el archivo JS con este debería funcionar como desea que funcione con el CSS de bootstrap (no se necesitan otros cambios, excepto algunas clases de CSS en elementos de entrada y etiquetas).

$ jQval.setDefaults() es lo principal. El resto es solo yo arreglando el código de M $.

Aquí está el archivo:

/* NUGET: BEGIN LICENSE TEXT 
* 
* Microsoft grants you the right to use these script files for the sole 
* purpose of either: (i) interacting through your browser with the Microsoft 
* website or online service, subject to the applicable licensing or use 
* terms; or (ii) using the files as included with a Microsoft product subject 
* to that product's license terms. Microsoft reserves all other rights to the 
* files not expressly granted by Microsoft, whether by implication, estoppel 
* or otherwise. Insofar as a script file is dual licensed under GPL, 
* Microsoft neither took the code under GPL nor distributes it thereunder but 
* under the terms set out in this paragraph. All notices and licenses 
* below are for informational purposes only. 
* 
* NUGET: END LICENSE TEXT */ 
/*! 
** 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"; 

    // Override jquery validate plugin defaults in order to utilize Twitter Bootstrap 3 has-error, has-success, etc. styling. 
    $jQval.setDefaults({ 
     highlight: function (element, errorClass, validClass) { 
      if (element.type === 'radio') { 
       this.findByName(element.name).addClass(errorClass).removeClass(validClass); 
      } else { 
       $(element).addClass(errorClass).removeClass(validClass); 
       $(element).closest('.form-group').removeClass('success').addClass('has-error'); 
      } 
     }, 
     unhighlight: function (element, errorClass, validClass) { 
      if (element.type === 'radio') { 
       this.findByName(element.name).removeClass(errorClass).addClass(validClass); 
      } else { 
       $(element).removeClass(errorClass).addClass(validClass); 
       $(element).closest('.form-group').removeClass('has-error').addClass('success'); 
      } 
     }, 
     errorElement: 'span', 
     errorClass: 'help-block', 
     errorPlacement: function (error, element) { 
      if (element.parent('.input-group').length || element.prop('type') === 'checkbox' || element.prop('type') === 'radio') { 
       error.insertAfter(element.parent()); 
      } else { 
       error.insertAfter(element); 
      } 
     } 
    }); 


    $('span.field-validation-valid, span.field-validation-error').each(function() { 
     $(this).addClass('help-inline'); 
    }); 

    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(/([!"#$%&'()*+,./:;<=>[email protected]\[\\\]^`{|}~])/g, "\\$1"); 
     return value.replace(new RegExp("([!\"#$%&'()*+,./:;<=>[email protected]\[\\\]^`{|}~])", '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) + "']"), 
      replaceAttrValue = container.attr("data-valmsg-replace"), 
      replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 

     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"), 
      replaceAttrValue = container.attr("data-valmsg-replace"), 
      replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 

     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), 
      defaultOptions = $jQval.unobtrusive.options || {}, 
      execInContext = function (name, args) { 
       var func = defaultOptions[name]; 
       func && $.isFunction(func) && func.apply(form, args); 
      } 

     if (!result) { 
      result = { 
       options: $.extend($jQval.defaults, { // options structure passed to jQuery Validate's validate() method 
        errorClass: defaultOptions.errorClass || "input-validation-error", 
        errorElement: defaultOptions.errorElement || "span", 
        errorPlacement: function() { 
         onError.apply(form, arguments); 
         execInContext("errorPlacement", arguments); 
        }, 
        invalidHandler: function() { 
         onErrors.apply(form, arguments); 
         execInContext("invalidHandler", arguments); 
        }, 
        messages: {}, 
        rules: {}, 
        success: function() { 
         onSuccess.apply(form, arguments); 
         execInContext("success", arguments); 
        } 
       }), 
       attachValidation: function() { 
        $form 
         .off("reset." + data_validation, onResetProxy) 
         .on("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> 

      // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one 
      // element with data-val=true 
      var $selector = $(selector), 
       $forms = $selector.parents() 
            .addBack() 
            .filter("form") 
            .add($selector.find("form")) 
            .has("[data-val=true]"); 

      $selector.find("[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; 
    }); 

    if ($jQval.methods.extension) { 
     adapters.addSingleVal("accept", "mimtype"); 
     adapters.addSingleVal("extension", "extension"); 
    } else { 
     // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 
     // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 
     // validating the extension, and ignore mime-type validations as they are not supported. 
     adapters.addSingleVal("extension", "extension", "accept"); 
    } 

    adapters.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.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); 
    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").filter("[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").filter("[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));