| Current Path : /home/lejardintz/www/modules/mod_as_contact_form/js/ |
| Current File : /home/lejardintz/www/modules/mod_as_contact_form/js/repeatablefix.js |
;(function($){
"use strict";
$.JRepeatable = function(input, options){
// To avoid scope issues,
var self = this;
//direct call
if(!self || self === window){
return new $.JRepeatable(input, options);
}
self.$input = $(input);
// check if alredy exist
if(self.$input.data("JRepeatable")){
return self;
}
// Add a reverse reference to the DOM object
self.$input.data("JRepeatable", self);
// method initialize
self.init = function(){
// merge options
self.options = $.extend({}, $.JRepeatable.defaults, options);
if($('body').find('>'+self.options.container).length){
self.$container_old = $(self.options.container).eq(0);
$('body').find('>'+self.options.container).find('.modal').html(self.$container_old.find('.modal').html())
self.$container_old.remove();
self.$container = $(self.options.container);
}
else{
self.$container = $(self.options.container);
// Move out form the Form container
// for prevent sending to server
$('body').append(self.$container);
// prepare modal window
self.prepareModal();
// bind open the modal
$(document).on('click', self.options.btModalOpen, function (e) {
e.preventDefault();
self.$modalWindow.modal('show');
});
// bind close the modal
self.$modalWindow.on('click', self.options.btModalClose, function (e) {
e.preventDefault();
self.$modalWindow.modal('hide');
// rollback
self.buildRows();
});
// bind save the modaldata
self.$modalWindow.on('click', self.options.btModalSaveData, function (e) {
e.preventDefault();
self.$modalWindow.modal('hide');
self.refreshValue();
});
// bind add button
self.$container.on('click', self.options.btAdd, function (e) {
e.preventDefault();
var after = $(this).parents(self.options.repeatableElement);
if(!after.length || after.closest('thead').length){
after = null;
}
self.addRow(after);
});
// bind remove button
self.$container.on('click', self.options.btRemove, function (e) {
e.preventDefault();
var row = $(this).parents(self.options.repeatableElement);
self.removeRow(row);
});
}
// container where the rows is live
self.$rowsContainer = self.$container.find(self.options.repeatableElement).parent();
// container for storing info about inputs
self.inputs = [];
self.values = {};
// prepare a row template, and find available field names
self.prepareTemplate();
// check the values and keep it as object
var val = self.$input.val();
if(val){
// value can be not valid JSON
try {
self.values = JSON.parse(val);
} catch (e) {
if(e instanceof SyntaxError){
// guess there a single quote problem
try {
val = val.replace(/'/g, '"').replace(/\\"/g, "\'");// ho ho ho
self.values = JSON.parse(val);
} catch (e) {
// nop
if(window.console){
console.log(e);
}
}
} else if(window.console){
console.log(e);
}
}
}
// so init the form depend from values that we have
self.buildRows();
// tell all that we a ready
self.$input.trigger('weready');
};
// prepare a template that we will use for repeating
self.prepareTemplate = function(){
//find available
var $rows = self.$container.find(self.options.repeatableElement);
var $row = $($rows.get(0));
// clear scripts that can be attached to the fields
try {
self.clearScripts($row);
} catch (e) {
if(window.console){
console.log(e);
}
}
var inputs = $row.find('*[name]');
//keep the name and type for each
for(var i = 0, l = inputs.length; i < l; i++){
var name = $(inputs[i]).attr('name');
// check if alredy exist, for radio case
if(self.values[name]){
continue;
}
self.inputs.push({
name: name,
type: $(inputs[i]).attr('type') || inputs[i].tagName.toLowerCase()
});
// initialize values
self.values[name] = [];
}
// keep template
self.template = $row.prop('outerHTML');
// remove
$rows.remove();
// tell all that the template ready
self.$input.trigger('prepare-template', self.template);
};
// prepare modal window
self.prepareModal = function(){
var modalEl = $(self.options.modalElement);
// fix modal style
modalEl.css({
position: 'absolute',
width: 'auto',
'max-width': '100%'
});
modalEl.on('shown', function () {
self.resizeModal();
});
$(window).resize(function() {
self.resizeModal();
});
// init bootstrap modal
self.$modalWindow = modalEl.modal({show: false});
// tell all that the modal are ready
self.$input.trigger('prepare-modal', self.$modalWindow);
};
//resize and count position for the modal popup
self.resizeModal = function (){
if(!self.$modalWindow.is(':visible')){
// do nothing with hidden
return;
}
var docHalfWidth = $(document).width() / 2,
modalHalfWidth = self.$modalWindow.width() / 2,
rowsHalfWidth = self.$rowsContainer.width() / 2,
marginLeft = modalHalfWidth >= docHalfWidth ? 0 : -modalHalfWidth,
left = marginLeft ? '50%' : 0,
top = $(document).scrollTop() + $(window).height() * 0.2;//20% from top of visible win
self.$modalWindow.css({
top: top,
left: left,
'margin-left': marginLeft,
overflow: rowsHalfWidth > modalHalfWidth ? 'auto' : 'visible'
});
};
// build rows
self.buildRows = function(){
// clean up any old
var $oldRows = self.$rowsContainer.children();
if($oldRows.length){
self.removeRow($oldRows);
}
// go through values and add a new copy
// but make sure that at least one will be added
var count = self.values[Object.keys(self.values)[0]].length || 1,
row = null;
for(var i = 0; i < count; i++){
row = self.addRow(row, i);
}
};
// add new row
self.addRow = function(after, valueKey){
// count how much we already have
var count = self.$container.find(self.options.repeatableElement).length;
if(count >= self.options.maximum){
return null;
}
// make new from template
var row = $.parseHTML(self.template);
//add to container
if(after){
$(after).after(row);
} else {
self.$rowsContainer.prepend(row);
}
var $row = $(row);
// fix names and id`s
//self.fixUniqueAttributes($row, count + 1);
// set values
if(valueKey !== null && valueKey !== undefined){
for(var i = 0, l = self.inputs.length; i < l; i++){
var name = self.inputs[i].name,
type = self.inputs[i].type,
value = null;
if(self.values[name]){
value = self.values[name][valueKey];
}
// skip undefined
if(value === null || value === undefined){
continue;
}
if(type === 'radio'){
$row.find('*[name*="'+name+'"][value="' + value + '"]').attr('checked', 'checked');
}else if(type === 'checkbox'){
// check if there a multiple
if(value.length){
for(var v = 0, vl = value.length; v < vl; v++){
$row.find('*[name*="'+name+'"][value="' + value[v] + '"]').attr('checked', 'checked');
}
} else {
$row.find('*[name*="'+name+'"][value="' + value + '"]').attr('checked', 'checked');
}
} else {
$row.find('*[name*="'+name+'"]').val(value);
}
}
}
// try find out with related scripts,
// tricky thing, so be careful
try {
self.fixScripts($row);
} catch (e) {
if(window.console){
console.log(e);
}
}
// tell all about new row
self.$input.trigger('row-add', $row);
return $row;
};
// remove row from container
self.removeRow = function(row){
// tell all about row removing
self.$input.trigger('row-remove', row);
$(row).remove();
};
//fix names ind id`s for field that in $row
self.fixUniqueAttributes = function($row, count){
//all elements that have a "id" attribute
var haveIds = $row.find('*[id]');
self.incresseAttrName(haveIds, 'id', count);
// all labels that have a "for" attribute
var haveFor = $row.find('label[for]');
self.incresseAttrName(haveFor, 'for', count);
// all inputs that have a "name" attribute
var haveName = $row.find('*[name]');
self.incresseAttrName(haveName, 'name', count);
};
// increse attribute name like: attribute_value + '-' + count
self.incresseAttrName = function (elements, attr, count){
for(var i = 0, l = elements.length; i < l; i++){
var $el = $(elements[i]);
var oldValue = $el.attr(attr);
// set new
$el.attr(attr, oldValue + '-' + count);
}
};
// refresh value in the main input
self.refreshValue = function(){
var $rows = self.$container.find(self.options.repeatableElement);
// reset existing
self.values = {};
// go through available input names
for(var i = 0, l = self.inputs.length; i < l; i++){
var name = self.inputs[i].name,
type = self.inputs[i].type;
// init new
self.values[name] = [];
// find all inputs and take their values
for(var r = 0, rl = $rows.length; r < rl; r++){
var $row = $($rows[r]),
val = null;
if(type === 'radio'){
val = $row.find('*[name="'+name+'"]:checked').val();
}else if(type === 'checkbox'){
var checked = $row.find('*[name="'+name+'"]:checked');
// test for multiple
if(checked.length > 1){
val = [];
for(var c = 0, cl = checked.length; c < cl; c++){
val.push($(checked[c]).val());
}
} else {
// single checkbox
val = checked.val();
}
}else{
val = $row.find('*[name="'+name+'"]').val();
console.log(val);
}
val = val === null ? '' : val;
self.values[name].push(val)
}
}
// put in to the main input
$(self.$input.attr('data-input')).val(JSON.stringify(self.values));
// tell all about value changed
$(self.$input.attr('data-input')).trigger('value-update', self.values);
};
// remove scripts attached to fields
self.clearScripts = function($row){
// destroy chosen if any
if($.fn.chosen){
$row.find('select.chzn-done').chosen('destroy');
}
// colorpicker
if($.fn.minicolors){
$row.find('.minicolors input').each(function(){
$(this).removeData('minicolors-initialized')
.removeData('minicolors-settings')
.removeProp('size')
.removeProp('maxlength')
.removeClass('minicolors-input')
// move out from <span>
.parents('span.minicolors').parent().append(this);
});
$row.find('span.minicolors').remove();
}
};
// method for hack the scripts that can be related
// to the one of field that in given $row
self.fixScripts = function($row){
// chosen hack
if($.fn.chosen){
$row.find('select').chosen()
}
//color picker
$row.find('.minicolors').each(function() {
var $el = $(this);
$el.minicolors({
control: $el.attr('data-control') || 'hue',
position: $el.attr('data-position') || 'right',
theme: 'bootstrap'
});
});
// fix media field
$row.find('a[onclick*="jInsertFieldValue"]').each(function(){
var $el = $(this),
inputId = $el.siblings('input[type="text"]').attr('id'),
$select = $el.prev(),
oldHref = $select.attr('href');
// update the clear button
$el.attr('onclick', "jInsertFieldValue('', '" + inputId + "');return false;")
// update select button
$select.attr('href', oldHref.replace(/&fieldid=(.+)&/, '&fieldid=' + inputId + '&'));
});
// another modals
if(window.SqueezeBox){
SqueezeBox.assign($row.find('a.modal').get(), {parse: 'rel'});
}
};
// Run initializer
self.init();
};
// defaults
$.JRepeatable.defaults = {
modalElement: "#modal-container", // id of the modal container
btModalOpen: "#open-modal", // id of the button for initiate the modal window
btModalClose: ".close-modal", // button for close the modal window, and rollback all changes
btModalSaveData: ".save-modal-data", // button for close the modal window, and keep the all changes
btAdd: "a.add", // button selector for "add" action
btRemove: "a.remove",// button selector for "remove" action
maximum: 20, // maximum repeating
repeatableElement: "table tbody tr"
};
$.fn.JRepeatable = function(options){
return this.each(function(){
var options = options || {},
data = $(this).data();
for (var p in data) {
// check options in the element
if (data.hasOwnProperty(p)) {
options[p] = data[p];
}
}
new $.JRepeatable(this, options);
});
};
// initialise all available
// wait when all will be loaded, important for scripts fix
})(jQuery);