You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1016 lines
27 KiB
1016 lines
27 KiB
// jquery.repeater version 1.2.1 |
|
// https://github.com/DubFriend/jquery.repeater |
|
// (MIT) 09-10-2016 |
|
// Brian Detering <BDeterin@gmail.com> (http://www.briandetering.net/) |
|
(function ($) { |
|
'use strict'; |
|
|
|
var identity = function (x) { |
|
return x; |
|
}; |
|
|
|
var isArray = function (value) { |
|
return $.isArray(value); |
|
}; |
|
|
|
var isObject = function (value) { |
|
return !isArray(value) && (value instanceof Object); |
|
}; |
|
|
|
var isNumber = function (value) { |
|
return value instanceof Number; |
|
}; |
|
|
|
var isFunction = function (value) { |
|
return value instanceof Function; |
|
}; |
|
|
|
var indexOf = function (object, value) { |
|
return $.inArray(value, object); |
|
}; |
|
|
|
var inArray = function (array, value) { |
|
return indexOf(array, value) !== -1; |
|
}; |
|
|
|
var foreach = function (collection, callback) { |
|
for(var i in collection) { |
|
if(collection.hasOwnProperty(i)) { |
|
callback(collection[i], i, collection); |
|
} |
|
} |
|
}; |
|
|
|
|
|
var last = function (array) { |
|
return array[array.length - 1]; |
|
}; |
|
|
|
var argumentsToArray = function (args) { |
|
return Array.prototype.slice.call(args); |
|
}; |
|
|
|
var extend = function () { |
|
var extended = {}; |
|
foreach(argumentsToArray(arguments), function (o) { |
|
foreach(o, function (val, key) { |
|
extended[key] = val; |
|
}); |
|
}); |
|
return extended; |
|
}; |
|
|
|
var mapToArray = function (collection, callback) { |
|
var mapped = []; |
|
foreach(collection, function (value, key, coll) { |
|
mapped.push(callback(value, key, coll)); |
|
}); |
|
return mapped; |
|
}; |
|
|
|
var mapToObject = function (collection, callback, keyCallback) { |
|
var mapped = {}; |
|
foreach(collection, function (value, key, coll) { |
|
key = keyCallback ? keyCallback(key, value) : key; |
|
mapped[key] = callback(value, key, coll); |
|
}); |
|
return mapped; |
|
}; |
|
|
|
var map = function (collection, callback, keyCallback) { |
|
return isArray(collection) ? |
|
mapToArray(collection, callback) : |
|
mapToObject(collection, callback, keyCallback); |
|
}; |
|
|
|
var pluck = function (arrayOfObjects, key) { |
|
return map(arrayOfObjects, function (val) { |
|
return val[key]; |
|
}); |
|
}; |
|
|
|
var filter = function (collection, callback) { |
|
var filtered; |
|
|
|
if(isArray(collection)) { |
|
filtered = []; |
|
foreach(collection, function (val, key, coll) { |
|
if(callback(val, key, coll)) { |
|
filtered.push(val); |
|
} |
|
}); |
|
} |
|
else { |
|
filtered = {}; |
|
foreach(collection, function (val, key, coll) { |
|
if(callback(val, key, coll)) { |
|
filtered[key] = val; |
|
} |
|
}); |
|
} |
|
|
|
return filtered; |
|
}; |
|
|
|
var call = function (collection, functionName, args) { |
|
return map(collection, function (object, name) { |
|
return object[functionName].apply(object, args || []); |
|
}); |
|
}; |
|
|
|
//execute callback immediately and at most one time on the minimumInterval, |
|
//ignore block attempts |
|
var throttle = function (minimumInterval, callback) { |
|
var timeout = null; |
|
return function () { |
|
var that = this, args = arguments; |
|
if(timeout === null) { |
|
timeout = setTimeout(function () { |
|
timeout = null; |
|
}, minimumInterval); |
|
callback.apply(that, args); |
|
} |
|
}; |
|
}; |
|
|
|
|
|
var mixinPubSub = function (object) { |
|
object = object || {}; |
|
var topics = {}; |
|
|
|
object.publish = function (topic, data) { |
|
foreach(topics[topic], function (callback) { |
|
callback(data); |
|
}); |
|
}; |
|
|
|
object.subscribe = function (topic, callback) { |
|
topics[topic] = topics[topic] || []; |
|
topics[topic].push(callback); |
|
}; |
|
|
|
object.unsubscribe = function (callback) { |
|
foreach(topics, function (subscribers) { |
|
var index = indexOf(subscribers, callback); |
|
if(index !== -1) { |
|
subscribers.splice(index, 1); |
|
} |
|
}); |
|
}; |
|
|
|
return object; |
|
}; |
|
|
|
// jquery.input version 0.0.0 |
|
// https://github.com/DubFriend/jquery.input |
|
// (MIT) 09-04-2014 |
|
// Brian Detering <BDeterin@gmail.com> (http://www.briandetering.net/) |
|
(function ($) { |
|
'use strict'; |
|
|
|
var createBaseInput = function (fig, my) { |
|
var self = mixinPubSub(), |
|
$self = fig.$; |
|
|
|
self.getType = function () { |
|
throw 'implement me (return type. "text", "radio", etc.)'; |
|
}; |
|
|
|
self.$ = function (selector) { |
|
return selector ? $self.find(selector) : $self; |
|
}; |
|
|
|
self.disable = function () { |
|
self.$().prop('disabled', true); |
|
self.publish('isEnabled', false); |
|
}; |
|
|
|
self.enable = function () { |
|
self.$().prop('disabled', false); |
|
self.publish('isEnabled', true); |
|
}; |
|
|
|
my.equalTo = function (a, b) { |
|
return a === b; |
|
}; |
|
|
|
my.publishChange = (function () { |
|
var oldValue; |
|
return function (e, domElement) { |
|
var newValue = self.get(); |
|
if(!my.equalTo(newValue, oldValue)) { |
|
self.publish('change', { e: e, domElement: domElement }); |
|
} |
|
oldValue = newValue; |
|
}; |
|
}()); |
|
|
|
return self; |
|
}; |
|
|
|
|
|
var createInput = function (fig, my) { |
|
var self = createBaseInput(fig, my); |
|
|
|
self.get = function () { |
|
return self.$().val(); |
|
}; |
|
|
|
self.set = function (newValue) { |
|
self.$().val(newValue); |
|
}; |
|
|
|
self.clear = function () { |
|
self.set(''); |
|
}; |
|
|
|
my.buildSetter = function (callback) { |
|
return function (newValue) { |
|
callback.call(self, newValue); |
|
}; |
|
}; |
|
|
|
return self; |
|
}; |
|
|
|
var inputEqualToArray = function (a, b) { |
|
a = isArray(a) ? a : [a]; |
|
b = isArray(b) ? b : [b]; |
|
|
|
var isEqual = true; |
|
if(a.length !== b.length) { |
|
isEqual = false; |
|
} |
|
else { |
|
foreach(a, function (value) { |
|
if(!inArray(b, value)) { |
|
isEqual = false; |
|
} |
|
}); |
|
} |
|
|
|
return isEqual; |
|
}; |
|
|
|
var createInputButton = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'button'; |
|
}; |
|
|
|
self.$().on('change', function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputCheckbox = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'checkbox'; |
|
}; |
|
|
|
self.get = function () { |
|
var values = []; |
|
self.$().filter(':checked').each(function () { |
|
values.push($(this).val()); |
|
}); |
|
return values; |
|
}; |
|
|
|
self.set = function (newValues) { |
|
newValues = isArray(newValues) ? newValues : [newValues]; |
|
|
|
self.$().each(function () { |
|
$(this).prop('checked', false); |
|
}); |
|
|
|
foreach(newValues, function (value) { |
|
self.$().filter('[value="' + value + '"]') |
|
.prop('checked', true); |
|
}); |
|
}; |
|
|
|
my.equalTo = inputEqualToArray; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputEmail = function (fig) { |
|
var my = {}, |
|
self = createInputText(fig, my); |
|
|
|
self.getType = function () { |
|
return 'email'; |
|
}; |
|
|
|
return self; |
|
}; |
|
|
|
var createInputFile = function (fig) { |
|
var my = {}, |
|
self = createBaseInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'file'; |
|
}; |
|
|
|
self.get = function () { |
|
return last(self.$().val().split('\\')); |
|
}; |
|
|
|
self.clear = function () { |
|
// http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery |
|
this.$().each(function () { |
|
$(this).wrap('<form>').closest('form').get(0).reset(); |
|
$(this).unwrap(); |
|
}); |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
// self.publish('change', self); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputHidden = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'hidden'; |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
var createInputMultipleFile = function (fig) { |
|
var my = {}, |
|
self = createBaseInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'file[multiple]'; |
|
}; |
|
|
|
self.get = function () { |
|
// http://stackoverflow.com/questions/14035530/how-to-get-value-of-html-5-multiple-file-upload-variable-using-jquery |
|
var fileListObject = self.$().get(0).files || [], |
|
names = [], i; |
|
|
|
for(i = 0; i < (fileListObject.length || 0); i += 1) { |
|
names.push(fileListObject[i].name); |
|
} |
|
|
|
return names; |
|
}; |
|
|
|
self.clear = function () { |
|
// http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery |
|
this.$().each(function () { |
|
$(this).wrap('<form>').closest('form').get(0).reset(); |
|
$(this).unwrap(); |
|
}); |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputMultipleSelect = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'select[multiple]'; |
|
}; |
|
|
|
self.get = function () { |
|
return self.$().val() || []; |
|
}; |
|
|
|
self.set = function (newValues) { |
|
self.$().val( |
|
newValues === '' ? [] : isArray(newValues) ? newValues : [newValues] |
|
); |
|
}; |
|
|
|
my.equalTo = inputEqualToArray; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputPassword = function (fig) { |
|
var my = {}, |
|
self = createInputText(fig, my); |
|
|
|
self.getType = function () { |
|
return 'password'; |
|
}; |
|
|
|
return self; |
|
}; |
|
|
|
var createInputRadio = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'radio'; |
|
}; |
|
|
|
self.get = function () { |
|
return self.$().filter(':checked').val() || null; |
|
}; |
|
|
|
self.set = function (newValue) { |
|
if(!newValue) { |
|
self.$().each(function () { |
|
$(this).prop('checked', false); |
|
}); |
|
} |
|
else { |
|
self.$().filter('[value="' + newValue + '"]').prop('checked', true); |
|
} |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputRange = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'range'; |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputSelect = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'select'; |
|
}; |
|
|
|
self.$().change(function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputText = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'text'; |
|
}; |
|
|
|
self.$().on('change keyup keydown', function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputTextarea = function (fig) { |
|
var my = {}, |
|
self = createInput(fig, my); |
|
|
|
self.getType = function () { |
|
return 'textarea'; |
|
}; |
|
|
|
self.$().on('change keyup keydown', function (e) { |
|
my.publishChange(e, this); |
|
}); |
|
|
|
return self; |
|
}; |
|
|
|
var createInputURL = function (fig) { |
|
var my = {}, |
|
self = createInputText(fig, my); |
|
|
|
self.getType = function () { |
|
return 'url'; |
|
}; |
|
|
|
return self; |
|
}; |
|
|
|
var buildFormInputs = function (fig) { |
|
var inputs = {}, |
|
$self = fig.$; |
|
|
|
var constructor = fig.constructorOverride || { |
|
button: createInputButton, |
|
text: createInputText, |
|
url: createInputURL, |
|
email: createInputEmail, |
|
password: createInputPassword, |
|
range: createInputRange, |
|
textarea: createInputTextarea, |
|
select: createInputSelect, |
|
'select[multiple]': createInputMultipleSelect, |
|
radio: createInputRadio, |
|
checkbox: createInputCheckbox, |
|
file: createInputFile, |
|
'file[multiple]': createInputMultipleFile, |
|
hidden: createInputHidden |
|
}; |
|
|
|
var addInputsBasic = function (type, selector) { |
|
var $input = isObject(selector) ? selector : $self.find(selector); |
|
|
|
$input.each(function () { |
|
var name = $(this).attr('name'); |
|
inputs[name] = constructor[type]({ |
|
$: $(this) |
|
}); |
|
}); |
|
}; |
|
|
|
var addInputsGroup = function (type, selector) { |
|
var names = [], |
|
$input = isObject(selector) ? selector : $self.find(selector); |
|
|
|
if(isObject(selector)) { |
|
inputs[$input.attr('name')] = constructor[type]({ |
|
$: $input |
|
}); |
|
} |
|
else { |
|
// group by name attribute |
|
$input.each(function () { |
|
if(indexOf(names, $(this).attr('name')) === -1) { |
|
names.push($(this).attr('name')); |
|
} |
|
}); |
|
|
|
foreach(names, function (name) { |
|
inputs[name] = constructor[type]({ |
|
$: $self.find('input[name="' + name + '"]') |
|
}); |
|
}); |
|
} |
|
}; |
|
|
|
|
|
if($self.is('input, select, textarea')) { |
|
if($self.is('input[type="button"], button, input[type="submit"]')) { |
|
addInputsBasic('button', $self); |
|
} |
|
else if($self.is('textarea')) { |
|
addInputsBasic('textarea', $self); |
|
} |
|
else if( |
|
$self.is('input[type="text"]') || |
|
$self.is('input') && !$self.attr('type') |
|
) { |
|
addInputsBasic('text', $self); |
|
} |
|
else if($self.is('input[type="password"]')) { |
|
addInputsBasic('password', $self); |
|
} |
|
else if($self.is('input[type="email"]')) { |
|
addInputsBasic('email', $self); |
|
} |
|
else if($self.is('input[type="url"]')) { |
|
addInputsBasic('url', $self); |
|
} |
|
else if($self.is('input[type="range"]')) { |
|
addInputsBasic('range', $self); |
|
} |
|
else if($self.is('select')) { |
|
if($self.is('[multiple]')) { |
|
addInputsBasic('select[multiple]', $self); |
|
} |
|
else { |
|
addInputsBasic('select', $self); |
|
} |
|
} |
|
else if($self.is('input[type="file"]')) { |
|
if($self.is('[multiple]')) { |
|
addInputsBasic('file[multiple]', $self); |
|
} |
|
else { |
|
addInputsBasic('file', $self); |
|
} |
|
} |
|
else if($self.is('input[type="hidden"]')) { |
|
addInputsBasic('hidden', $self); |
|
} |
|
else if($self.is('input[type="radio"]')) { |
|
addInputsGroup('radio', $self); |
|
} |
|
else if($self.is('input[type="checkbox"]')) { |
|
addInputsGroup('checkbox', $self); |
|
} |
|
else { |
|
//in all other cases default to a "text" input interface. |
|
addInputsBasic('text', $self); |
|
} |
|
} |
|
else { |
|
addInputsBasic('button', 'input[type="button"], button, input[type="submit"]'); |
|
addInputsBasic('text', 'input[type="text"]'); |
|
addInputsBasic('password', 'input[type="password"]'); |
|
addInputsBasic('email', 'input[type="email"]'); |
|
addInputsBasic('url', 'input[type="url"]'); |
|
addInputsBasic('range', 'input[type="range"]'); |
|
addInputsBasic('textarea', 'textarea'); |
|
addInputsBasic('select', 'select:not([multiple])'); |
|
addInputsBasic('select[multiple]', 'select[multiple]'); |
|
addInputsBasic('file', 'input[type="file"]:not([multiple])'); |
|
addInputsBasic('file[multiple]', 'input[type="file"][multiple]'); |
|
addInputsBasic('hidden', 'input[type="hidden"]'); |
|
addInputsGroup('radio', 'input[type="radio"]'); |
|
addInputsGroup('checkbox', 'input[type="checkbox"]'); |
|
} |
|
|
|
return inputs; |
|
}; |
|
|
|
$.fn.inputVal = function (newValue) { |
|
var $self = $(this); |
|
|
|
var inputs = buildFormInputs({ $: $self }); |
|
|
|
if($self.is('input, textarea, select')) { |
|
if(typeof newValue === 'undefined') { |
|
return inputs[$self.attr('name')].get(); |
|
} |
|
else { |
|
inputs[$self.attr('name')].set(newValue); |
|
return $self; |
|
} |
|
} |
|
else { |
|
if(typeof newValue === 'undefined') { |
|
return call(inputs, 'get'); |
|
} |
|
else { |
|
foreach(newValue, function (value, inputName) { |
|
inputs[inputName].set(value); |
|
}); |
|
return $self; |
|
} |
|
} |
|
}; |
|
|
|
$.fn.inputOnChange = function (callback) { |
|
var $self = $(this); |
|
var inputs = buildFormInputs({ $: $self }); |
|
foreach(inputs, function (input) { |
|
input.subscribe('change', function (data) { |
|
callback.call(data.domElement, data.e); |
|
}); |
|
}); |
|
return $self; |
|
}; |
|
|
|
$.fn.inputDisable = function () { |
|
var $self = $(this); |
|
call(buildFormInputs({ $: $self }), 'disable'); |
|
return $self; |
|
}; |
|
|
|
$.fn.inputEnable = function () { |
|
var $self = $(this); |
|
call(buildFormInputs({ $: $self }), 'enable'); |
|
return $self; |
|
}; |
|
|
|
$.fn.inputClear = function () { |
|
var $self = $(this); |
|
call(buildFormInputs({ $: $self }), 'clear'); |
|
return $self; |
|
}; |
|
|
|
}(jQuery)); |
|
|
|
$.fn.repeaterVal = function () { |
|
var parse = function (raw) { |
|
var parsed = []; |
|
|
|
foreach(raw, function (val, key) { |
|
var parsedKey = []; |
|
if(key !== "undefined") { |
|
parsedKey.push(key.match(/^[^\[]*/)[0]); |
|
parsedKey = parsedKey.concat(map( |
|
key.match(/\[[^\]]*\]/g), |
|
function (bracketed) { |
|
return bracketed.replace(/[\[\]]/g, ''); |
|
} |
|
)); |
|
|
|
parsed.push({ |
|
val: val, |
|
key: parsedKey |
|
}); |
|
} |
|
}); |
|
|
|
return parsed; |
|
}; |
|
|
|
var build = function (parsed) { |
|
if( |
|
parsed.length === 1 && |
|
(parsed[0].key.length === 0 || parsed[0].key.length === 1 && !parsed[0].key[0]) |
|
) { |
|
return parsed[0].val; |
|
} |
|
|
|
foreach(parsed, function (p) { |
|
p.head = p.key.shift(); |
|
}); |
|
|
|
var grouped = (function () { |
|
var grouped = {}; |
|
|
|
foreach(parsed, function (p) { |
|
if(!grouped[p.head]) { |
|
grouped[p.head] = []; |
|
} |
|
grouped[p.head].push(p); |
|
}); |
|
|
|
return grouped; |
|
}()); |
|
|
|
var built; |
|
|
|
if(/^[0-9]+$/.test(parsed[0].head)) { |
|
built = []; |
|
foreach(grouped, function (group) { |
|
built.push(build(group)); |
|
}); |
|
} |
|
else { |
|
built = {}; |
|
foreach(grouped, function (group, key) { |
|
built[key] = build(group); |
|
}); |
|
} |
|
|
|
return built; |
|
}; |
|
|
|
return build(parse($(this).inputVal())); |
|
}; |
|
|
|
$.fn.repeater = function (fig) { |
|
fig = fig || {}; |
|
|
|
var setList; |
|
|
|
$(this).each(function () { |
|
|
|
var $self = $(this); |
|
|
|
var show = fig.show || function () { |
|
$(this).show(); |
|
}; |
|
|
|
var hide = fig.hide || function (removeElement) { |
|
removeElement(); |
|
}; |
|
|
|
var $list = $self.find('[data-repeater-list]').first(); |
|
|
|
var $filterNested = function ($items, repeaters) { |
|
return $items.filter(function () { |
|
return repeaters ? |
|
$(this).closest( |
|
pluck(repeaters, 'selector').join(',') |
|
).length === 0 : true; |
|
}); |
|
}; |
|
|
|
var $items = function () { |
|
return $filterNested($list.find('[data-repeater-item]'), fig.repeaters); |
|
}; |
|
|
|
var $itemTemplate = $list.find('[data-repeater-item]') |
|
.first().clone().hide(); |
|
|
|
var $firstDeleteButton = $filterNested( |
|
$filterNested($(this).find('[data-repeater-item]'), fig.repeaters) |
|
.first().find('[data-repeater-delete]'), |
|
fig.repeaters |
|
); |
|
|
|
if(fig.isFirstItemUndeletable && $firstDeleteButton) { |
|
$firstDeleteButton.remove(); |
|
} |
|
|
|
var getGroupName = function () { |
|
var groupName = $list.data('repeater-list'); |
|
return fig.$parent ? |
|
fig.$parent.data('item-name') + '[' + groupName + ']' : |
|
groupName; |
|
}; |
|
|
|
var initNested = function ($listItems) { |
|
if(fig.repeaters) { |
|
$listItems.each(function () { |
|
var $item = $(this); |
|
foreach(fig.repeaters, function (nestedFig) { |
|
$item.find(nestedFig.selector).repeater(extend( |
|
nestedFig, { $parent: $item } |
|
)); |
|
}); |
|
}); |
|
} |
|
}; |
|
|
|
var $foreachRepeaterInItem = function (repeaters, $item, cb) { |
|
if(repeaters) { |
|
foreach(repeaters, function (nestedFig) { |
|
cb.call($item.find(nestedFig.selector)[0], nestedFig); |
|
}); |
|
} |
|
}; |
|
|
|
var setIndexes = function ($items, groupName, repeaters) { |
|
$items.each(function (index) { |
|
var $item = $(this); |
|
$item.data('item-name', groupName + '[' + index + ']'); |
|
$filterNested($item.find('[name]'), repeaters) |
|
.each(function () { |
|
var $input = $(this); |
|
// match non empty brackets (ex: "[foo]") |
|
var matches = $input.attr('name').match(/\[[^\]]+\]/g); |
|
|
|
var name = matches ? |
|
// strip "[" and "]" characters |
|
last(matches).replace(/\[|\]/g, '') : |
|
$input.attr('name'); |
|
|
|
|
|
var newName = groupName + '[' + index + '][' + name + ']' + |
|
($input.is(':checkbox') || $input.attr('multiple') ? '[]' : ''); |
|
|
|
$input.attr('name', newName); |
|
|
|
$foreachRepeaterInItem(repeaters, $item, function (nestedFig) { |
|
var $repeater = $(this); |
|
setIndexes( |
|
$filterNested($repeater.find('[data-repeater-item]'), nestedFig.repeaters || []), |
|
groupName + '[' + index + ']' + |
|
'[' + $repeater.find('[data-repeater-list]').first().data('repeater-list') + ']', |
|
nestedFig.repeaters |
|
); |
|
}); |
|
}); |
|
}); |
|
|
|
$list.find('input[name][checked]') |
|
.removeAttr('checked') |
|
.prop('checked', true); |
|
}; |
|
|
|
setIndexes($items(), getGroupName(), fig.repeaters); |
|
initNested($items()); |
|
if(fig.initEmpty) { |
|
$items().remove(); |
|
} |
|
|
|
if(fig.ready) { |
|
fig.ready(function () { |
|
setIndexes($items(), getGroupName(), fig.repeaters); |
|
}); |
|
} |
|
|
|
var appendItem = (function () { |
|
var setItemsValues = function ($item, data, repeaters) { |
|
if(data || fig.defaultValues) { |
|
var inputNames = {}; |
|
$filterNested($item.find('[name]'), repeaters).each(function () { |
|
var key = $(this).attr('name').match(/\[([^\]]*)(\]|\]\[\])$/)[1]; |
|
inputNames[key] = $(this).attr('name'); |
|
}); |
|
|
|
$item.inputVal(map( |
|
filter(data || fig.defaultValues, function (val, name) { |
|
return inputNames[name]; |
|
}), |
|
identity, |
|
function (name) { |
|
return inputNames[name]; |
|
} |
|
)); |
|
} |
|
|
|
|
|
$foreachRepeaterInItem(repeaters, $item, function (nestedFig) { |
|
var $repeater = $(this); |
|
$filterNested( |
|
$repeater.find('[data-repeater-item]'), |
|
nestedFig.repeaters |
|
) |
|
.each(function () { |
|
var fieldName = $repeater.find('[data-repeater-list]').data('repeater-list'); |
|
if(data && data[fieldName]) { |
|
var $template = $(this).clone(); |
|
$repeater.find('[data-repeater-item]').remove(); |
|
foreach(data[fieldName], function (data) { |
|
var $item = $template.clone(); |
|
setItemsValues( |
|
$item, |
|
data, |
|
nestedFig.repeaters || [] |
|
); |
|
$repeater.find('[data-repeater-list]').append($item); |
|
}); |
|
} |
|
else { |
|
setItemsValues( |
|
$(this), |
|
nestedFig.defaultValues, |
|
nestedFig.repeaters || [] |
|
); |
|
} |
|
}); |
|
}); |
|
|
|
}; |
|
|
|
return function ($item, data) { |
|
$list.append($item); |
|
setIndexes($items(), getGroupName(), fig.repeaters); |
|
$item.find('[name]').each(function () { |
|
$(this).inputClear(); |
|
}); |
|
setItemsValues($item, data || fig.defaultValues, fig.repeaters); |
|
}; |
|
}()); |
|
|
|
var addItem = function (data) { |
|
var $item = $itemTemplate.clone(); |
|
appendItem($item, data); |
|
if(fig.repeaters) { |
|
initNested($item); |
|
} |
|
show.call($item.get(0)); |
|
}; |
|
|
|
setList = function (rows) { |
|
$items().remove(); |
|
foreach(rows, addItem); |
|
}; |
|
|
|
$filterNested($self.find('[data-repeater-create]'), fig.repeaters).click(function () { |
|
addItem(); |
|
}); |
|
|
|
$list.on('click', '[data-repeater-delete]', function () { |
|
var self = $(this).closest('[data-repeater-item]').get(0); |
|
hide.call(self, function () { |
|
$(self).remove(); |
|
setIndexes($items(), getGroupName(), fig.repeaters); |
|
}); |
|
}); |
|
}); |
|
|
|
this.setList = setList; |
|
|
|
return this; |
|
}; |
|
|
|
}(jQuery)); |