Posted By

kouphax on 10/25/08


Tagged

javascript jquery annotations constraints


Versions (?)

Constraints jQuery Plugin


 / Published in: JavaScript
 

Constraints plugin (requires annotation plugin).

This is the second draft version that has been severly refactoed both internally and externally.

  1. /*---------------------------------------------------------------------------------
  2.  *
  3.  * Process Constraints jQuery Plugin
  4.  *
  5.  *---------------------------------------------------------------------------------
  6.  *
  7.  * This plugin is responsible for apply constraints to a target form. It
  8.  * will examin each fiels annotations to find @Constraints annotation and
  9.  * appply the requested constraints to the field. An number of configuration
  10.  * options are available (see below)
  11.  *
  12.  * @author James Hughes
  13.  *
  14.  * -------------------------------------------------------------------------------
  15.  * 24/10/2008 - Initial Version
  16.  * -------------------------------------------------------------------------------
  17.  * 28/10/2008 - Second Draft: Major Internal Refactoring. Introduced new public
  18.  * API's for working with constratins and messages. Added the
  19.  * ability to remove constraints singularly and globally as well as
  20.  * actually uninstall the plugin.
  21.  * -------------------------------------------------------------------------------
  22.  *///------------------------------------------------------------------------------
  23. (function($){
  24.  
  25. /*-----------------------------------------------------------------------------
  26.   *
  27.   * isEmpty Utility Function
  28.   *
  29.   *-----------------------------------------------------------------------------
  30.   *
  31.   * Utility function that ensures a string is either null or an empty string.
  32.   *
  33.   * @plugin
  34.   * @param v - the value to check for emptiness
  35.   *
  36.   *///--------------------------------------------------------------------------
  37. $.isEmpty = function(v){
  38. return !v || v == "" || $.trim(v) == "";
  39. };
  40.  
  41. /*-----------------------------------------------------------------------------
  42.   *
  43.   * Process Constraints Plugin
  44.   *
  45.   *-----------------------------------------------------------------------------
  46.   *
  47.   * Extend the jQuery Object to provide a utility function that will perform
  48.   * the constraint application functionality to the form passed in
  49.   *
  50.   * @plugin
  51.   * @param o - custom options object that accepts
  52.   *
  53.   * customMessages: map of custom constraint messages
  54.   * customConstraints: map of custom constraints to apply
  55.   * constraintTrigger: event that triggers contraint tests
  56.   * stopOnFirst: determines if we break on first error
  57.   * errorFn: error handler fn(field, failed)
  58.   * successFn: called when all constraints pass
  59.   *
  60.   *///--------------------------------------------------------------------------
  61. $.fn.constrain = function(o){
  62.  
  63. /*-------------------------------------------------------------------------
  64.   *
  65.   * Apply Options
  66.   *
  67.   *-------------------------------------------------------------------------
  68.   *
  69.   * Merge the default and custom options resulting in a specific options
  70.   * map for this function call.
  71.   *
  72.   *///----------------------------------------------------------------------
  73. var options = $.extend({},defaultOptions, o);
  74.  
  75. /*-------------------------------------------------------------------------
  76.   *
  77.   * Messages
  78.   *
  79.   *-------------------------------------------------------------------------
  80.   *
  81.   * Constraint messages are built up from a set of defaults. Merged with
  82.   * a set of user defined messages. When a constraint fails the first
  83.   * message looked up is the id of the field followed by the name of the
  84.   * constraint eg - txtName.mandatory. If this does not exist or if the
  85.   * field does not have an id it will ue the default message.
  86.   *
  87.   *///----------------------------------------------------------------------
  88. if(o.customMessages){
  89. MessageSource.addMessages(o.customMessages);
  90. }
  91.  
  92. /*-------------------------------------------------------------------------
  93.   *
  94.   * Create Available Constraints
  95.   *
  96.   *-------------------------------------------------------------------------
  97.   *
  98.   * Represents a map of all available constraints that can be applied to
  99.   * a field. This is created by merging customConstraints map from the
  100.   * passed options with the default constraints.
  101.   *
  102.   *///----------------------------------------------------------------------
  103. if(options.customConstraints){
  104. ConstraintService.registerAll(options.customConstraints);
  105. }
  106.  
  107. /*-------------------------------------------------------------------------
  108.   *
  109.   * Apply Constraints
  110.   *
  111.   *-------------------------------------------------------------------------
  112.   *
  113.   * This section discovers the required constraints on a per field basis
  114.   * and applies the behaviour to the field
  115.   *
  116.   *///----------------------------------------------------------------------
  117. return this.each(function(){
  118.  
  119. /*---------------------------------------------------------------------
  120.   *
  121.   * No Constraint Failover
  122.   *
  123.   *---------------------------------------------------------------------
  124.   *
  125.   * Most of this API is open to the public therefore open to the
  126.   * irresponsible, ignorant, clueless and just plain stupid. We need
  127.   * to cater for as much worst case edge cases as we can without
  128.   * making the good people suffer. Exit if no constraints defined on
  129.   * element.
  130.   *
  131.   *///------------------------------------------------------------------
  132. if(!$(this).annotations("@Constraints")[0]){ return undefined };
  133.  
  134. /*---------------------------------------------------------------------
  135.   *
  136.   * Constraint Discovery
  137.   *
  138.   *---------------------------------------------------------------------
  139.   *
  140.   * We extract the requested constraints via annotations on the field
  141.   * and build a map of applicable constraints which is set as a data
  142.   * item on the element. At the same time we also set another map of
  143.   * constratint data that can be passed into the constraint test
  144.   * function
  145.   *
  146.   *///------------------------------------------------------------------
  147. var requestedConstraints = $(this).annotations("@Constraints")[0].data;
  148. for(constraint in requestedConstraints){
  149. /* filter out falsey values */
  150. if(requestedConstraints[constraint]){
  151. ConstraintService.bind($(this), constraint, requestedConstraints[constraint]);
  152. }
  153. }
  154.  
  155. /*---------------------------------------------------------------------
  156.   *
  157.   * Event Binding
  158.   *
  159.   *---------------------------------------------------------------------
  160.   *
  161.   * Bind the Constraint Trigger Callback to the trigger event. Also
  162.   * we are passing in the options object so we still have access to
  163.   * the options object. Done in this way to ensure we can unbind the
  164.   * callback function if the user wants.
  165.   *
  166.   *///------------------------------------------------------------------
  167. $(this).bind((this.constraintTrigger = options.constraintTrigger), options, constraintCallback);
  168. });
  169. }
  170.  
  171. /*-----------------------------------------------------------------------------
  172.   *
  173.   * Unconstrain Plugin
  174.   *
  175.   *-----------------------------------------------------------------------------
  176.   *
  177.   * Removes any current constraints applied to the passed in fields as well
  178.   * as removing data caches and constraint events
  179.   *
  180.   * @plugin
  181.   *
  182.   *///--------------------------------------------------------------------------
  183. $.fn.unconstrain = function(){
  184. return this.each(function(){ ConstraintService.unconstrain(this); });
  185. }
  186.  
  187. /*-----------------------------------------------------------------------------
  188.   *
  189.   * Unconstrain Plugin
  190.   *
  191.   *-----------------------------------------------------------------------------
  192.   *
  193.   * Helper function to remove all constraints form an entire form.
  194.   *
  195.   * @plugin
  196.   * @param frm - form/id/jQuery representing the form to process
  197.   *
  198.   *///--------------------------------------------------------------------------
  199. $.unconstrainForm = function(frm){
  200. ConstraintService.unconstrainAll($(frm)[0]);
  201. }
  202.  
  203. /*-----------------------------------------------------------------------------
  204.   *
  205.   * Process Constraints Plugin
  206.   *
  207.   *-----------------------------------------------------------------------------
  208.   *
  209.   * Extend the jQuery Object to provide a utility function that will perform
  210.   * the constraint application functionality to the form passed in
  211.   *
  212.   * @plugin
  213.   * @param frm - form/id/jQuery representing the form to process
  214.   * @param o - custom options object that accepts
  215.   *
  216.   * customMessages: map of custom constraint messages
  217.   * customConstraints: map of custom constraints to apply
  218.   * constraintTrigger: event that triggers contraint tests
  219.   * stopOnFirst: determines if we break on first error
  220.   * errorFn: error handler fn(field, failed)
  221.   * successFn: called when all constraints pass
  222.   *
  223.   *///--------------------------------------------------------------------------
  224. $.constrainForm = function(frm,o){
  225. $.annotated("@Constraints", $(frm)[0]).constrain(o);
  226. }
  227.  
  228. /*-----------------------------------------------------------------------------
  229.   *
  230.   * Default Options
  231.   *
  232.   *-----------------------------------------------------------------------------
  233.   *
  234.   * This map represents the global default options that should be used
  235.   * when applying constraints. They can be overridden via custom maps
  236.   * passed into the functions.
  237.   *
  238.   *///--------------------------------------------------------------------------
  239. var defaultOptions = {
  240. customMessages : {}, // map of custom constraint messages
  241. customConstraints : {}, // map of custom constraints to apply
  242. constraintTrigger : 'blur', // event that triggers contraint tests
  243. stopOnFirst : false, // determines if we break on first error
  244. errorFn : function(){}, // error handling callback
  245. successfn : function(){} // successfull callback
  246. }
  247.  
  248. /*-----------------------------------------------------------------------------
  249.   *
  250.   * Constraint Service
  251.   *
  252.   *-----------------------------------------------------------------------------
  253.   *
  254.   * Singleton class used to handles page level contraint testing and
  255.   * registration.
  256.   *
  257.   * @constructor
  258.   *
  259.   *///--------------------------------------------------------------------------
  260. var ConstraintService = function(){
  261.  
  262. /*-------------------------------------------------------------------------
  263.   *
  264.   * Default Constraints
  265.   *
  266.   *-------------------------------------------------------------------------
  267.   *
  268.   * Represents a map of all available constraints that can be applied to a
  269.   * field. This is merged with a custom constraints that can be declared
  270.   * via the options object to provide a list of all available constraints
  271.   * that can be applied to the fields
  272.   *
  273.   *///----------------------------------------------------------------------
  274. var defaultConstraints = {
  275. alpha:function(v){
  276. return $.isEmpty(v) || /^[a-z]*$/i.test(v);
  277. },
  278. alphanumeric:function(v){
  279. return $.isEmpty(v) || /^[a-z0-9]*$/i.test(v);
  280. },
  281. mandatory:function(v){
  282. return !$.isEmpty(v);
  283. },
  284. creditCard:function(v){
  285. return $.isEmpty(v) || /^\d{4}-?\d{4}-?\d{4}-?\d{4}$/.test(v);
  286. },
  287. currency:function(v){
  288. return $.isEmpty(v) || /^(\d{1,3},?(\d{3},?)*\d{3}(\.\d{0,2})?|\d{1,3}(\.\d{0,2})?|\.\d{1,2}?)$/.test(v);
  289. },
  290. digitsOnly:function(v){
  291. return $.isEmpty(v) || /^[0-9]*$/.test(v);
  292. },
  293. email:function(v){
  294. return $.isEmpty(v) || /^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i.test(v);
  295. },
  296. inList:function(v,l){
  297. return $.isEmpty(v) || $.inArray(v,l) > -1;
  298. },
  299. ip:function(v){
  300. return $.isEmpty(v) || /^(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])$/.test(v);
  301. },
  302. matches:function(v,e){
  303. return $.isEmpty(v) || (e.constructor === RegExp) ? e.test(v) : r == v;
  304. },
  305. max:function(v,m){
  306. return $.isEmpty(v) || (!isNaN(v) && parseInt(v) <= m);
  307. },
  308. maxSize:function(v,m){
  309. return $.isEmpty(v) || v.length <= m;
  310. },
  311. min:function(v,m){
  312. return $.isEmpty(v) || (!isNaN(v) && parseInt(v) >= m);
  313. },
  314. minSize:function(v,m){
  315. return $.isEmpty(v) || v.length >= m;
  316. },
  317. notEqual:function(v,n){
  318. return $.isEmpty(v) || v != n;
  319. },
  320. range:function(v,d,e){
  321.  
  322. if($.isEmpty(v)){ return true; }
  323.  
  324. switch($(e).data("constraints").type){
  325. case 'boolean': return /^(true)|(false)$/i.test(v);
  326. case 'date': return !isNaN(Date.parse(v)) && Date.parse(v) >= Date.parse(d.start) && Date.parse(v) <= Date.parse(d.end);
  327. case 'float': return !isNaN(v) && parseFloat(v) >= d.start && parseFloat(v) <= d.end;
  328. case 'int': return !isNaN(v) && parseInt(v) >= d.start && parseInt(v) <= d.end;
  329. case 'string':
  330. default: return v >= d.start && v <= d.end;
  331. }
  332. },
  333. size:function(v,d){
  334. return $.isEmpty(v) || ((d.end) ? v.length >= d.start && v.length <= d.end : v.length === d.start);
  335. },
  336. type:function(v,t){
  337.  
  338. if($.isEmpty(v)){ return true; }
  339.  
  340. switch(t){
  341. case 'boolean': return /^(true)|(false)$/i.test(v);
  342. case 'date': return !isNaN(Date.parse(v));
  343. case 'float': return !isNaN(parseFloat(v));
  344. case 'int': return !isNaN(parseInt(v)) && /^-?[0-9]+$/.test(v);
  345. case 'string': return v.constructor === String;
  346. default: throw(t + " is not a valid field type");
  347. }
  348. },
  349. url:function(v){
  350. return $.isEmpty(v) || /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(v);
  351. },
  352. validator:function(v,f,e){
  353. return $.isEmpty(v) || f(v,e);
  354. }
  355. };
  356.  
  357. /*-------------------------------------------------------------------------
  358.   *
  359.   * Manipulate Constraints
  360.   *
  361.   *-------------------------------------------------------------------------
  362.   *
  363.   * Helper function that wraps the default pre and post functionality.
  364.   *
  365.   * Accepts a target element and a processing function that accepts the
  366.   * constraint cache and constratin data cache for that element and allows
  367.   * you to edit it before setting the values back to the cache.
  368.   *
  369.   *///----------------------------------------------------------------------
  370. var manipulateConstraints = function(el, f){
  371.  
  372. var c = $(el).data("constraints") || {};
  373. var cd = $(el).data("constraint-data") || {};
  374.  
  375. f(c, cd);
  376.  
  377. $(el).data("constraints", c);
  378. $(el).data("constraint-data", cd);
  379. };
  380.  
  381. /*-------------------------------------------------------------------------
  382.   *
  383.   * Has Constraints?
  384.   *
  385.   *-------------------------------------------------------------------------
  386.   *
  387.   * Helper function that d
  388.   *
  389.   *///----------------------------------------------------------------------
  390. var hasConstraint = function(el,constraint){
  391. return !!($(el).data("constraints") || {})[constraint];
  392. }
  393.  
  394. /*-------------------------------------------------------------------------
  395.   *
  396.   * Initialisation
  397.   *
  398.   *-------------------------------------------------------------------------
  399.   *
  400.   * Set up the initial state of the Constraint Service.
  401.   *
  402.   *///----------------------------------------------------------------------
  403. var availableConstraints = $.extend({},defaultConstraints);
  404.  
  405. /*-------------------------------------------------------------------------
  406.   *
  407.   * Constraint Service Public API
  408.   *
  409.   *-------------------------------------------------------------------------
  410.   *
  411.   * Publically available functions for the Constraints Service
  412.   *
  413.   *///----------------------------------------------------------------------
  414. return {
  415.  
  416. /*---------------------------------------------------------------------
  417.   *
  418.   * Register Constraint
  419.   *
  420.   *---------------------------------------------------------------------
  421.   *
  422.   * Registers a single constraint with the Constraint Service so it
  423.   * can be used going forward by fields
  424.   *
  425.   * @param name - name of the constraint to apply
  426.   * @param test - test function for constraint
  427.   *
  428.   *///------------------------------------------------------------------
  429. register: function(name, test){
  430. availableConstraints[name] = test;
  431. },
  432.  
  433. /*---------------------------------------------------------------------
  434.   *
  435.   * Register Constraints
  436.   *
  437.   *---------------------------------------------------------------------
  438.   *
  439.   * Registers a group of constraints at one time. Takes a map of name
  440.   * function pairs and applies it to the available constraints
  441.   *
  442.   * @param constraints - {name:test,...} map of constraints
  443.   *
  444.   *///------------------------------------------------------------------
  445. registerAll: function(constraints){
  446. $.extend(availableConstraints, constraints);
  447. },
  448.  
  449. /*---------------------------------------------------------------------
  450.   *
  451.   * Get Constraint Test
  452.   *
  453.   *---------------------------------------------------------------------
  454.   *
  455.   * Returns a, if defined, the associated constratin test funciton
  456.   * otherwise it returns undefined.
  457.   *
  458.   * @param name - name of constaint to return
  459.   *
  460.   *///------------------------------------------------------------------
  461. get: function(name){
  462. return availableConstraints[name];
  463. },
  464.  
  465. /*---------------------------------------------------------------------
  466.   *
  467.   * Bind Constraint
  468.   *
  469.   *---------------------------------------------------------------------
  470.   *
  471.   * Performs constraint binding work on the passed in element. More
  472.   * specifically it loads and cahces the constraint and data on to the
  473.   * element so the global constraint function can manipulate it.
  474.   *
  475.   * @param element - target element to bind constraint to
  476.   * @param constraint - name/id of constraint to apply
  477.   * @param data - constratin data applicable to bound contraint
  478.   *
  479.   *///------------------------------------------------------------------
  480. bind: function(element, constraint, data){
  481. manipulateConstraints(element, function(constraints,constraintData){
  482. constraints[constraint] = ConstraintService.get(constraint);
  483. constraintData[constraint] = data;
  484. });
  485. },
  486.  
  487. /*---------------------------------------------------------------------
  488.   *
  489.   * Unbind Constraint
  490.   *
  491.   *---------------------------------------------------------------------
  492.   *
  493.   * Removes the constraint from the passed in element including data
  494.   *
  495.   * @param element - target element to remove constraint from
  496.   * @param constraint - name/id of constraint to remover
  497.   *
  498.   *///------------------------------------------------------------------
  499. unbind: function(element, constraint){
  500. manipulateConstraints(element, function(constraints,constraintData){
  501. delete(constraints[constraint]);
  502. delete(constraintData[constraint]);
  503. });
  504. },
  505.  
  506. /*---------------------------------------------------------------------
  507.   *
  508.   * Unbind All Constraints
  509.   *
  510.   *---------------------------------------------------------------------
  511.   *
  512.   * Globally unbinds constraint from all elements under the passed in
  513.   * root element (document is default).
  514.   *
  515.   * @param constraint - name/id of constraint to remove
  516.   * @param root - the root element to begin removal
  517.   *
  518.   *///------------------------------------------------------------------
  519. unbindAll : function(constraint, root){
  520. $.annotated("@Constraints", root).each(function(){
  521. if(hasConstraint(this,constraint)){
  522. ConstraintService.unbind(this, constraint);
  523. }
  524. });
  525. },
  526.  
  527. /*---------------------------------------------------------------------
  528.   *
  529.   * Unconstrain
  530.   *
  531.   *---------------------------------------------------------------------
  532.   *
  533.   * Removes constraint related data and events from the element
  534.   *
  535.   * @param root - the root element to begin removal
  536.   *
  537.   *///------------------------------------------------------------------
  538. unconstrain : function(el){
  539.  
  540. /* remove data */
  541. $(el).removeData("constraints");
  542. $(el).removeData("constraint-data");
  543.  
  544. /* unbind events */
  545. $(el).unbind(this.constraintTrigger, constraintCallback);
  546.  
  547. /* delete dom expando's */
  548. delete(el.constraintTrigger);
  549. },
  550.  
  551. /*---------------------------------------------------------------------
  552.   *
  553.   * Unconstrain All
  554.   *
  555.   *---------------------------------------------------------------------
  556.   *
  557.   * Globally destroys all constraints including data and events
  558.   *
  559.   * @param root - the root element to begin removal
  560.   *
  561.   *///------------------------------------------------------------------
  562. unconstrainAll : function(root){
  563. $.annotated("@Constraints", root).each(function(){
  564. ConstraintService.unconstrain(this)
  565. });
  566. }
  567. }
  568. }();
  569.  
  570. /*-----------------------------------------------------------------------------
  571.   *
  572.   * Message Source
  573.   *
  574.   *-----------------------------------------------------------------------------
  575.   *
  576.   * This Singleton encapsulates message source functionaltiy related
  577.   * specifically to loading messages for constraints.
  578.   *
  579.   * @constructor
  580.   *
  581.   *///--------------------------------------------------------------------------
  582. var MessageSource = (function(){
  583.  
  584. /*-------------------------------------------------------------------------
  585.   *
  586.   * Default Messages
  587.   *
  588.   *-------------------------------------------------------------------------
  589.   *
  590.   * This map the default messages that should be applied to a
  591.   * field when there are no custom messages to be applied to a failed
  592.   * constraint.
  593.   *
  594.   *///----------------------------------------------------------------------
  595. var defaultMessages = {
  596. alpha : "${field} must be composed of alpha characters A-Z,a-z",
  597. alphaNumeric : "${field} must be composed of alphanumeric characters A-Z,a-z,0-9",
  598. mandatory : "${field} is a mandatory field",
  599. creditCard : "${field} must be a valid credit card number",
  600. currency : "${value} is not a valid currency format",
  601. digitsOnly : "${field} must be composed of only digits",
  602. email : "${field} must be a valid email address",
  603. indexed : "${field} is indexed and no indexed fields contain values",
  604. inList : "${field} must be one of the following values: ${data}",
  605. ip : "${field} must be a valid IP Address",
  606. matches : "${field} does not match the required expression",
  607. max : "${field} cannot exceed ${data}",
  608. maxSize : "${field} cannot exceeds the maximum length (${data})",
  609. min : "${field} cannot be less than ${data}",
  610. minSize : "${field} cannot is less than the minimum length (${data})",
  611. notEqual : "${field} cannot have the value of ${value}",
  612. range : "${field} must be between ${start} and ${end}",
  613. size : "${field} is not the stated size",
  614. type : "${field} is not the correct type (${data})",
  615. url : "${field} must be a valid URL",
  616. validator : "${field} has failed custom validation"
  617. };
  618.  
  619. var ms = {"default":defaultMessages}
  620.  
  621. /*-------------------------------------------------------------------------
  622.   *
  623.   * Format Message Function
  624.   *
  625.   *-------------------------------------------------------------------------
  626.   *
  627.   * Private function to apply data to a templated message
  628.   *
  629.   * @param m - the unformatted message
  630.   * @param e - the element in question
  631.   * @param k - the key for the data-cache to get extra data from
  632.   * @param d - the data-cache for extra template options
  633.   *
  634.   *///----------------------------------------------------------------------
  635. var formatMessage = function(m,e,k,d){
  636.  
  637. var cdata = ((d) ? d[k] : null) || {};
  638.  
  639. if(cdata.constructor !== Object){
  640. cdata = {data : cdata}
  641. }
  642.  
  643. var data = $.extend({}, {field:e.id || e.name, value: $(e).val()}, cdata), fm = m;
  644.  
  645. for(d in data){
  646. fm = fm.replace(new RegExp('\\${'+d+'}','g'), data[d].toString());
  647. }
  648.  
  649. return fm;
  650. };
  651.  
  652. return {
  653.  
  654. /*---------------------------------------------------------------------
  655.   *
  656.   * Get Message Function
  657.   *
  658.   *---------------------------------------------------------------------
  659.   *
  660.   * This function interrogates a passed element and returns a the
  661.   * message that most closely matches the proximity. If
  662.   * <element_name/element_id>.<k> exists then this is returned as an
  663.   * evaluated message. Otherwise it looks up the global default
  664.   * message default.<key>.
  665.   *
  666.   * @param e - source element
  667.   * @param k - key for the message
  668.   *
  669.   *///------------------------------------------------------------------
  670. getMessage:function(e,k){
  671. return formatMessage(((e && e.id && ms[e.id])?ms[e.id][k]:ms["default"][k]) || "",e,k,(e)?$(e).data("constaint-data"):null);
  672. },
  673.  
  674. /*---------------------------------------------------------------------
  675.   *
  676.   * Add Messages Function
  677.   *
  678.   *---------------------------------------------------------------------
  679.   *
  680.   * Add new custom messages to the messageSource
  681.   *
  682.   *///------------------------------------------------------------------
  683. addMessages:function(c){
  684. ms = $.extend(true,ms,c);
  685. },
  686.  
  687. /*---------------------------------------------------------------------
  688.   *
  689.   * Add Message Function
  690.   *
  691.   *---------------------------------------------------------------------
  692.   *
  693.   * Add a new custom message to the messageSource
  694.   *
  695.   *///------------------------------------------------------------------
  696. addMessage: function(namespace, msg){
  697. MessageSource.addMessages({namespace:msg});
  698. },
  699.  
  700. /*---------------------------------------------------------------------
  701.   *
  702.   * Remove Namespace Function
  703.   *
  704.   *---------------------------------------------------------------------
  705.   *
  706.   * Delete an entire namespace from the messageSource
  707.   *
  708.   *///------------------------------------------------------------------
  709. removeNamespace: function(namespace){
  710. delete(ms[namespace]);
  711. },
  712.  
  713. /*---------------------------------------------------------------------
  714.   *
  715.   * Remove Message Function
  716.   *
  717.   *---------------------------------------------------------------------
  718.   *
  719.   * Delete a single message from a certain namespace. Will also
  720.   * remove the namespace if it is empty.
  721.   *
  722.   *///------------------------------------------------------------------
  723. removeMessage: function(namespace, msg){
  724.  
  725. delete(ms[namespace][msg]);
  726.  
  727. for(t in ms[namespace]){
  728. return undefined;
  729. }
  730.  
  731. removeNamespace(ms[namespace]);
  732. }
  733. };
  734. })();
  735.  
  736. /*-----------------------------------------------------------------------------
  737.   *
  738.   * Constraints Callback
  739.   *
  740.   *-----------------------------------------------------------------------------
  741.   *
  742.   * Handles the constratint management when a constraint action is triggered.
  743.   *
  744.   *///--------------------------------------------------------------------------
  745. function constraintCallback(event){
  746.  
  747. var cs = $(this).data("constraints");
  748. var cd = $(this).data("constraint-data");
  749.  
  750. var failedConstraints = [];
  751.  
  752. for(c in cs){
  753.  
  754. var pass = cs[c]($(this).val(), cd[c], this);
  755.  
  756. if(!pass){
  757.  
  758. failedConstraints.push({
  759. constraint : c,
  760. message : MessageSource.getMessage(this,c)
  761. });
  762.  
  763. if(event.data.stopOnFirst){ break; }
  764. }
  765. }
  766.  
  767. event.data[(failedConstraints.length > 0)?'errorFn':'successFn'](this, failedConstraints);
  768. }
  769.  
  770. /*-----------------------------------------------------------------------------
  771.   *
  772.   * Constraints Public API
  773.   *
  774.   *-----------------------------------------------------------------------------
  775.   *
  776.   * Extend the core jQuery object to allow access to the public functions
  777.   * for the Constraint functionality
  778.   *
  779.   *///--------------------------------------------------------------------------
  780. $.extend({
  781.  
  782. /*
  783.   * fn.constrain
  784.   * fn.unconstrain
  785.   * constrainForm
  786.   * unconstrainForm
  787.   */
  788.  
  789. cs : {
  790.  
  791. //-- DEFAULT OPTIONS API ----------------------------------------------
  792. defaultOptions : defaultOptions,
  793.  
  794. //-- CONSTRAINT SERVICE API -------------------------------------------
  795. register : ConstraintService.register,
  796. registerAll : ConstraintService.registerAll,
  797. bind : ConstraintService.bind,
  798. unbind : ConstraintService.unbind,
  799. unconstrain : ConstraintService.unconstrain,
  800. unconstrainAll : ConstraintService.unconstrainAll,
  801.  
  802. //-- MESSAGE SOURCE API -----------------------------------------------
  803. addMessages : MessageSource.addMessages,
  804. addMessage : MessageSource.addMessage,
  805. getMessage : MessageSource.getMessage,
  806. deleteMessage : MessageSource.removeMessage,
  807. deleteMessageNamespace : MessageSource.removeNamespace,
  808.  
  809. /*---------------------------------------------------------------------
  810.   *
  811.   * Unistall Constrains plugin
  812.   *
  813.   *---------------------------------------------------------------------
  814.   *
  815.   * Unistall the entire plugin by deregistering all events and data
  816.   * caches in the document but also delete the objects from memory.
  817.   *
  818.   *///------------------------------------------------------------------
  819. uninstall: function(){
  820.  
  821. /* remove constraint data and events */
  822. ConstraintService.unconstrainAll(document);
  823.  
  824. /* delete the object from global object */
  825. delete(constraintCallback);
  826. delete(MessageSource);
  827. delete(ConstraintService);
  828. delete(defaultOptions);
  829. delete($.isEmpty);
  830. delete($.constrainForm);
  831. delete($.unconstrainForm);
  832. delete($.fn.constrain);
  833. delete($.fn.unconstrain);
  834. delete($.constraints);
  835. }
  836. }
  837. });
  838.  
  839. })(jQuery);

Report this snippet  

You need to login to post a comment.