| Server IP : 35.201.19.92 / Your IP : 216.73.216.191 Web Server : nginx System : Linux pod-200961 6.8.0-1055-gke #61-Ubuntu SMP Tue May 26 22:57:42 UTC 2026 x86_64 User : fpm200098 ( 200098) PHP Version : 8.2.34 Disable Function : apache_child_terminate,apache_get_modules,apache_get_version,apache_getenv,apache_note,apache_setenv,disk_free_space,disk_total_space,diskfreespace,dl,exec,fastcgi_finish_request,link,opcache_compile_file,opcache_get_configuration,opcache_invalidate,opcache_is_script_cached,opcache_reset,passthru,pclose,pcntl_exec,popen,posix_getpid,posix_getppid,posix_getpwuid,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_uname,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,realpath_cache_get,shell_exec,show_source,symlink,system MySQL : OFF | cURL : ON | WGET : OFF | Perl : ON | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /nas/content/live/questfamilyday/wp-content/plugins/gravityperks/scripts/ |
Upload File : |
/**
* jQuery Repeater
*
* Easily create a section of repeatable items.
*
*/
jQuery.fn.repeater = function(options) {
var defaults = {
template: '',
limit: 5,
items: [{}],
saveEvents: 'blur change',
saveElements: 'input, select',
addImageSrc: '',
removeImageSrc: '',
callbacks: {
save: function() { },
beforeAdd: function() { },
add: function() { },
beforeAddNew: function() { },
addNew: function() { },
beforeRemove: function() { },
remove: function() { },
repeaterButtons: function() { return false; }
}
}
this.options = jQuery.extend( true, {}, defaults, options );
this.elem = jQuery( this );
this.items = this.options.items;
this.callbacks = this.options.callbacks;
this._template = this.options.template ? this.options.template : this.elem.next( '#' + this.elem.prop( 'id' ) + '-template' ).html();
// add "repeater" namespace to all saveEvents
var saveEvents = this.options.saveEvents.split( ' ' );
var newSaveEvents = [];
for (i in saveEvents) {
newSaveEvents.push( saveEvents[i] + '.repeater' );
}
this.options.saveEvents = newSaveEvents.join( ' ' );
this.init = function() {
// if no template provided or in "storage", use current HTML
if ( ! this._template) {
this._template = this.elem.html();
}
// move template html into "storage"
this.elem.after( '<div id="' + this.elem.prop( 'id' ) + '-template" style="display:none">' + this._template + '</div>' );
this.elem.addClass( 'repeater' );
this.elem.empty();
for (i in this.items) {
this.addItem( this.items[i], i );
}
var repeater = this;
jQuery( this.elem ).off( 'click.repeater', 'a.add-item:not(".inactive")' );
jQuery( this.elem ).on('click.repeater', 'a.add-item:not(".inactive")', function(event){
repeater.addNewItem( this );
});
jQuery( this.elem ).off( 'click.repeater', 'a.remove-item' );
jQuery( this.elem ).on('click.repeater', 'a.remove-item', function(event){
repeater.removeItem( this )
});
jQuery( this.elem ).off( this.options.saveEvents, this.options.saveElements );
jQuery( this.elem ).on(this.options.saveEvents, this.options.saveElements, function(){
repeater.save();
});
return this;
}
this.addItem = function(item, index) {
var itemHTML = this._template;
for (var property in item) {
itemHTML = itemHTML.replace( /{i}/g, index );
var repeaterButtonHTML = this.callbacks.repeaterButtons( this, index ) ? this.callbacks.repeaterButtons( this, index ) : this.addRepeaterButtons( index );
itemHTML = itemHTML.replace( "{buttons}", repeaterButtonHTML );
var re = new RegExp( '{' + property + '}', 'g' );
itemHTML = itemHTML.replace( re, item[property] );
}
var itemObj = jQuery( itemHTML ).addClass( 'item-' + index );
this.callbacks.beforeAdd( this, itemObj, item );
this.append( itemObj );
this.callbacks.add( this, itemObj, item );
}
this.addRepeaterButtons = function(index) {
var cssClass = this.items.length >= options.limit && options.limit !== 0 ? 'inactive' : '';
var str = '<div class="repeater-buttons">';
str += '<a class="add-item ' + cssClass + '" data-index="' + index + '">';
str += '<img src="' + options.addImageSrc + '/images/add.png" alt="Add" /></a>';
if (this.items.length > 1) {
str += '<a class="remove-item" data-index="' + index + '"><img src="' + options.removeImageSrc + '/images/remove.png" alt="Remove" /></a>';
}
return str;
}
this.addNewItem = function(elem) {
var index = jQuery( elem ).attr( 'data-index' );
this.callbacks.beforeAddNew( this, index );
this.items.splice( index + 1, 0, this.getBaseObject() );
this.callbacks.addNew( this, index );
this.refresh();
}
this.removeItem = function(elem) {
var index = jQuery( elem ).attr( 'data-index' );
this.callbacks.beforeRemove( this, index );
// using delete (over splice) to maintain the correct indexes for
// the items array when saving the data from the UI
delete this.items[index];
this.callbacks.remove( this, index );
this.save();
this.refresh();
}
this.refresh = function() {
this.elem.empty();
for (i in this.items) {
this.addItem( this.items[i], i );
}
}
this.save = function() {
var keys = this.getDataKeys();
var data = new Array();
for (i = 0; i < this.items.length; i++) {
if (typeof this.items[i] == 'undefined') {
continue;
}
var item = {};
for (j in keys) {
var key = keys[j];
var id = '#' + key + '_' + i;
item[key] = jQuery( this.elem ).find( id ).val();
}
data.push( item );
}
// save data to items
this.items = data;
// save data externally via callback
this.callbacks.save( this, data );
}
/**
* Loops through the current items array and retrieves the object properties of the
* first valid item object. Originally this would simply pull the object keys from
* the first index of the items array; however, when the first item has been
* 'deleted' (see the save() method), it will be undefined.
*/
this.getDataKeys = function() {
var keys = new Array();
for (var i in this.items) {
if (typeof this.items[i] == 'undefined') {
continue;
}
for (var key in this.items[i]) {
keys[keys.length] = key;
}
break;
}
return keys;
}
this.getBaseObject = function() {
var item = {};
var keys = this.getDataKeys();
for (var i in keys) {
item[keys[i]] = '';
}
return item;
}
return this.init( true );
};