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
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
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
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
10 years ago
10 years ago
9 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 );