25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

303 lines
10 KiB

  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. /* global BASE_URL, alertAlreadyDisplayed */
  6. define([
  7. 'jquery',
  8. 'underscore',
  9. 'Magento_Ui/js/modal/alert',
  10. 'jquery/ui',
  11. 'jquery/validate',
  12. 'mage/translate',
  13. 'mage/validation'
  14. ], function ($, _, alert) {
  15. 'use strict';
  16. $.extend(true, $.validator.prototype, {
  17. /**
  18. * Focus invalid fields
  19. */
  20. focusInvalid: function () {
  21. if (this.settings.focusInvalid) {
  22. try {
  23. $(this.errorList.length && this.errorList[0].element || [])
  24. .trigger('focus')
  25. .trigger('focusin');
  26. } catch (e) {
  27. // ignore IE throwing errors when focusing hidden elements
  28. }
  29. }
  30. },
  31. /**
  32. * Elements.
  33. */
  34. elements: function () {
  35. var validator = this,
  36. rulesCache = {};
  37. // select all valid inputs inside the form (no submit or reset buttons)
  38. return $(this.currentForm)
  39. .find('input, select, textarea')
  40. .not(this.settings.forceIgnore)
  41. .not(':submit, :reset, :image, [disabled]')
  42. .not(this.settings.ignore)
  43. .filter(function () {
  44. if (!this.name && validator.settings.debug && window.console) {
  45. console.error('%o has no name assigned', this);
  46. }
  47. // select only the first element for each name, and only those with rules specified
  48. if (this.name in rulesCache || !validator.objectLength($(this).rules())) {
  49. return false;
  50. }
  51. rulesCache[this.name] = true;
  52. return true;
  53. });
  54. }
  55. });
  56. $.extend($.fn, {
  57. /**
  58. * ValidationDelegate overridden for those cases where the form is located in another form,
  59. * to avoid not correct working of validate plug-in
  60. * @override
  61. * @param {String} delegate - selector, if event target matched against this selector,
  62. * then event will be delegated
  63. * @param {String} type - event type
  64. * @param {Function} handler - event handler
  65. * @return {Element}
  66. */
  67. validateDelegate: function (delegate, type, handler) {
  68. return this.on(type, $.proxy(function (event) {
  69. var target = $(event.target),
  70. form = target[0].form;
  71. if (form && $(form).is(this) && $.data(form, 'validator') && target.is(delegate)) {
  72. return handler.apply(target, arguments);
  73. }
  74. }, this));
  75. }
  76. });
  77. $.widget('mage.validation', $.mage.validation, {
  78. options: {
  79. messagesId: 'messages',
  80. forceIgnore: '',
  81. ignore: ':disabled, .ignore-validate, .no-display.template, ' +
  82. ':disabled input, .ignore-validate input, .no-display.template input, ' +
  83. ':disabled select, .ignore-validate select, .no-display.template select, ' +
  84. ':disabled textarea, .ignore-validate textarea, .no-display.template textarea',
  85. errorElement: 'label',
  86. errorUrl: typeof BASE_URL !== 'undefined' ? BASE_URL : null,
  87. /**
  88. * @param {HTMLElement} element
  89. */
  90. highlight: function (element) {
  91. if ($.validator.defaults.highlight && typeof $.validator.defaults.highlight === 'function') {
  92. $.validator.defaults.highlight.apply(this, arguments);
  93. }
  94. $(element).trigger('highlight.validate');
  95. },
  96. /**
  97. * @param {HTMLElement} element
  98. */
  99. unhighlight: function (element) {
  100. if ($.validator.defaults.unhighlight && typeof $.validator.defaults.unhighlight === 'function') {
  101. $.validator.defaults.unhighlight.apply(this, arguments);
  102. }
  103. $(element).trigger('unhighlight.validate');
  104. }
  105. },
  106. /**
  107. * Validation creation
  108. * @protected
  109. */
  110. _create: function () {
  111. if (!this.options.submitHandler && typeof this.options.submitHandler !== 'function') {
  112. if (!this.options.frontendOnly && this.options.validationUrl) {
  113. this.options.submitHandler = $.proxy(this._ajaxValidate, this);
  114. } else {
  115. this.options.submitHandler = $.proxy(this._submit, this);
  116. }
  117. }
  118. this.element.on('resetElement', function (e) {
  119. $(e.target).rules('remove');
  120. });
  121. this._super('_create');
  122. },
  123. /**
  124. * ajax validation
  125. * @protected
  126. */
  127. _ajaxValidate: function () {
  128. $.ajax({
  129. url: this.options.validationUrl,
  130. type: 'POST',
  131. dataType: 'json',
  132. data: this.element.serialize(),
  133. context: $('body'),
  134. success: $.proxy(this._onSuccess, this),
  135. error: $.proxy(this._onError, this),
  136. showLoader: true,
  137. dontHide: false
  138. });
  139. },
  140. /**
  141. * Process ajax success.
  142. *
  143. * @protected
  144. * @param {Object} response
  145. */
  146. _onSuccess: function (response) {
  147. if (!response.error) {
  148. this._submit();
  149. } else {
  150. this._showErrors(response);
  151. $(this.element[0]).trigger('afterValidate.error');
  152. $('body').trigger('processStop');
  153. }
  154. },
  155. /**
  156. * Submitting a form.
  157. * @private
  158. */
  159. _submit: function () {
  160. $(this.element[0]).trigger('afterValidate.beforeSubmit');
  161. this.element[0].submit();
  162. },
  163. /**
  164. * Displays errors after backend validation.
  165. *
  166. * @param {Object} data - Data that came from backend.
  167. */
  168. _showErrors: function (data) {
  169. $('body').notification('clear')
  170. .notification('add', {
  171. error: data.error,
  172. message: data.message,
  173. /**
  174. * @param {*} message
  175. */
  176. insertMethod: function (message) {
  177. $('.messages:first').html(message);
  178. }
  179. });
  180. },
  181. /**
  182. * Tries to retrieve element either by id or by inputs' name property.
  183. * @param {String} code - String to search by.
  184. * @returns {jQuery} jQuery element.
  185. */
  186. _getByCode: function (code) {
  187. var parent = this.element[0],
  188. element;
  189. element = parent.querySelector('#' + code) || parent.querySelector('input[name=' + code + ']');
  190. return $(element);
  191. },
  192. /**
  193. * Process ajax error
  194. * @protected
  195. */
  196. _onError: function () {
  197. $(this.element[0]).trigger('afterValidate.error');
  198. $('body').trigger('processStop');
  199. if (this.options.errorUrl) {
  200. location.href = this.options.errorUrl;
  201. }
  202. }
  203. });
  204. _.each({
  205. 'validate-greater-zero-based-on-option': [
  206. function (v, el) {
  207. var optionType = $(el)
  208. .closest('.form-list')
  209. .prev('.fieldset-alt')
  210. .find('select.select-product-option-type'),
  211. optionTypeVal = optionType.val();
  212. v = Number(v) || 0;
  213. if (optionType && (optionTypeVal == 'checkbox' || optionTypeVal == 'multi') && v <= 0) { //eslint-disable-line
  214. return false;
  215. }
  216. return true;
  217. },
  218. $.mage.__('Please enter a number greater 0 in this field.')
  219. ],
  220. 'validate-rating': [
  221. function () {
  222. var ratings = $('#detailed_rating').find('.field-rating'),
  223. noError = true;
  224. ratings.each(function (index, rating) {
  225. noError = noError && $(rating).find('input:checked').length > 0;
  226. });
  227. return noError;
  228. },
  229. $.mage.__('Please select one of each ratings above.')
  230. ],
  231. 'validate-downloadable-file': [
  232. function (v, element) {
  233. var elmParent = $(element).parent(),
  234. linkType = elmParent.find('input[value="file"]'),
  235. newFileContainer;
  236. if (linkType.is(':checked') && (v === '' || v === '[]')) {
  237. newFileContainer = elmParent.find('.new-file');
  238. if (!alertAlreadyDisplayed && (newFileContainer.empty() || newFileContainer.is(':visible'))) {
  239. window.alertAlreadyDisplayed = true;
  240. alert({
  241. content: $.mage.__('There are files that were selected but not uploaded yet. ' +
  242. 'Please upload or remove them first')
  243. });
  244. }
  245. return false;
  246. }
  247. return true;
  248. },
  249. 'Please upload a file.'
  250. ],
  251. 'validate-downloadable-url': [
  252. function (v, element) {
  253. var linkType = $(element).parent().find('input[value="url"]');
  254. if (linkType.is(':checked') && v === '') {
  255. return false;
  256. }
  257. return true;
  258. },
  259. $.mage.__('Please specify Url.')
  260. ]
  261. }, function (rule, i) {
  262. rule.unshift(i);
  263. $.validator.addMethod.apply($.validator, rule);
  264. });
  265. return $.mage.validation;
  266. });