grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026/** * @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ ;(function($){ "use strict"; $.subformRepeatable = function(container, options){ this.$container = $(container); // check if already exist if(this.$container.data("subformRepeatable")){ return self; } // Add a reverse reference to the DOM object this.$container.data("subformRepeatable", self); // merge options this.options = $.extend({}, $.subformRepeatable.defaults, options); // template for the repeating group this.template = ''; // prepare a row template, and find available field names this.prepareTemplate(); // check rows container this.$containerRows = this.options.rowsContainer ? this.$container.find(this.options.rowsContainer) : this.$container; // To avoid scope issues, var self = this; // bind add button this.$container.on('click', this.options.btAdd, function (e) { e.preventDefault(); var after = $(this).parents(self.options.repeatableElement); if(!after.length){ after = null; } self.addRow(after); }); // bind remove button this.$container.on('click', this.options.btRemove, function (e) { e.preventDefault(); var $row = $(this).parents(self.options.repeatableElement); self.removeRow($row); }); // bind move button if(this.options.btMove){ this.$containerRows.sortable({ items: this.options.repeatableElement, handle: this.options.btMove, tolerance: 'pointer' }); } // tell all that we a ready this.$container.trigger('subform-ready'); }; // prepare a template that we will use repeating $.subformRepeatable.prototype.prepareTemplate = function(){ // create from template if (this.options.rowTemplateSelector) { // Find the template element and get its HTML content, this is our template. var $tmplElement = this.$container.find(this.options.rowTemplateSelector).last(); this.template = $.trim($tmplElement.html()) || ''; // This is IE fix for