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.
 
 
 
 
 
 

421 lines
16 KiB

(function ($) {
/**
* This object provides helper functions for parsing a pasted smart snippet's code and auto populating the variable
* fields needed by that smart snippet.
* @type {Object}
*/
var LayoutParser = {
/**
* Clear all added variables from a container
* @param jQuery container
*/
emptyContainer:function (container) {
container.children('.inline-related ').each(function (i, item) {
if (!$(item).hasClass('empty-form'))
$(item).remove();
});
},
/**
* Gets the standard variables container or the drop down one
* @param String variablesHolderType
* @return {*\jQuery}
*/
getContainer:function (variablesHolderType) {
var cx = null;
$('.inline-group').each(function (i, item) {
if (variablesHolderType == 'standard') {
var header = $(item).children('h2').get(0);
if ($(header).text().toLowerCase() == 'standard variables') {
cx = $(item);
return;
}
} else if (variablesHolderType == 'select') {
var header = $(item).children('h2').get(0);
if ($(header).text().toLowerCase() == 'drop down variables') {
cx = $(item);
return;
}
}
});
return cx;
},
getExistingStandardVariables:function (container) {
var fieldRows = container.children('.dynamic-variables');
var existingVars = new Array();
fieldRows.each(function (i, row) {
var textField = $(row).find('.vTextField');
var typeField = $(row).find('select');
var name = textField.val();
var type = typeField.val();
var typeDocId = typeField.attr('id');
var obj = {name:name, type:type, typeDocId:typeDocId};
existingVars.push(obj);
});
return existingVars;
},
getExistingSelectVariables:function (container) {
var fieldRows = container.children('.dynamic-variables-2');
var existingVars = new Array();
fieldRows.each(function (i, row) {
var name = $(row).find('.field-name').find('.vTextField').val();
var nameDocId = $(row).find('.field-name').find('.vTextField').attr('id');
var values = $(row).find('.field-choices').find('.vTextField').val();
var valuesDocId = $(row).find('.field-choices').find('.vTextField').attr('id');
var obj = {name:name, values:values, valuesDocId:valuesDocId};
existingVars.push(obj);
});
return existingVars;
},
groupExistingVars:function (existingVars, newVars, variablesType) {
var similarVars = [];
var updateVars = [];
var toBeDeletedVars = [];
var similarFieldToCheck = (variablesType && variablesType.toLowerCase() == 'select' ? 'values' : 'type');
for (var i = 0; i < existingVars.length; i++) {
var toBeUpdated = false;
var updatedFieldValue = undefined;
var isSimilar = false;
for (var j = 0; j < newVars.length; j++) {
if (existingVars[i].name == newVars[j].varname && existingVars[i][similarFieldToCheck] == newVars[j][similarFieldToCheck]) {
isSimilar = true;
break;
} else if (existingVars[i].name == newVars[j].varname && existingVars[i][similarFieldToCheck] != newVars[j][similarFieldToCheck]) {
toBeUpdated = true;
updatedFieldValue = newVars[j][similarFieldToCheck];
break;
}
}
if (toBeUpdated) {
existingVars[i].updateWithValue = updatedFieldValue;
updateVars.push(existingVars[i]);
} else if (isSimilar) {
similarVars.push(existingVars[i]);
} else if (!toBeUpdated && !isSimilar) {
toBeDeletedVars.push(existingVars[i]);
}
}
return {
similarVars:similarVars,
toUpdateVars:updateVars,
deleteVars:toBeDeletedVars
};
},
findByVarName:function (arr, vName) {
var found = false;
$.each(arr, function (i, item) {
if (item.name == vName) {
found = item;
return;
}
});
return found;
},
markForDeletion:function (container, deletedVars) {
var rows = container.children('.inline-related');
var self = this;
$.each(rows, function (i, row) {
var varName = $(row).find('.field-name').find('.vTextField').val();
var isFoundVar = self.findByVarName(deletedVars, varName);
if (isFoundVar) {
var deleteBtn = $(row).find('a.inline-deletelink');
if(deleteBtn.get(0)) {
//most likely variable was added from a previous paste or by the user so trigger the deletion here
deleteBtn.trigger('click');
} else {
var deleteCheckbox = $(row).find('.delete').find('input[type=checkbox]');
deleteCheckbox.attr('checked', 'checked');
}
}
});
},
updateVars:function (container, updatedVars, varsType) {
var rows = container.children('.inline-related');
var objFieldToUpdate = (varsType.toLowerCase() == 'select' ? 'valuesDocId' : 'typeDocId');
var self = this;
$.each(rows, function (i, row) {
var varName = $(row).find('.field-name').find('.vTextField').val();
var isFoundVar = self.findByVarName(updatedVars, varName);
if (isFoundVar) {
$('#'+ isFoundVar[objFieldToUpdate]).val(isFoundVar.updateWithValue)
}
});
},
/**
* Find the "Add another Standard Variable" button and trigger a click event on it. Returns the div container
* holding form fields
* @param container
* @return {*|jQuery}
*/
clickAddNewFieldStd:function (container) {
//count the number of already inserted vars here
//subtract 1 for the empty one present by default
var presentFieldsCount = container.children('.inline-related').length - 1;
var addNewFieldBtn = $(container).children('div.add-row').find('a');
addNewFieldBtn.trigger('click');
var addedField = $(container).children('.inline-related').last().prev();
addedField.attr('id', 'variables-' + presentFieldsCount);
var textField = addedField.find('input.vTextField');
$(textField).attr('id', 'id_variables-' + presentFieldsCount + '-name');
$(textField).attr('name', 'variables-' + presentFieldsCount + '-name');
var textLabel = addedField.find('div.field-name').find('label');
$(textLabel).attr('for', 'id_variables-' + presentFieldsCount + '-name');
var select = addedField.find('div.field-widget').find('select');
$(select).attr('id', 'id_variables-' + presentFieldsCount + '-widget');
$(select).attr('name', 'variables-' + presentFieldsCount + '-widget');
var selectLabel = addedField.find('div.field-widget').find('label');
$(selectLabel).attr('for', 'id_variables-' + presentFieldsCount + '-widget')
return addedField;
},
/**
* Find the "Add another Drop Down Variable" button and trigger a click event on it. Returns the div container
* holding form fields. There is really no difference at the moment between this and the clickAddNewFieldStd.
* The only reason for them to be separate is for expressiveness and future extensions.
* @param container
* @return {*|jQuery}
*/
clickAddNewFieldSelect:function (container) {
var addNewFieldBtn = $(container).children('div.add-row').find('a');
addNewFieldBtn.trigger('click');
var addedField = $(container).children('.inline-related').last().prev();
var inputFields = addedField.children('.vTextField');
var presentFieldsCount = container.children('.inline-related').length;
$(inputFields[0]).attr('id', 'id_variables-2-' + presentFieldsCount + '-name');
$(inputFields[0]).attr('name', 'variables-2-' + presentFieldsCount + '-name');
$(inputFields[1]).attr('id', 'id_variables-2-' + presentFieldsCount + '-choices');
$(inputFields[1]).attr('name', 'variables-2-' + presentFieldsCount + '-choices');
return addedField;
},
/**
* Add a new standard variable in the container
* varNameObj = {varname: 'name', type: 'type'}
* @param varNameObj
* @param container
*/
addStdVar:function (varNameObj, container) {
var fieldCx = this.clickAddNewFieldStd(container);
$(fieldCx).find('input.vTextField').val(varNameObj.varname);
$(fieldCx).find('select').val(varNameObj.type);
},
/**
* Add a new drop down variable in the container
* varNameObj = {varname: 'name', type: 'type', values: 'value1,value2,value3'}
* @param varNameObj
* @param container
*/
addSelectVar:function (varNameObj, container) {
var fieldCx = this.clickAddNewFieldSelect(container);
$(fieldCx).find('div.field-name').find('input.vTextField').val(varNameObj.varname);
$(fieldCx).find('div.field-choices').find('input.vTextField').val(varNameObj.values);
},
/**
* The following code will try to match everything that's within an html comment tag. It should look like this
*
* <!-- SmartSnippets Variables
* varname=type
* -->
*
* Where type could be anything from TextField, TextAreaField, MerlinField or ImageField
* Each variable is declared on a new line.
*/
extractVarnames:function (text) {
var regex = /<!-- SmartSnippets Variables([^>]*)-->/gi;
var variablesSnippet = regex.exec(text);
var varNames = []; //hold the var names here
if (variablesSnippet) {
var lines = variablesSnippet[1].split('\n'); //split the input in multiple lines
$.each(lines, function (index, line) {
if ($.trim(line).length > 0) {
var vObj = {};
var vDeclarationArr = line.split('=');
vObj.varname = $.trim(vDeclarationArr[0]);
var type = $.trim(vDeclarationArr[1]);
if (type.toLowerCase().indexOf('select') != -1) {
var tmp = type.split('|');
vObj.type = $.trim(tmp[0]);
vObj.values = vDeclarationArr[2] ? $.trim(vDeclarationArr[2]) : '';
} else {
vObj.type = $.trim(vDeclarationArr[1]);
}
varNames.push(vObj);
}
});
}
return varNames;
},
groupNewVars:function (varsArr) {
var returnObj = {};
returnObj.standard = new Array();
returnObj.select = new Array();
$.each(varsArr, function (i, variable) {
if (variable.type.toLowerCase() == 'select') {
returnObj.select.push(variable);
} else {
returnObj.standard.push(variable);
}
});
return returnObj;
},
getOnlyToAddVars: function(groupedVars, newVars) {
var onlyToAdd = new Array();
for (var i = 0; i < newVars.length; i++) {
var notInUpdates = true;
var notInSimilar = true;
for(var j = 0; j < groupedVars.similarVars.length; j++) {
if(newVars[i].varname == groupedVars.similarVars[j].name) {
notInSimilar = false;
}
}
for(var k = 0; k < groupedVars.toUpdateVars.length; k++) {
if(newVars[i].varname == groupedVars.toUpdateVars[k].name) {
notInUpdates = false;
}
}
if(notInSimilar && notInUpdates) {
onlyToAdd.push(newVars[i]);
}
}
return onlyToAdd;
},
/**
* Given an array of objects with the following structure {varname: 'name', type: 'type', values: 'value1,
* value2,value3'} or varNameObj = {varname: 'name', type: 'type'} this function fill parse the array.
*
* @param varNamesArr
*/
populate:function (varNamesArr) {
var self = this;
if (varNamesArr.length > 0) { //don't do any mumbo jumbo if we have no varnames
var groupedNewVars = self.groupNewVars(varNamesArr);
var stdContainer = self.getContainer('standard');
var selectContainer = self.getContainer('select');
var existingStdVars = self.getExistingStandardVariables(stdContainer);
var existingSelectVars = self.getExistingSelectVariables(selectContainer);
var groupedExistingStdVars = self.groupExistingVars(existingStdVars, groupedNewVars.standard, 'standard');
if (existingStdVars.length > 0) {
self.markForDeletion(stdContainer, groupedExistingStdVars.deleteVars);
self.updateVars(stdContainer, groupedExistingStdVars.toUpdateVars, 'standard');
}
var groupedExistingSelectVars = self.groupExistingVars(existingSelectVars, groupedNewVars.select, 'select');
if(existingSelectVars.length > 0) {
self.markForDeletion(selectContainer, groupedExistingSelectVars.deleteVars);
self.updateVars(selectContainer, groupedExistingSelectVars.toUpdateVars, 'select');
}
var onlyToAddStdVars = self.getOnlyToAddVars(groupedExistingStdVars, groupedNewVars.standard);
var onlyToAddSelectVars = self.getOnlyToAddVars(groupedExistingSelectVars, groupedNewVars.select);
$.each(onlyToAddStdVars, function(i, vObj) {
self.addStdVar(vObj, stdContainer);
});
$.each(onlyToAddSelectVars, function(i, vObj) {
self.addSelectVar(vObj, selectContainer);
});
}
}
};
$.updateSnippetVars = function(el){
//use a setTimeout to capture pasted text
setTimeout(function () {
var checkboxes = django.jQuery('.delete input[type=checkbox]');
django.jQuery.each(checkboxes, function(i, box) {
django.jQuery(this).attr('checked', false);
});
var text = django.jQuery(el).val();
var varNames = LayoutParser.extractVarnames(text);
LayoutParser.populate(varNames);
}, 100);
};
$(document).ready(function () {
var textArea = $('#id_template_code');
textArea.bind('paste', function (e) {
var el = $(this);
// if ($.trim($(el).val()).length == 0) {//only when the area is empty
//use a setTimeout to capture pasted text
$.updateSnippetVars(el);
// }
});
});
})(django.jQuery);