Advertisement
Guest User

Untitled

a guest
Mar 30th, 2020
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.93 KB | None | 0 0
  1. /**
  2. * yii2-dynamic-form
  3. *
  4. * A jQuery plugin to clone form elements in a nested manner, maintaining accessibility.
  5. *
  6. * @author Wanderson Bragança <wanderson.wbc@gmail.com>
  7. */
  8. (function ($) {
  9. var pluginName = 'yiiDynamicForm';
  10.  
  11. var regexID = /^(.+?)([-\d-]{1,})(.+)$/i;
  12.  
  13. var regexName = /(^.+?)([\[\d{1,}\]]{1,})(\[.+\]$)/i;
  14.  
  15. $.fn.yiiDynamicForm = function (method) {
  16. if (methods[method]) {
  17. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  18. } else if (typeof method === 'object' || !method) {
  19. return methods.init.apply(this, arguments);
  20. } else {
  21. $.error('Method ' + method + ' does not exist on jQuery.yiiDynamicForm');
  22. return false;
  23. }
  24. };
  25.  
  26. var events = {
  27. beforeInsert: 'beforeInsert',
  28. afterInsert: 'afterInsert',
  29. beforeDelete: 'beforeDelete',
  30. afterDelete: 'afterDelete',
  31. limitReached: 'limitReached'
  32. };
  33.  
  34. var methods = {
  35. init: function (widgetOptions) {
  36. return this.each(function () {
  37. widgetOptions.template = _parseTemplate(widgetOptions);
  38. });
  39. },
  40.  
  41. addItem: function (widgetOptions, e, $elem) {
  42. _addItem(widgetOptions, e, $elem);
  43. },
  44.  
  45. deleteItem: function (widgetOptions, e, $elem) {
  46. _deleteItem(widgetOptions, e, $elem);
  47. },
  48.  
  49. updateContainer: function () {
  50. var widgetOptions = eval($(this).attr('data-dynamicform'));
  51. _updateAttributes(widgetOptions);
  52. _restoreSpecialJs(widgetOptions);
  53. _fixFormValidaton(widgetOptions);
  54. }
  55. };
  56.  
  57. var _parseTemplate = function(widgetOptions) {
  58.  
  59. var $template = $(widgetOptions.template);
  60. $template.find('div[data-dynamicform]').each(function(){
  61. var widgetOptions = eval($(this).attr('data-dynamicform'));
  62. if ($(widgetOptions.widgetItem).length > 1) {
  63. var item = $(this).find(widgetOptions.widgetItem).first()[0].outerHTML;
  64. $(this).find(widgetOptions.widgetBody).html(item);
  65. }
  66. });
  67.  
  68. $template.find('input, textarea, select').each(function() {
  69. $(this).val('');
  70. });
  71.  
  72. $template.find('input[type="checkbox"], input[type="radio"]').each(function() {
  73. var inputName = $(this).attr('name');
  74. var $inputHidden = $template.find('input[type="hidden"][name="' + inputName + '"]').first();
  75. if ($inputHidden) {
  76. $(this).val(1);
  77. $inputHidden.val(0);
  78. }
  79. });
  80.  
  81. return $template;
  82. };
  83.  
  84. var _getWidgetOptionsRoot = function(widgetOptions) {
  85. return eval($(widgetOptions.widgetBody).parents('div[data-dynamicform]').last().attr('data-dynamicform'));
  86. };
  87.  
  88. var _getLevel = function($elem) {
  89. var level = $elem.parents('div[data-dynamicform]').length;
  90. level = (level < 0) ? 0 : level;
  91. return level;
  92. };
  93.  
  94. var _count = function($elem, widgetOptions) {
  95. return $elem.closest('.' + widgetOptions.widgetContainer).find(widgetOptions.widgetItem).length;
  96. };
  97.  
  98. var _createIdentifiers = function(level) {
  99. return new Array(level + 2).join('0').split('');
  100. };
  101.  
  102. var _addItem = function(widgetOptions, e, $elem) {
  103. var count = _count($elem, widgetOptions);
  104.  
  105. if (count < widgetOptions.limit) {
  106. $toclone = widgetOptions.template;
  107. $newclone = $toclone.clone(false, false);
  108.  
  109. if (widgetOptions.insertPosition === 'top') {
  110. $elem.closest('.' + widgetOptions.widgetContainer).find(widgetOptions.widgetBody).prepend($newclone);
  111. } else {
  112. $elem.closest('.' + widgetOptions.widgetContainer).find(widgetOptions.widgetBody).append($newclone);
  113. }
  114.  
  115. _updateAttributes(widgetOptions);
  116. _restoreSpecialJs(widgetOptions);
  117. _fixFormValidaton(widgetOptions);
  118. $elem.closest('.' + widgetOptions.widgetContainer).triggerHandler(events.afterInsert, $newclone);
  119. } else {
  120. // trigger a custom event for hooking
  121. $elem.closest('.' + widgetOptions.widgetContainer).triggerHandler(events.limitReached, widgetOptions.limit);
  122. }
  123. };
  124.  
  125. var _removeValidations = function($elem, widgetOptions, count) {
  126. if (count > 1) {
  127. $elem.find('div[data-dynamicform]').each(function() {
  128. var currentWidgetOptions = eval($(this).attr('data-dynamicform'));
  129. var level = _getLevel($(this));
  130. var identifiers = _createIdentifiers(level);
  131. var numItems = $(this).find(currentWidgetOptions.widgetItem).length;
  132.  
  133. for (var i = 1; i <= numItems -1; i++) {
  134. var aux = identifiers;
  135. aux[level] = i;
  136. currentWidgetOptions.fields.forEach(function(input) {
  137. var id = input.id.replace("{}", aux.join('-'));
  138. if ($("#" + currentWidgetOptions.formId).yiiActiveForm("find", id) !== "undefined") {
  139. $("#" + currentWidgetOptions.formId).yiiActiveForm("remove", id);
  140. }
  141. });
  142. }
  143. });
  144.  
  145. var level = _getLevel($elem.closest('.' + widgetOptions.widgetContainer));
  146. var widgetOptionsRoot = _getWidgetOptionsRoot(widgetOptions);
  147. var identifiers = _createIdentifiers(level);
  148. identifiers[0] = $(widgetOptionsRoot.widgetItem).length - 1;
  149. identifiers[level] = count - 1;
  150.  
  151. widgetOptions.fields.forEach(function(input) {
  152. var id = input.id.replace("{}", identifiers.join('-'));
  153. if ($("#" + widgetOptions.formId).yiiActiveForm("find", id) !== "undefined") {
  154. $("#" + widgetOptions.formId).yiiActiveForm("remove", id);
  155. }
  156. });
  157. }
  158. };
  159.  
  160. var _deleteItem = function(widgetOptions, e, $elem) {
  161. var count = _count($elem, widgetOptions);
  162.  
  163. if (count > widgetOptions.min) {
  164. $todelete = $elem.closest(widgetOptions.widgetItem);
  165.  
  166. // trigger a custom event for hooking
  167. var eventResult = $('.' + widgetOptions.widgetContainer).triggerHandler(events.beforeDelete, $todelete);
  168. if (eventResult !== false) {
  169. _removeValidations($todelete, widgetOptions, count);
  170. $todelete.remove();
  171. _updateAttributes(widgetOptions);
  172. _restoreSpecialJs(widgetOptions);
  173. _fixFormValidaton(widgetOptions);
  174. $('.' + widgetOptions.widgetContainer).triggerHandler(events.afterDelete);
  175. }
  176. }
  177. };
  178.  
  179. var _updateAttrID = function($elem, index) {
  180. var widgetOptions = eval($elem.closest('div[data-dynamicform]').attr('data-dynamicform'));
  181. var id = $elem.attr('id');
  182. var newID = id;
  183.  
  184. if (id !== undefined) {
  185. var matches = id.match(regexID);
  186. if (matches && matches.length === 4) {
  187. matches[2] = matches[2].substring(1, matches[2].length - 1);
  188. var identifiers = matches[2].split('-');
  189. identifiers[0] = index;
  190.  
  191. if (identifiers.length > 1) {
  192. var widgetsOptions = [];
  193. $elem.parents('div[data-dynamicform]').each(function(i){
  194. widgetsOptions[i] = eval($(this).attr('data-dynamicform'));
  195. });
  196.  
  197. widgetsOptions = widgetsOptions.reverse();
  198. for (var i = identifiers.length - 1; i >= 1; i--) {
  199. identifiers[i] = $elem.closest(widgetsOptions[i].widgetItem).index();
  200. }
  201. }
  202.  
  203. newID = matches[1] + '-' + identifiers.join('-') + '-' + matches[3];
  204. $elem.attr('id', newID);
  205. } else {
  206. newID = id + index;
  207. $elem.attr('id', newID);
  208. }
  209. }
  210.  
  211. if (id !== newID) {
  212. $elem.closest(widgetOptions.widgetItem).find('.field-' + id).each(function() {
  213. $(this).removeClass('field-' + id).addClass('field-' + newID);
  214. });
  215. // update "for" attribute
  216. $elem.closest(widgetOptions.widgetItem).find("label[for='" + id + "']").attr('for',newID);
  217. }
  218.  
  219. return newID;
  220. };
  221.  
  222. var _updateAttrName = function($elem, index) {
  223. var name = $elem.attr('name');
  224.  
  225. if (name !== undefined) {
  226. var matches = name.match(regexName);
  227.  
  228. if (matches && matches.length === 4) {
  229. matches[2] = matches[2].replace(/\]\[/g, "-").replace(/\]|\[/g, '');
  230. var identifiers = matches[2].split('-');
  231. identifiers[0] = index;
  232.  
  233. if (identifiers.length > 1) {
  234. var widgetsOptions = [];
  235. $elem.parents('div[data-dynamicform]').each(function(i){
  236. widgetsOptions[i] = eval($(this).attr('data-dynamicform'));
  237. });
  238.  
  239. widgetsOptions = widgetsOptions.reverse();
  240. for (var i = identifiers.length - 1; i >= 1; i--) {
  241. identifiers[i] = $elem.closest(widgetsOptions[i].widgetItem).index();
  242. }
  243. }
  244.  
  245. name = matches[1] + '[' + identifiers.join('][') + ']' + matches[3];
  246. $elem.attr('name', name);
  247. }
  248. }
  249.  
  250. return name;
  251. };
  252.  
  253. var _updateAttributes = function(widgetOptions) {
  254. var widgetOptionsRoot = _getWidgetOptionsRoot(widgetOptions);
  255.  
  256. $(widgetOptionsRoot.widgetItem).each(function(index) {
  257. var $item = $(this);
  258. $(this).find('*').each(function() {
  259. // update "id" attribute
  260. _updateAttrID($(this), index);
  261.  
  262. // update "name" attribute
  263. _updateAttrName($(this), index);
  264. });
  265. });
  266. };
  267.  
  268. var _fixFormValidatonInput = function(widgetOptions, attribute, id, name) {
  269. if (attribute !== undefined) {
  270. attribute = $.extend(true, {}, attribute);
  271. attribute.id = id;
  272. attribute.container = ".field-" + id;
  273. attribute.input = "#" + id;
  274. attribute.name = name;
  275. attribute.value = $("#" + id).val();
  276. attribute.status = 0;
  277.  
  278. if ($("#" + widgetOptions.formId).yiiActiveForm("find", id) !== "undefined") {
  279. $("#" + widgetOptions.formId).yiiActiveForm("remove", id);
  280. }
  281.  
  282. $("#" + widgetOptions.formId).yiiActiveForm("add", attribute);
  283. }
  284. };
  285.  
  286. var _fixFormValidaton = function(widgetOptions) {
  287. var widgetOptionsRoot = _getWidgetOptionsRoot(widgetOptions);
  288.  
  289. $(widgetOptionsRoot.widgetBody).find('input, textarea, select').each(function() {
  290. var id = $(this).attr('id');
  291. var name = $(this).attr('name');
  292.  
  293. if (id !== undefined && name !== undefined) {
  294. currentWidgetOptions = eval($(this).closest('div[data-dynamicform]').attr('data-dynamicform'));
  295. var matches = id.match(regexID);
  296.  
  297. if (matches && matches.length === 4) {
  298. matches[2] = matches[2].substring(1, matches[2].length - 1);
  299. var level = _getLevel($(this));
  300. var identifiers = _createIdentifiers(level -1);
  301. var baseID = matches[1] + '-' + identifiers.join('-') + '-' + matches[3];
  302. var attribute = $("#" + currentWidgetOptions.formId).yiiActiveForm("find", baseID);
  303. _fixFormValidatonInput(currentWidgetOptions, attribute, id, name);
  304. }
  305. }
  306. });
  307. };
  308.  
  309. var _restoreSpecialJs = function(widgetOptions) {
  310. var widgetOptionsRoot = _getWidgetOptionsRoot(widgetOptions);
  311.  
  312. // "kartik-v/yii2-widget-datepicker"
  313. var $hasDatepicker = $(widgetOptionsRoot.widgetItem).find('[data-krajee-datepicker]');
  314. if ($hasDatepicker.length > 0) {
  315. $hasDatepicker.each(function() {
  316. $(this).parent().removeData().datepicker('remove');
  317. $(this).parent().datepicker(eval($(this).attr('data-krajee-datepicker')));
  318. });
  319. }
  320.  
  321. // "kartik-v/yii2-widget-timepicker"
  322. var $hasTimepicker = $(widgetOptionsRoot.widgetItem).find('[data-krajee-timepicker]');
  323. if ($hasTimepicker.length > 0) {
  324. $hasTimepicker.each(function() {
  325. $(this).removeData().off();
  326. $(this).parent().find('.bootstrap-timepicker-widget').remove();
  327. $(this).unbind();
  328. $(this).timepicker(eval($(this).attr('data-krajee-timepicker')));
  329. });
  330. }
  331.  
  332. // "kartik-v/yii2-money"
  333. var $hasMaskmoney = $(widgetOptionsRoot.widgetItem).find('[data-krajee-maskMoney]');
  334. if ($hasMaskmoney.length > 0) {
  335. $hasMaskmoney.each(function() {
  336. $(this).parent().find('input').removeData().off();
  337. var id = '#' + $(this).attr('id');
  338. var displayID = id + '-disp';
  339. $(displayID).maskMoney('destroy');
  340. $(displayID).maskMoney(eval($(this).attr('data-krajee-maskMoney')));
  341. $(displayID).maskMoney('mask', parseFloat($(id).val()));
  342. $(displayID).on('change', function () {
  343. var numDecimal = $(displayID).maskMoney('unmasked')[0];
  344. $(id).val(numDecimal);
  345. $(id).trigger('change');
  346. });
  347. });
  348. }
  349.  
  350. // "kartik-v/yii2-widget-fileinput"
  351. var $hasFileinput = $(widgetOptionsRoot.widgetItem).find('[data-krajee-fileinput]');
  352. if ($hasFileinput.length > 0) {
  353. $hasFileinput.each(function() {
  354. $(this).fileinput(eval($(this).attr('data-krajee-fileinput')));
  355. });
  356. }
  357.  
  358. // "kartik-v/yii2-widget-touchspin"
  359. var $hasTouchSpin = $(widgetOptionsRoot.widgetItem).find('[data-krajee-TouchSpin]');
  360. if ($hasTouchSpin.length > 0) {
  361. $hasTouchSpin.each(function() {
  362. $(this).TouchSpin('destroy');
  363. $(this).TouchSpin(eval($(this).attr('data-krajee-TouchSpin')));
  364. });
  365. }
  366.  
  367. // "kartik-v/yii2-widget-colorinput"
  368. var $hasSpectrum = $(widgetOptionsRoot.widgetItem).find('[data-krajee-spectrum]');
  369. if ($hasSpectrum.length > 0) {
  370. $hasSpectrum.each(function() {
  371. var id = '#' + $(this).attr('id');
  372. var sourceID = id + '-source';
  373. $(sourceID).spectrum('destroy');
  374. $(sourceID).unbind();
  375. $(id).unbind();
  376. var configSpectrum = eval($(this).attr('data-krajee-spectrum'));
  377. configSpectrum.change = function (color) {
  378. jQuery(id).val(color.toString());
  379. };
  380. $(sourceID).attr('name', $(sourceID).attr('id'));
  381. $(sourceID).spectrum(configSpectrum);
  382. $(sourceID).spectrum('set', jQuery(id).val());
  383. $(id).on('change', function(){
  384. $(sourceID).spectrum('set', jQuery(id).val());
  385. });
  386. });
  387. }
  388.  
  389. // "kartik-v/yii2-widget-depdrop"
  390. var $hasDepdrop = $(widgetOptionsRoot.widgetItem).find('[data-krajee-depdrop]');
  391. if ($hasDepdrop.length > 0) {
  392. $hasDepdrop.each(function() {
  393. $(this).removeData().off();
  394. $(this).unbind();
  395. var configDepdrop = eval($(this).attr('data-krajee-depdrop'));
  396. var inputID = $(this).attr('id');
  397. var matchID = inputID.match(regex);
  398. if (matchID && matchID.length === 4) {
  399. for (index = 0; index < configDepdrop.depends.length; ++index) {
  400. var match = configDepdrop.depends[index].match(regex);
  401. if (match && match.length === 4) {
  402. configDepdrop.depends[index] = match[1] + matchID[2] + match[3];
  403. }
  404. }
  405. }
  406. $(this).depdrop(configDepdrop);
  407. });
  408. }
  409.  
  410. // "kartik-v/yii2-widget-select2"
  411. var $hasSelect2 = $(widgetOptionsRoot.widgetItem).find('[data-krajee-select2]');
  412. if ($hasSelect2.length > 0) {
  413. $hasSelect2.each(function() {
  414. var id = $(this).attr('id');
  415. var configSelect2 = eval($(this).attr('data-krajee-select2'));
  416. $(this).select2('destroy');
  417. $.when($('#' + id).select2(configSelect2)).done(initSelect2Loading(id));
  418. $('#' + id).on('select2-open', function() {
  419. initSelect2DropStyle(id)
  420. });
  421. if ($(this).attr('data-krajee-depdrop')) {
  422. $(this).on('depdrop.beforeChange', function(e,i,v) {
  423. var configDepdrop = eval($(this).attr('data-krajee-depdrop'));
  424. var loadingText = (configDepdrop.loadingText)? configDepdrop.loadingText : 'Loading ...';
  425. $('#' + id).select2('data', {text: loadingText});
  426. });
  427. $(this).on('depdrop.change', function(e,i,v,c) {
  428. $('#' + id).select2('val', $('#' + id).val());
  429. });
  430. }
  431. });
  432. }
  433. };
  434.  
  435. })(window.jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement