(function ($) { $.fn.repeatable = function (userSettings) { /** * Default settings * @type {Object} */ var defaults = { addTrigger: ".add", deleteTrigger: ".delete", max: null, startWith: 0, template: null, itemContainer: ".field-group", onAdd: function () {}, onDelete: function () {} }; /** * Iterator used to make each added * repeatable element unique * @type {Number} */ var i = 0; /** * DOM element into which repeatable * items will be added * @type {jQuery object} */ var target = $(this); /** * Blend passed user settings with defauly settings * @type {array} */ var settings = $.extend({}, defaults, userSettings); /** * Total templated items found on the page * at load. These may be created by server-side * scripts. * @return null */ var total = function () { return $(target).find(settings.itemContainer).length; }(); /** * Add an element to the target * and call the callback function * @return null */ var addOne = function () { createOne(); settings.onAdd.call(this); }; /** * Delete the parent element * and call the callback function * @return null */ var deleteOne = function () { $(this).parents(settings.itemContainer).first().remove(); total--; maintainAddBtn(); settings.onDelete.call(this); }; /** * Add an element to the target * @return null */ var createOne = function() { getUniqueTemplate().appendTo(target); total++; maintainAddBtn(); }; /** * Alter the given template to make * each form field name unique * @return {jQuery object} */ var getUniqueTemplate = function () { var template = $(settings.template).html(); template = template.replace(/{\?}/g, "new" + i++); // {?} => iterated placeholder template = template.replace(/\{[^\?\}]*\}/g, ""); // {valuePlaceholder} => "" return $(template); }; /** * Determines if the add trigger * needs to be disabled * @return null */ var maintainAddBtn = function () { if (!settings.max) { return; } if (total === settings.max) { $(settings.addTrigger).attr("disabled", "disabled"); } else if (total < settings.max) { $(settings.addTrigger).removeAttr("disabled"); } }; /** * Setup the repeater * @return null */ (function () { $(settings.addTrigger).on("click", addOne); $("form").on("click", ".delete", deleteOne); if (!total) { var toCreate = settings.startWith - total; for (var j = 0; j < toCreate; j++) { createOne(); } } })(); }; })(jQuery);