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.

206 lines
5.3 KiB

  1. (function($K)
  2. {
  3. $K.add('module', 'validate', {
  4. init: function(app, context)
  5. {
  6. this.app = app;
  7. this.$win = app.$win;
  8. this.progress = app.progress;
  9. this.response = app.response;
  10. // defaults
  11. var defaults = {
  12. errorClass: 'is-error',
  13. send: true,
  14. trigger: false,
  15. shortcut: false,
  16. progress: false
  17. };
  18. // context
  19. this.context = context;
  20. this.params = context.getParams(defaults);
  21. this.$element = context.getElement();
  22. },
  23. // public
  24. start: function()
  25. {
  26. this._disableDefaultValidation();
  27. this._enableShortcut();
  28. if (this.params.trigger)
  29. {
  30. this._startTrigger();
  31. }
  32. else
  33. {
  34. this._startSubmit();
  35. }
  36. },
  37. stop: function()
  38. {
  39. this.enableButtons();
  40. this.clear();
  41. this.$element.off('.kube.validate');
  42. this.$win.off('.kube.validate');
  43. if (this.$trigger) this.$trigger.off('.');
  44. },
  45. clear: function()
  46. {
  47. this.$element.find('.' + this.params.errorClass).each(this._clearError.bind(this));
  48. },
  49. disableButtons: function()
  50. {
  51. this.$element.find('button').attr('disabled', true);
  52. },
  53. enableButtons: function()
  54. {
  55. this.$element.find('button').removeAttr('disabled');
  56. },
  57. // private
  58. _build: function(e)
  59. {
  60. e.preventDefault();
  61. if (this.params.send) this._send();
  62. else this.app.broadcast('validate.send', this);
  63. return false;
  64. },
  65. _send: function()
  66. {
  67. if (this.params.progress)
  68. {
  69. this.progress.show();
  70. }
  71. this.disableButtons();
  72. this._saveCodeMirror();
  73. this.app.broadcast('validate.send', this);
  74. $K.ajax.post({
  75. url: this.$element.attr('action'),
  76. data: this.$element.serialize(),
  77. success: this._parse.bind(this)
  78. });
  79. return false;
  80. },
  81. _parse: function(data)
  82. {
  83. this.enableButtons();
  84. this.clear();
  85. if (this.params.progress)
  86. {
  87. this.progress.hide();
  88. }
  89. var json = this.response.parse(data);
  90. if (!json)
  91. {
  92. this.app.broadcast('validate.error', this, json);
  93. }
  94. else if (typeof json.type !== 'undefined' && json.type === 'error')
  95. {
  96. this._setErrors(json.errors);
  97. this.app.broadcast('validate.error', this, json.errors);
  98. }
  99. else
  100. {
  101. this.app.broadcast('validate.success', this, json);
  102. }
  103. },
  104. _setErrors: function(errors)
  105. {
  106. for (var name in errors)
  107. {
  108. var text = errors[name];
  109. var $el = this.$element.find('[name=' + name + ']');
  110. if ($el.length !== 0)
  111. {
  112. $el.addClass(this.params.errorClass);
  113. this._setFieldEvent($el, name);
  114. if (text !== '')
  115. {
  116. this._showErrorText(name, text);
  117. }
  118. }
  119. }
  120. },
  121. _setFieldEvent: function($el, name)
  122. {
  123. var eventName = this._getFieldEventName($el);
  124. $el.on(eventName + '.kube.validate', function()
  125. {
  126. this._clearError($el);
  127. }.bind(this));
  128. },
  129. _showErrorText: function(name, text)
  130. {
  131. var $el = this.$element.find('#' + name + '-validation-error');
  132. $el.addClass(this.params.errorClass);
  133. $el.html(text);
  134. $el.removeClass('is-hidden');
  135. },
  136. _getFieldEventName: function($el)
  137. {
  138. return ($el.get().tagName === 'SELECT' || $el.attr('type') === 'checkbox' || $el.attr('type') === 'radio') ? 'change' : 'keyup';
  139. },
  140. _clearError: function(node)
  141. {
  142. var $el = $K.dom(node);
  143. var $errorEl = this.$element.find('#' + $el.attr('name') + '-validation-error');
  144. $errorEl.removeClass(this.params.errorClass);
  145. $errorEl.html('');
  146. $errorEl.addClass('is-hidden');
  147. $el.removeClass(this.params.errorClass).off('.kube.validate');
  148. },
  149. _saveCodeMirror: function()
  150. {
  151. $K.dom('.CodeMirror').each(function(node)
  152. {
  153. node.CodeMirror.save();
  154. });
  155. },
  156. _disableDefaultValidation: function()
  157. {
  158. this.$element.attr('novalidate', 'novalidate');
  159. },
  160. _enableShortcut: function()
  161. {
  162. if (!this.params.shortcut) return;
  163. // ctrl + s or cmd + s
  164. this.$win.on('keydown.kube.validate', this._handleShortcut.bind(this));
  165. },
  166. _handleShortcut: function(e)
  167. {
  168. if (((e.ctrlKey || e.metaKey) && e.which === 83))
  169. {
  170. e.preventDefault();
  171. return this._send();
  172. }
  173. return true;
  174. },
  175. _startTrigger: function()
  176. {
  177. this.$trigger = $(this.opts.trigger);
  178. this.$element.on('submit', function() { return false; });
  179. this.$trigger.off('.kube.validate');
  180. this.$trigger.on('click.kube.validate', this._build.bind(this));
  181. },
  182. _startSubmit: function()
  183. {
  184. this.$element.on('submit.kube.validate', this._build.bind(this));
  185. }
  186. });
  187. })(Kube);