form.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. (function () {
  2. /**
  3. * 表单提交
  4. *
  5. * @param opts
  6. * @constructor
  7. */
  8. var $eColumns = {};
  9. LA.Form = function (opts) {
  10. opts = $.extend({
  11. $form: null,
  12. errorClass: 'has-error',
  13. groupSelector: '.form-group',
  14. template: '<label class="control-label" for="inputError"><i class="fa fa-times-circle-o"></i> _message_</label><br/>',
  15. disableRedirect: false, //
  16. columnSelectors: {}, //
  17. disableRemoveError: false,
  18. after: function (success, data) {},
  19. }, opts);
  20. var originalVals = {},
  21. cls = opts.errorClass,
  22. groupSlt = opts.groupSelector,
  23. tpl = opts.template,
  24. $form = opts.$form,
  25. tabSelector = '.tab-pane',
  26. get_tab_id = function ($c) {
  27. return $c.parents(tabSelector).attr('id');
  28. },
  29. get_tab_title_error = function ($c) {
  30. var id = get_tab_id($c);
  31. if (!id) return $('<none></none>');
  32. return $("[href='#" + id + "'] .text-red");
  33. };
  34. // 移除错误信息
  35. remove_field_error();
  36. $form.ajaxSubmit({
  37. beforeSubmit: function (d, f, o) {
  38. if (call_events(LA._form_.before, d, f, o) === false) {
  39. return false;
  40. }
  41. LA.NP.start();
  42. },
  43. success: function (d) {
  44. LA.NP.done();
  45. if (opts.after(true, d) === false) {
  46. return;
  47. }
  48. if (call_events(LA._form_.success, d) === false) {
  49. return;
  50. }
  51. if (!d.status) {
  52. LA.error(d.message || 'Save failed!');
  53. return;
  54. }
  55. LA.success(d.message || 'Save succeeded!');
  56. if (opts.disableRedirect || d.redirect === false) return;
  57. if (d.redirect) {
  58. return LA.reload(d.redirect);
  59. }
  60. history.back(-1);
  61. },
  62. error: function (v) {
  63. LA.NP.done();
  64. if (opts.after(false, v) === false) {
  65. return;
  66. }
  67. if (call_events(LA._form_.error, v) === false) {
  68. return;
  69. }
  70. try {
  71. var error = JSON.parse(v.responseText), i;
  72. if (v.status != 422 || !error || !LA.isset(error, 'errors')) {
  73. return LA.error(v.status + ' ' + v.statusText);
  74. }
  75. error = error.errors;
  76. for (i in error) {
  77. // 显示错误信息
  78. $eColumns[i] = show_field_error($form, i, error[i]);
  79. }
  80. } catch (e) {
  81. return LA.error(v.status + ' ' + v.statusText);
  82. }
  83. }
  84. });
  85. // 触发钩子事件
  86. function call_events(evs) {
  87. var i, r, a = arguments, j, p = [];
  88. delete a[0];
  89. a = a || [];
  90. for (j in a) {
  91. p.push(a[j]);
  92. }
  93. for (i in evs) {
  94. r = evs[i].apply(evs[i], p);
  95. if (r === false) return r; // 返回 false 会代码阻止继续执行
  96. }
  97. }
  98. // 删除错误有字段的错误信息
  99. function remove_field_error() {
  100. var i, p, t;
  101. for (i in $eColumns) {
  102. p = $eColumns[i].parents(groupSlt);
  103. p.removeClass(cls);
  104. p.find('error').html('');
  105. t = get_tab_title_error($eColumns[i]);
  106. if (!t.hasClass('hide')) {
  107. t.addClass('hide');
  108. }
  109. }
  110. // 重置
  111. $eColumns = {};
  112. }
  113. // 显示错误信息
  114. function show_field_error($form, column, errors) {
  115. var $c = get_field_obj($form, column);
  116. get_tab_title_error($c).removeClass('hide');
  117. // 保存字段原始数据
  118. originalVals[column] = get_val($c);
  119. if (!$c) {
  120. if (LA.len(errors) && errors.length) {
  121. LA.error(errors.join(" \n "));
  122. }
  123. return;
  124. }
  125. var p = $c.closest(groupSlt), j;
  126. p.addClass(cls);
  127. for (j in errors) {
  128. p.find('error').eq(0).append(tpl.replace('_message_', errors[j]));
  129. }
  130. if (!opts.disableRemoveError) {
  131. remove_error_when_val_changed($c, column);
  132. }
  133. return $c;
  134. }
  135. // 获取字段对象
  136. function get_field_obj($form, column) {
  137. if (column.indexOf('.') != -1) {
  138. column = column.split('.');
  139. var first = column.shift(), i, sub = '';
  140. for (i in column) {
  141. sub += '[' + column[i] + ']';
  142. }
  143. column = first + sub;
  144. }
  145. var $c = $form.find('[name="' + column + '"]');
  146. if (!$c.length) $c = $form.find('[name="' + column + '[]"]');
  147. if (!$c.length) {
  148. $c = $form.find('[name="' + column.replace(/start$/, '') + '"]');
  149. }
  150. if (!$c.length) {
  151. $c = $form.find('[name="' + column.replace(/end$/, '') + '"]');
  152. }
  153. if (!$c.length) {
  154. $c = $form.find('[name="' + column.replace(/start\]$/, ']') + '"]');
  155. }
  156. if (!$c.length) {
  157. $c = $form.find('[name="' + column.replace(/end\]$/, ']') + '"]');
  158. }
  159. return $c;
  160. }
  161. // 获取字段值
  162. function get_val($c) {
  163. var vals = [],
  164. t = $c.attr('type'),
  165. cked = t === 'checkbox' || t === 'radio',
  166. i;
  167. for (i = 0; i < $c.length; i++) {
  168. if (cked) {
  169. vals.push($($c[i]).prop('checked'));
  170. continue;
  171. }
  172. vals.push($($c[i]).val());
  173. }
  174. return vals;
  175. }
  176. // 当字段值变化时移除错误信息
  177. function remove_error_when_val_changed($c, column) {
  178. var p = $c.parents(groupSlt);
  179. $c.one('change', rm);
  180. $c.off('blur', rm).on('blur', function () {
  181. if (val_changed()) rm();
  182. });
  183. // 表单值发生变化就移除错误信息
  184. function autorm() {
  185. setTimeout(function () {
  186. if (!$c.length) return;
  187. if (val_changed()) return rm();
  188. autorm();
  189. }, 500);
  190. }
  191. autorm();
  192. // 判断值是否改变
  193. function val_changed() {
  194. return !LA.arr.equal(originalVals[column], get_val($c));
  195. }
  196. function rm() {
  197. p.removeClass(cls);
  198. p.find('error').html('');
  199. // tab页下没有错误信息了,隐藏title的错误图标
  200. var id = get_tab_id($c), t;
  201. if (id && !$('#'+id).find('.'+cls).length) {
  202. t = get_tab_title_error($c);
  203. if (!t.hasClass('hide')) {
  204. t.addClass('hide');
  205. }
  206. }
  207. delete $eColumns[column];
  208. }
  209. }
  210. };
  211. })();