You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1039 lines
32 KiB

10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * # Semantic - Form Validation
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. $.fn.form = function(fields, parameters) {
  13. var
  14. $allModules = $(this),
  15. settings = $.extend(true, {}, $.fn.form.settings, parameters),
  16. validation = $.extend({}, $.fn.form.settings.defaults, fields),
  17. namespace = settings.namespace,
  18. metadata = settings.metadata,
  19. selector = settings.selector,
  20. className = settings.className,
  21. error = settings.error,
  22. eventNamespace = '.' + namespace,
  23. moduleNamespace = 'module-' + namespace,
  24. moduleSelector = $allModules.selector || '',
  25. time = new Date().getTime(),
  26. performance = [],
  27. query = arguments[0],
  28. methodInvoked = (typeof query == 'string'),
  29. queryArguments = [].slice.call(arguments, 1),
  30. returnedValue
  31. ;
  32. $allModules
  33. .each(function() {
  34. var
  35. $module = $(this),
  36. $field = $(this).find(selector.field),
  37. $group = $(this).find(selector.group),
  38. $message = $(this).find(selector.message),
  39. $prompt = $(this).find(selector.prompt),
  40. $submit = $(this).find(selector.submit),
  41. $clear = $(this).find(selector.clear),
  42. $reset = $(this).find(selector.reset),
  43. formErrors = [],
  44. keyHeldDown = false,
  45. element = this,
  46. instance = $module.data(moduleNamespace),
  47. module
  48. ;
  49. module = {
  50. initialize: function() {
  51. module.verbose('Initializing form validation', $module, validation, settings);
  52. module.bindEvents();
  53. module.set.defaults();
  54. module.instantiate();
  55. },
  56. instantiate: function() {
  57. module.verbose('Storing instance of module', module);
  58. instance = module;
  59. $module
  60. .data(moduleNamespace, module)
  61. ;
  62. },
  63. destroy: function() {
  64. module.verbose('Destroying previous module', instance);
  65. module.removeEvents();
  66. $module
  67. .removeData(moduleNamespace)
  68. ;
  69. },
  70. refresh: function() {
  71. module.verbose('Refreshing selector cache');
  72. $field = $module.find(selector.field);
  73. },
  74. submit: function() {
  75. module.verbose('Submitting form', $module);
  76. $module
  77. .submit()
  78. ;
  79. },
  80. attachEvents: function(selector, action) {
  81. action = action || 'submit';
  82. $(selector)
  83. .on('click', function(event) {
  84. module[action]();
  85. event.preventDefault();
  86. })
  87. ;
  88. },
  89. bindEvents: function() {
  90. if(settings.keyboardShortcuts) {
  91. $field
  92. .on('keydown' + eventNamespace, module.event.field.keydown)
  93. ;
  94. }
  95. $module
  96. .on('submit' + eventNamespace, module.validate.form)
  97. ;
  98. $field
  99. .on('blur' + eventNamespace, module.event.field.blur)
  100. ;
  101. // attach events to common elements
  102. module.attachEvents($submit, 'submit');
  103. module.attachEvents($reset, 'reset');
  104. module.attachEvents($clear, 'clear');
  105. $field
  106. .each(function() {
  107. var
  108. type = $(this).prop('type'),
  109. inputEvent = module.get.changeEvent(type)
  110. ;
  111. $(this)
  112. .on(inputEvent + eventNamespace, module.event.field.change)
  113. ;
  114. })
  115. ;
  116. },
  117. clear: function() {
  118. $field
  119. .each(function () {
  120. var
  121. $field = $(this),
  122. $element = $field.parent(),
  123. $fieldGroup = $field.closest($group),
  124. $prompt = $fieldGroup.find(selector.prompt),
  125. defaultValue = $field.data(metadata.defaultValue) || '',
  126. isCheckbox = $element.is(selector.uiCheckbox),
  127. isDropdown = $element.is(selector.uiDropdown),
  128. isErrored = $fieldGroup.hasClass(className.error)
  129. ;
  130. if(isErrored) {
  131. module.verbose('Resetting error on field', $fieldGroup);
  132. $fieldGroup.removeClass(className.error);
  133. $prompt.remove();
  134. }
  135. if(isDropdown) {
  136. module.verbose('Resetting dropdown value', $element, defaultValue);
  137. $element.dropdown('clear');
  138. }
  139. else if(isCheckbox) {
  140. $element.checkbox('uncheck');
  141. }
  142. else {
  143. module.verbose('Resetting field value', $field, defaultValue);
  144. $field.val('');
  145. }
  146. })
  147. ;
  148. },
  149. reset: function() {
  150. $field
  151. .each(function () {
  152. var
  153. $field = $(this),
  154. $element = $field.parent(),
  155. $fieldGroup = $field.closest($group),
  156. $prompt = $fieldGroup.find(selector.prompt),
  157. defaultValue = $field.data(metadata.defaultValue) || '',
  158. isCheckbox = $element.is(selector.uiCheckbox),
  159. isDropdown = $element.is(selector.uiDropdown),
  160. isErrored = $fieldGroup.hasClass(className.error)
  161. ;
  162. if(isErrored) {
  163. module.verbose('Resetting error on field', $fieldGroup);
  164. $fieldGroup.removeClass(className.error);
  165. $prompt.remove();
  166. }
  167. if(isDropdown) {
  168. module.verbose('Resetting dropdown value', $element, defaultValue);
  169. $element.dropdown('restore defaults');
  170. }
  171. else if(isCheckbox) {
  172. module.verbose('Resetting checkbox value', $element, defaultValue);
  173. if(defaultValue === true) {
  174. $element.checkbox('check');
  175. }
  176. else {
  177. $element.checkbox('uncheck');
  178. }
  179. }
  180. else {
  181. module.verbose('Resetting field value', $field, defaultValue);
  182. $field.val(defaultValue);
  183. }
  184. })
  185. ;
  186. },
  187. removeEvents: function() {
  188. $module
  189. .off(eventNamespace)
  190. ;
  191. $field
  192. .off(eventNamespace)
  193. ;
  194. $submit
  195. .off(eventNamespace)
  196. ;
  197. $field
  198. .off(eventNamespace)
  199. ;
  200. },
  201. event: {
  202. field: {
  203. keydown: function(event) {
  204. var
  205. $field = $(this),
  206. key = event.which,
  207. keyCode = {
  208. enter : 13,
  209. escape : 27
  210. }
  211. ;
  212. if( key == keyCode.escape) {
  213. module.verbose('Escape key pressed blurring field');
  214. $field
  215. .blur()
  216. ;
  217. }
  218. if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) {
  219. $submit
  220. .addClass(className.pressed)
  221. ;
  222. if(!keyHeldDown) {
  223. $field
  224. .one('keyup' + eventNamespace, module.event.field.keyup)
  225. ;
  226. module.submit();
  227. module.debug('Enter pressed on input submitting form');
  228. }
  229. keyHeldDown = true;
  230. }
  231. },
  232. keyup: function() {
  233. keyHeldDown = false;
  234. $submit.removeClass(className.pressed);
  235. },
  236. blur: function() {
  237. var
  238. $field = $(this),
  239. $fieldGroup = $field.closest($group)
  240. ;
  241. if( $fieldGroup.hasClass(className.error) ) {
  242. module.debug('Revalidating field', $field, module.get.validation($field));
  243. module.validate.field( module.get.validation($field) );
  244. }
  245. else if(settings.on == 'blur' || settings.on == 'change') {
  246. module.validate.field( module.get.validation($field) );
  247. }
  248. },
  249. change: function() {
  250. var
  251. $field = $(this),
  252. $fieldGroup = $field.closest($group)
  253. ;
  254. if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) {
  255. clearTimeout(module.timer);
  256. module.timer = setTimeout(function() {
  257. module.debug('Revalidating field', $field, module.get.validation($field));
  258. module.validate.field( module.get.validation($field) );
  259. }, settings.delay);
  260. }
  261. }
  262. }
  263. },
  264. get: {
  265. changeEvent: function(type) {
  266. if(type == 'checkbox' || type == 'radio' || type == 'hidden') {
  267. return 'change';
  268. }
  269. else {
  270. return module.get.inputEvent();
  271. }
  272. },
  273. inputEvent: function() {
  274. return (document.createElement('input').oninput !== undefined)
  275. ? 'input'
  276. : (document.createElement('input').onpropertychange !== undefined)
  277. ? 'propertychange'
  278. : 'keyup'
  279. ;
  280. },
  281. field: function(identifier) {
  282. module.verbose('Finding field with identifier', identifier);
  283. if( $field.filter('#' + identifier).length > 0 ) {
  284. return $field.filter('#' + identifier);
  285. }
  286. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  287. return $field.filter('[name="' + identifier +'"]');
  288. }
  289. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  290. return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
  291. }
  292. return $('<input/>');
  293. },
  294. validation: function($field) {
  295. var
  296. rules
  297. ;
  298. $.each(validation, function(fieldName, field) {
  299. if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
  300. rules = field;
  301. }
  302. });
  303. return rules || false;
  304. },
  305. value: function (field) {
  306. var
  307. fields = [],
  308. results
  309. ;
  310. fields.push(field);
  311. results = module.get.values.call(element, fields);
  312. return results[field];
  313. },
  314. values: function (fields) {
  315. var
  316. values = {}
  317. ;
  318. // return all fields if no parameters
  319. if(!$.isArray(fields)) {
  320. fields = $field;
  321. }
  322. $.each(fields, function(index, field) {
  323. var
  324. $field = (typeof field === 'string')
  325. ? module.get.field(field)
  326. : $(field),
  327. type = $field.prop('type'),
  328. name = $field.prop('name'),
  329. value = $field.val(),
  330. isCheckbox = $field.is(selector.checkbox),
  331. isRadio = $field.is(selector.radio),
  332. isChecked = (isCheckbox)
  333. ? $field.is(':checked')
  334. : false
  335. ;
  336. if(name) {
  337. if(isRadio) {
  338. if(isChecked) {
  339. values[name] = value;
  340. }
  341. }
  342. else if(isCheckbox) {
  343. if(isChecked) {
  344. values[name] = true;
  345. }
  346. else {
  347. module.debug('Omitted unchecked checkbox', $field);
  348. return true;
  349. }
  350. }
  351. else {
  352. values[name] = value;
  353. }
  354. }
  355. });
  356. return values;
  357. }
  358. },
  359. has: {
  360. field: function(identifier) {
  361. module.verbose('Checking for existence of a field with identifier', identifier);
  362. if( $field.filter('#' + identifier).length > 0 ) {
  363. return true;
  364. }
  365. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  366. return true;
  367. }
  368. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  369. return true;
  370. }
  371. return false;
  372. }
  373. },
  374. add: {
  375. prompt: function(identifier, errors) {
  376. var
  377. $field = module.get.field(identifier),
  378. $fieldGroup = $field.closest($group),
  379. $prompt = $fieldGroup.children(selector.prompt),
  380. promptExists = ($prompt.length !== 0)
  381. ;
  382. errors = (typeof errors == 'string')
  383. ? [errors]
  384. : errors
  385. ;
  386. module.verbose('Adding field error state', identifier);
  387. $fieldGroup
  388. .addClass(className.error)
  389. ;
  390. if(settings.inline) {
  391. if(!promptExists) {
  392. $prompt = settings.templates.prompt(errors);
  393. $prompt
  394. .appendTo($fieldGroup)
  395. ;
  396. }
  397. $prompt
  398. .html(errors[0])
  399. ;
  400. if(!promptExists) {
  401. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  402. module.verbose('Displaying error with css transition', settings.transition);
  403. $prompt.transition(settings.transition + ' in', settings.duration);
  404. }
  405. else {
  406. module.verbose('Displaying error with fallback javascript animation');
  407. $prompt
  408. .fadeIn(settings.duration)
  409. ;
  410. }
  411. }
  412. else {
  413. module.verbose('Inline errors are disabled, no inline error added', identifier);
  414. }
  415. }
  416. },
  417. errors: function(errors) {
  418. module.debug('Adding form error messages', errors);
  419. $message
  420. .html( settings.templates.error(errors) )
  421. ;
  422. }
  423. },
  424. remove: {
  425. prompt: function(field) {
  426. var
  427. $field = module.get.field(field.identifier),
  428. $fieldGroup = $field.closest($group),
  429. $prompt = $fieldGroup.children(selector.prompt)
  430. ;
  431. $fieldGroup
  432. .removeClass(className.error)
  433. ;
  434. if(settings.inline && $prompt.is(':visible')) {
  435. module.verbose('Removing prompt for field', field);
  436. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  437. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  438. $prompt.remove();
  439. });
  440. }
  441. else {
  442. $prompt
  443. .fadeOut(settings.duration, function(){
  444. $prompt.remove();
  445. })
  446. ;
  447. }
  448. }
  449. }
  450. },
  451. set: {
  452. success: function() {
  453. $module
  454. .removeClass(className.error)
  455. .addClass(className.success)
  456. ;
  457. },
  458. defaults: function () {
  459. $field
  460. .each(function () {
  461. var
  462. $field = $(this),
  463. isCheckbox = ($field.filter(selector.checkbox).length > 0),
  464. value = (isCheckbox)
  465. ? $field.is(':checked')
  466. : $field.val()
  467. ;
  468. $field.data(metadata.defaultValue, value);
  469. })
  470. ;
  471. },
  472. error: function() {
  473. $module
  474. .removeClass(className.success)
  475. .addClass(className.error)
  476. ;
  477. },
  478. value: function (field, value) {
  479. var
  480. fields = {}
  481. ;
  482. fields[field] = value;
  483. return module.set.values.call(element, fields);
  484. },
  485. values: function (fields) {
  486. if($.isEmptyObject(fields)) {
  487. return;
  488. }
  489. $.each(fields, function(key, value) {
  490. var
  491. $field = module.get.field(key),
  492. $element = $field.parent(),
  493. isCheckbox = $element.is(selector.uiCheckbox),
  494. isDropdown = $element.is(selector.uiDropdown),
  495. isRadio = $field.is(selector.radio),
  496. fieldExists = ($field.length > 0)
  497. ;
  498. if(fieldExists) {
  499. if(isRadio && isCheckbox) {
  500. module.verbose('Selecting radio value', value, $field);
  501. $field.filter('[value="' + value + '"]')
  502. .parent(selector.uiCheckbox)
  503. .checkbox('check')
  504. ;
  505. }
  506. else if(isCheckbox) {
  507. module.verbose('Setting checkbox value', value, $element);
  508. if(value === true) {
  509. $element.checkbox('check');
  510. }
  511. else {
  512. $element.checkbox('uncheck');
  513. }
  514. }
  515. else if(isDropdown) {
  516. module.verbose('Setting dropdown value', value, $element);
  517. $element.dropdown('set selected', value);
  518. }
  519. else {
  520. module.verbose('Setting field value', value, $field);
  521. $field.val(value);
  522. }
  523. }
  524. });
  525. module.validate.form();
  526. }
  527. },
  528. validate: {
  529. form: function(event) {
  530. var
  531. allValid = true,
  532. apiRequest
  533. ;
  534. // input keydown event will fire submit repeatedly by browser default
  535. if(keyHeldDown) {
  536. return false;
  537. }
  538. // reset errors
  539. formErrors = [];
  540. $.each(validation, function(fieldName, field) {
  541. if( !( module.validate.field(field) ) ) {
  542. allValid = false;
  543. }
  544. });
  545. if(allValid) {
  546. module.debug('Form has no validation errors, submitting');
  547. module.set.success();
  548. return settings.onSuccess.call(element, event);
  549. }
  550. else {
  551. module.debug('Form has errors');
  552. module.set.error();
  553. if(!settings.inline) {
  554. module.add.errors(formErrors);
  555. }
  556. // prevent ajax submit
  557. if($module.data('moduleApi') !== undefined) {
  558. event.stopImmediatePropagation();
  559. }
  560. return settings.onFailure.call(element, formErrors);
  561. }
  562. },
  563. // takes a validation object and returns whether field passes validation
  564. field: function(field) {
  565. var
  566. $field = module.get.field(field.identifier),
  567. fieldValid = true,
  568. fieldErrors = []
  569. ;
  570. if($field.prop('disabled')) {
  571. module.debug('Field is disabled. Skipping', field.identifier);
  572. fieldValid = true;
  573. }
  574. else if(field.optional && $.trim($field.val()) === ''){
  575. module.debug('Field is optional and empty. Skipping', field.identifier);
  576. fieldValid = true;
  577. }
  578. else if(field.rules !== undefined) {
  579. $.each(field.rules, function(index, rule) {
  580. if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) {
  581. module.debug('Field is invalid', field.identifier, rule.type);
  582. fieldErrors.push(rule.prompt);
  583. fieldValid = false;
  584. }
  585. });
  586. }
  587. if(fieldValid) {
  588. module.remove.prompt(field, fieldErrors);
  589. settings.onValid.call($field);
  590. }
  591. else {
  592. formErrors = formErrors.concat(fieldErrors);
  593. module.add.prompt(field.identifier, fieldErrors);
  594. settings.onInvalid.call($field, fieldErrors);
  595. return false;
  596. }
  597. return true;
  598. },
  599. // takes validation rule and returns whether field passes rule
  600. rule: function(field, validation) {
  601. var
  602. $field = module.get.field(field.identifier),
  603. type = validation.type,
  604. value = $.trim($field.val() + ''),
  605. bracketRegExp = /\[(.*)\]/i,
  606. bracket = bracketRegExp.exec(type),
  607. isValid = true,
  608. ancillary,
  609. functionType
  610. ;
  611. // if bracket notation is used, pass in extra parameters
  612. if(bracket !== undefined && bracket !== null) {
  613. ancillary = '' + bracket[1];
  614. functionType = type.replace(bracket[0], '');
  615. isValid = settings.rules[functionType].call(element, value, ancillary);
  616. }
  617. // normal notation
  618. else {
  619. isValid = settings.rules[type].call($field, value);
  620. }
  621. return isValid;
  622. }
  623. },
  624. setting: function(name, value) {
  625. if( $.isPlainObject(name) ) {
  626. $.extend(true, settings, name);
  627. }
  628. else if(value !== undefined) {
  629. settings[name] = value;
  630. }
  631. else {
  632. return settings[name];
  633. }
  634. },
  635. internal: function(name, value) {
  636. if( $.isPlainObject(name) ) {
  637. $.extend(true, module, name);
  638. }
  639. else if(value !== undefined) {
  640. module[name] = value;
  641. }
  642. else {
  643. return module[name];
  644. }
  645. },
  646. debug: function() {
  647. if(settings.debug) {
  648. if(settings.performance) {
  649. module.performance.log(arguments);
  650. }
  651. else {
  652. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  653. module.debug.apply(console, arguments);
  654. }
  655. }
  656. },
  657. verbose: function() {
  658. if(settings.verbose && settings.debug) {
  659. if(settings.performance) {
  660. module.performance.log(arguments);
  661. }
  662. else {
  663. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  664. module.verbose.apply(console, arguments);
  665. }
  666. }
  667. },
  668. error: function() {
  669. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  670. module.error.apply(console, arguments);
  671. },
  672. performance: {
  673. log: function(message) {
  674. var
  675. currentTime,
  676. executionTime,
  677. previousTime
  678. ;
  679. if(settings.performance) {
  680. currentTime = new Date().getTime();
  681. previousTime = time || currentTime;
  682. executionTime = currentTime - previousTime;
  683. time = currentTime;
  684. performance.push({
  685. 'Name' : message[0],
  686. 'Arguments' : [].slice.call(message, 1) || '',
  687. 'Element' : element,
  688. 'Execution Time' : executionTime
  689. });
  690. }
  691. clearTimeout(module.performance.timer);
  692. module.performance.timer = setTimeout(module.performance.display, 100);
  693. },
  694. display: function() {
  695. var
  696. title = settings.name + ':',
  697. totalTime = 0
  698. ;
  699. time = false;
  700. clearTimeout(module.performance.timer);
  701. $.each(performance, function(index, data) {
  702. totalTime += data['Execution Time'];
  703. });
  704. title += ' ' + totalTime + 'ms';
  705. if(moduleSelector) {
  706. title += ' \'' + moduleSelector + '\'';
  707. }
  708. if($allModules.length > 1) {
  709. title += ' ' + '(' + $allModules.length + ')';
  710. }
  711. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  712. console.groupCollapsed(title);
  713. if(console.table) {
  714. console.table(performance);
  715. }
  716. else {
  717. $.each(performance, function(index, data) {
  718. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  719. });
  720. }
  721. console.groupEnd();
  722. }
  723. performance = [];
  724. }
  725. },
  726. invoke: function(query, passedArguments, context) {
  727. var
  728. object = instance,
  729. maxDepth,
  730. found,
  731. response
  732. ;
  733. passedArguments = passedArguments || queryArguments;
  734. context = element || context;
  735. if(typeof query == 'string' && object !== undefined) {
  736. query = query.split(/[\. ]/);
  737. maxDepth = query.length - 1;
  738. $.each(query, function(depth, value) {
  739. var camelCaseValue = (depth != maxDepth)
  740. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  741. : query
  742. ;
  743. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  744. object = object[camelCaseValue];
  745. }
  746. else if( object[camelCaseValue] !== undefined ) {
  747. found = object[camelCaseValue];
  748. return false;
  749. }
  750. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  751. object = object[value];
  752. }
  753. else if( object[value] !== undefined ) {
  754. found = object[value];
  755. return false;
  756. }
  757. else {
  758. return false;
  759. }
  760. });
  761. }
  762. if( $.isFunction( found ) ) {
  763. response = found.apply(context, passedArguments);
  764. }
  765. else if(found !== undefined) {
  766. response = found;
  767. }
  768. if($.isArray(returnedValue)) {
  769. returnedValue.push(response);
  770. }
  771. else if(returnedValue !== undefined) {
  772. returnedValue = [returnedValue, response];
  773. }
  774. else if(response !== undefined) {
  775. returnedValue = response;
  776. }
  777. return found;
  778. }
  779. };
  780. if(methodInvoked) {
  781. if(instance === undefined) {
  782. module.initialize();
  783. }
  784. module.invoke(query);
  785. }
  786. else {
  787. if(instance !== undefined) {
  788. module.destroy();
  789. }
  790. module.initialize();
  791. }
  792. })
  793. ;
  794. return (returnedValue !== undefined)
  795. ? returnedValue
  796. : this
  797. ;
  798. };
  799. $.fn.form.settings = {
  800. name : 'Form',
  801. namespace : 'form',
  802. debug : false,
  803. verbose : true,
  804. performance : true,
  805. keyboardShortcuts : true,
  806. on : 'submit',
  807. inline : false,
  808. delay : 200,
  809. revalidate : true,
  810. transition : 'scale',
  811. duration : 200,
  812. onValid : function() {},
  813. onInvalid : function() {},
  814. onSuccess : function() { return true; },
  815. onFailure : function() { return false; },
  816. metadata : {
  817. defaultValue : 'default',
  818. validate : 'validate'
  819. },
  820. selector : {
  821. checkbox : 'input[type="checkbox"], input[type="radio"]',
  822. clear : '.clear',
  823. field : 'input, textarea, select',
  824. group : '.field',
  825. input : 'input',
  826. message : '.error.message',
  827. prompt : '.prompt.label',
  828. radio : 'input[type="radio"]',
  829. reset : '.reset',
  830. submit : '.submit',
  831. uiCheckbox : '.ui.checkbox',
  832. uiDropdown : '.ui.dropdown'
  833. },
  834. className : {
  835. error : 'error',
  836. label : 'ui prompt label',
  837. pressed : 'down',
  838. success : 'success'
  839. },
  840. error: {
  841. method : 'The method you called is not defined.'
  842. },
  843. templates: {
  844. // template that produces error message
  845. error: function(errors) {
  846. var
  847. html = '<ul class="list">'
  848. ;
  849. $.each(errors, function(index, value) {
  850. html += '<li>' + value + '</li>';
  851. });
  852. html += '</ul>';
  853. return $(html);
  854. },
  855. // template that produces label
  856. prompt: function(errors) {
  857. return $('<div/>')
  858. .addClass('ui red pointing prompt label')
  859. .html(errors[0])
  860. ;
  861. }
  862. },
  863. rules: {
  864. // checkbox checked
  865. checked: function() {
  866. return ($(this).filter(':checked').length > 0);
  867. },
  868. // value contains (text)
  869. contains: function(value, text) {
  870. text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  871. return (value.search(text) !== -1);
  872. },
  873. // is most likely an email
  874. email: function(value){
  875. var
  876. emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", "i")
  877. ;
  878. return emailRegExp.test(value);
  879. },
  880. // is not empty or blank string
  881. empty: function(value) {
  882. return !(value === undefined || '' === value);
  883. },
  884. // is valid integer
  885. integer: function(value, range) {
  886. var
  887. intRegExp = /^\-?\d+$/,
  888. min,
  889. max,
  890. parts
  891. ;
  892. if(range === undefined || range === '' || range === '..') {
  893. // do nothing
  894. }
  895. else if(range.indexOf('..') == -1) {
  896. if(intRegExp.test(range)) {
  897. min = max = range - 0;
  898. }
  899. }
  900. else {
  901. parts = range.split('..', 2);
  902. if(intRegExp.test(parts[0])) {
  903. min = parts[0] - 0;
  904. }
  905. if(intRegExp.test(parts[1])) {
  906. max = parts[1] - 0;
  907. }
  908. }
  909. return (
  910. intRegExp.test(value) &&
  911. (min === undefined || value >= min) &&
  912. (max === undefined || value <= max)
  913. );
  914. },
  915. // is exactly value
  916. is: function(value, text) {
  917. return (value == text);
  918. },
  919. // is at least string length
  920. length: function(value, requiredLength) {
  921. return (value !== undefined)
  922. ? (value.length >= requiredLength)
  923. : false
  924. ;
  925. },
  926. // matches another field
  927. match: function(value, fieldIdentifier) {
  928. // use either id or name of field
  929. var
  930. $form = $(this),
  931. matchingValue
  932. ;
  933. if($form.find('#' + fieldIdentifier).length > 0) {
  934. matchingValue = $form.find('#' + fieldIdentifier).val();
  935. }
  936. else if($form.find('[name="' + fieldIdentifier +'"]').length > 0) {
  937. matchingValue = $form.find('[name="' + fieldIdentifier + '"]').val();
  938. }
  939. else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').length > 0 ) {
  940. matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val();
  941. }
  942. return (matchingValue !== undefined)
  943. ? ( value.toString() == matchingValue.toString() )
  944. : false
  945. ;
  946. },
  947. // string length is less than max length
  948. maxLength: function(value, maxLength) {
  949. return (value !== undefined)
  950. ? (value.length <= maxLength)
  951. : false
  952. ;
  953. },
  954. // value is not exactly notValue
  955. not: function(value, notValue) {
  956. return (value != notValue);
  957. },
  958. // value is most likely url
  959. url: function(value) {
  960. var
  961. urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
  962. ;
  963. return urlRegExp.test(value);
  964. }
  965. }
  966. };
  967. })( jQuery, window , document );