/**
* ELEMENTS CREATING
*
* Script for creating elements and manipulating with element options.
*
*/
(function ($) {
var newElementId = 0;
/**
* Get element current position
*
* @param $element
*/
CMA.getElementPosition = function ($element) {
var elementPosition = {};
var $rowContainer = $('#cma-elements-container .row-container');
var $currentRowContainer = $element.closest('.row-container');
elementPosition.rowId = $rowContainer.index($currentRowContainer);
elementPosition.gridId = $currentRowContainer.find('.grid').index($element.closest('.grid'));
elementPosition.elIndex = $element.parent().find($element).index();
return elementPosition;
}
/**
* Set element new position
*
* @param $element
* @param newElementId
* @param position
* @param oldGridPosition
*/
CMA.setElementPosition = function ($element, newElementId, position, oldGridPosition) {
// if this is new element
if (newElementId) {
var elInfo = {};
var elPos = CMA.getElementPosition($element);
elInfo.name = $element.data('name');
elInfo.id = $element.data('id');
elInfo.type = $element.data('type');
elInfo.options = {};
CMA.layout.rows[elPos.rowId].grids[elPos.gridId].elements.push(elInfo);
} else {
var oldElement, oldElPosition;
var elPos = CMA.getElementPosition($element);
newElementId = $element.data('id');
if (oldGridPosition) {
oldElPosition = CMA.getElementPosition(oldGridPosition);
} else {
oldElPosition = elPos;
}
var elementsCollection = CMA.layout.rows[oldElPosition.rowId].grids[oldElPosition.gridId].elements;
for (var i = 0; i < elementsCollection.length; i++) {
if (elementsCollection[i].id == newElementId) {
oldElement = elementsCollection[i];
elementsCollection.splice(i, 1);
}
}
CMA.layout.rows[oldElPosition.rowId].grids[oldElPosition.gridId].elements = elementsCollection;
CMA.layout.rows[elPos.rowId].grids[elPos.gridId].elements.splice(position, 0, oldElement);
}
}
/**
* Remove element from grid and in main object
*
*/
$.fn.removeElement = function () {
var $element = $(this);
$element.hide();
var rowContainer = $element.closest('.row-container');
// Remove the dialog if it exists
if (typeof ($element.data('dialog')) != "undefined")
$element.data('dialog').dialog('destroy').remove();
// get element position
var elPos = CMA.getElementPosition($element);
// remove it from Layout object
CMA.layout.rows[elPos.rowId].grids[elPos.gridId].elements.splice(elPos.elIndex, 1);
// remove it from grid
$element.remove();
rowContainer.rowsResizeGrids(true);
CMA.saveLayoutDataInHTML();
}
/**
* Create and return a new element
*
* @param name
* @param data
* @param type
*
* @return {*}
*/
CMA.createElement = function (name, data, type) {
var elementData = {};
elementData.translations = {};
var elementId;
newElementId++;
// check if element is still available (registered in wordpress)
var elObject = _.filter(CMA.availableElements, function (obj) {
return obj.name == name;
});
if (elObject.length == 0)
return null;
elementData.name = name;
elementData.type = type;
elementData.id = newElementId;
elementData.title = elObject[0].title;
elementData.description = elObject[0].description;
// add additional description for element that has define "selected_option" field
if (typeof (elObject[0].selected_option) == "undefined" || !elObject[0].selected_option) {
elementData.selected_option = 0;
} else if (!_.isEmpty(data)) {
// check if option ID is complex i.e. field is group
var optionId = elObject[0].selected_option;
if (optionId.indexOf('|') != -1) {
optionId = optionId.split("|");
}
// when field is select/radio "selected_option_options" is set so we can retrieve selected Value instead of Key
if (typeof (elObject[0].selected_option_options) != "undefined" && !_.isEmpty(elObject[0].selected_option_options)) {
// check if optionId is array
// if that's a case we will get first value in array
if (_.isArray(optionId)) {
var selectedOptionKey = data[optionId[0]][1][optionId[1]];
} else {
var selectedOptionKey = data[optionId];
}
// check that "selected_option_options" is array and that it has some value
if (
(_.isArray(elObject[0].selected_option_options) || _.isObject(elObject[0].selected_option_options))
&& typeof (elObject[0].selected_option_options[selectedOptionKey]) != "undefined"
)
{
// get Value of field by it's Key
elementData.selected_option = elObject[0].selected_option_options[selectedOptionKey];
}
}
// otherwise just check that field isn't empty
else if (!_.isEmpty(data[optionId]) || (_.isArray(optionId) && !_.isEmpty(data[optionId[0]][1][optionId[1]]))) {
// check if optionId is array
// if that's a case we will get first value in array
if (_.isArray(optionId)) {
var text = data[optionId[0]][1][optionId[1]];
} else {
var text = data[optionId];
}
// unescape HTML so we can clean up the string
text = _.unescape(text);
// remove all HTML
text = $('<div/>').html(text).text();
// check if string is longer of 25 letters
if (text.length > 25) {
// cut the string to 25 letters
elementData.selected_option = text.substr(0, 25) + "...";
} else {
elementData.selected_option = text;
}
}
}
// add translations to the object
elementData.translations.edit = CMA.i10n.templates.element['edit'];
elementData.translations.duplicate = CMA.i10n.templates.element['duplicate'];
elementData.translations['delete'] = CMA.i10n.templates.element['delete'];
// fetch and render template
var elementTemplate = $("#cma-tpl-element").html();
var element = _.template(elementTemplate, elementData, CMA.templatesOptions);
var element = $(element);
// Create button edit
element.find('.actions .edit')
.click(function () {
var dialog = CMA.initElementDialog(element);
dialog.dialog('open');
return false;
});
// Create button duplicate
element.find('.actions .duplicate')
.click(function () {
// find element position and options
//var $element = $(this).closest('.element');
var elPos = CMA.getElementPosition(element);
var elId = element.data('id');
var elOptions = CMA.layout.rows[elPos.rowId].grids[elPos.gridId].elements[elPos.elIndex].options;
// duplicate the element in grid
var duplicate = CMA.createElement(element.attr('data-name'), elOptions, element.attr('data-type'));
// add element to grid
CMA.addElementToGrid(duplicate, element.closest('.elements-container'), null);
// get duplicate position
var duplPos = CMA.getElementPosition(duplicate);
// duplicate element options
CMA.layout.rows[duplPos.rowId].grids[duplPos.gridId].elements[duplPos.elIndex].options = elOptions;
// create and open dialog
var dialog = CMA.initElementDialog(duplicate);
dialog.dialog('open');
duplicate.removeClass('new-element');
CMA.saveLayoutDataInHTML();
return false;
});
// Create button delete
element.find('.actions .delete')
.click(function () {
var confirm = window.confirm("Are you sure you want to delete the element?");
if (confirm == true) {
$(this).closest('.element').removeElement();
}
return false;
});
// This is to refresh the dialog positions
$(window).resize();
return element;
}
/**
* Init Dialog for element
*
* @param element
* @param data
*
* @return dialog
*/
CMA.initElementDialog = function (element, data) {
var dialog;
var elementClass;
var elObject = _.filter(CMA.availableElements, function (obj) {
return obj.name == element.data('name');
});
if (elObject.length == 0)
return null;
if (typeof (element.data('dialog')) != "undefined" || element.data('dialog'))
return element.data('dialog');
// add additional class for easier styling
if (element.data('type') == 'widget') {
elementClass = 'widget-' + element.data('name');
} else {
elementClass = 'shortcode-' + element.data('name');
}
var promise;
dialog = $('<div class="elements-dialog dialog-form"></div>')
.dialog({
dialogClass: 'cma-admin-dialog ' + elementClass,
autoOpen: false,
modal: false, // Disable modal so we don't mess with media editor. We'll create our own overlay.
draggable: false,
resizable: false,
title: CMA.i10n.messages.editWidget.replace('%s', elObject[0].title),
minWidth: 760,
maxHeight: Math.round($(window).height() * 0.85),
create: function (event, ui) {
var currentDialog = $(this);
var dialogTypeClass = 'cma-' + element.data('type') + '-content';
$(this).addClass(dialogTypeClass);
// This is so we can access the dialog (and its forms) later.
element.data('dialog', currentDialog).disableSelection();
currentDialog.data('element', element.data('id'));
var nonce = $('#_cma_nonce').val();
var elementName = element.data('name');
var type = element.data('type');
var elementId = element.data('id');
var data = {action: "cma_element_options_form", name: elementName, nonce: nonce, type: type, id: elementId}
promise = CMA.fetchHTMLForms(data, currentDialog);
promise.done(function (response) {
var elPos = CMA.getElementPosition(element);
var data = CMA.layout.rows[elPos.rowId].grids[elPos.gridId].elements[elPos.elIndex];
// populate dialog option fields
if (!_.isEmpty(data))
CMA.fillDialogOptionFields(currentDialog, data);
// calculate new vertical position for dialog
CMA.setDialogVerticalPosition(currentDialog);
// trigger event so we can hook up onto it and change form
currentDialog.trigger('elementsdialogcreated', [element, $(this)]);
});
},
open: function () {
var currentDialog = $(this);
promise.done(function (response) {
// trigger event so we can hook up onto it and change form
currentDialog.trigger('elementsdialogopen', [element, currentDialog]);
});
var overlay = $('<div class="cma-ui-widget-overlay ui-front"></div>').css('z-index', 1000);
currentDialog.data('overlay', overlay).closest('.ui-dialog').before(overlay);
},
close: function () {
// trigger event so we can hook up onto it and change form
$(this).trigger('elementsdialogclose', [element, $(this)]);
var element;
var elementId = $(this).data('element');
$('.grid .element').each(function () {
if ($(this).data('id') == elementId) {
element = $(this);
}
})
var elementPos = CMA.getElementPosition(element);
var elementIndex = element.index();
var elementOptions = CMA.getDialogOptions($(this));
CMA.layout.rows[elementPos['rowId']].grids[elementPos['gridId']].elements[elementIndex].options = elementOptions;
CMA.saveLayoutDataInHTML();
$(this).data('overlay').remove();
// trigger event so we can hook up onto it and change form
$(this).trigger('elementsdialogcloseafter', [element, $(this)]);
},
buttons: [{text: CMA.i10n.buttons['done'], click: function () {
dialog.dialog('close');
}}]
})
.keypress(function (e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
if ($(this).closest('.ui-dialog').find('textarea:focus').length > 0)
return;
// This is the same as clicking the add button
$(this).closest('.ui-dialog').find('.ui-dialog-buttonpane .cma-ui-button:eq(0)').click();
e.preventDefault();
return false;
}
else if (e.keyCode === $.ui.keyCode.ESCAPE) {
$(this).closest('.ui-dialog').dialog('close');
}
});
return dialog;
}
// increment element group index in name attribute
function cma_group_name_replace(g1, g2, g3, g4) {
return g2 + "[" + (Number(g3) + 1) + "]";
}
// increment element group index in ID attribute
function cma_group_id_replace(match, g1, g2, g3, g4) {
return "-" + (Number(g1) + 1) + g2;
}
// increment element subgroup index in name attribute
function cma_subgroup_name_replace(match, g2, g3, g4, g5) {
return "[" + g2 + "]" + g3 + "[" + (Number(g4) + 1) + "]" + g5;
}
// increment element subgroup index in ID attribute
function cma_subgroup_id_replace(match, g2, g3) {
return "-" + (Number(g2) + 1) + "-" + g3;
}
/**
* Duplicate options group
*
* @param group
*
* @return object
*/
CMA.duplicateOptionsGroup = function (group, subGroup) {
var duplicate = group.clone();
if (duplicate.find('.icons-selector').length > 0) {
duplicate.find('.icons-selector').remove();
duplicate.find('.cma-icon-picker').prop('selectedIndex', 0).fontIconPicker();
}
duplicate.find('input[name^="elements"], textarea[name^="elements"], select[name^="elements"]').each(function () {
// check if we are duplicating subgroup
if ($(this).closest('.shortcode-options-group').hasClass('subgroup') && subGroup) {
$(this)
// replace attribute name
.attr('name', function (i, val) {
return val.replace(/\[([0-9])\](\[[a-zA-Z0-9]+\])\[([0-9])\](\[[a-zA-Z0-9]+\])$/, cma_subgroup_name_replace);
})
// replace attribute ID
.attr('id', function (i, val) {
return val.replace(/-([0-9]+)-([0-9a-zA-Z]+(?:-[0-9a-zA-Z]+)?)$/, cma_subgroup_id_replace);
})
// replace "for" attribute for label
.closest('.option-container').find('> label')
.attr('for', function (i, val) {
return val.replace(/-([0-9]+)-([0-9a-zA-Z]+(?:-[0-9a-zA-Z]+)?)$/, cma_subgroup_id_replace);
});
} else {
$(this)
// replace attribute name
.attr('name', function (i, val) {
return val.replace(/(\[[0-9]+\]\[.*?])\[([0-9]+)\]/, cma_group_name_replace);
})
// replace attribute ID
.attr('id', function (i, val) {
return val.replace(/-([0-9]+)(-[0-9a-zA-Z]+-[0-9]+-[0-9a-zA-Z]+-?[0-9a-zA-Z]+)+$/, cma_group_id_replace);
})
// replace "for" attribute for label
.closest('.option-container').find('> label')
.attr('for', function (i, val) {
return val.replace(/-([0-9]+)(-[0-9a-zA-Z]+-[0-9]+-[0-9a-zA-Z]+-?[0-9a-zA-Z]+)+$/, cma_group_id_replace);
});
}
if ($(this).attr('type') == 'text' || $(this).is('textarea') || $(this).attr('type') == 'number' || $(this).attr('type') == 'hidden') {
$(this).val('');
if ($(this).data('type') == 'image') {
$(this).closest('.option-container').find('.shortcode-options-thumb-id').val('').end().find('.shortcode-options-thumbs').empty();
}
} else if ($(this).is('select')) {
$(this).prop('selectedIndex', 0);
} else if ($(this).attr('type') == 'checkbox') {
$(this).prop('checked', 0);
} else if ($(this).attr('type') == 'radio') {
$(this).prop('checked', 0);
$(this).next('label').attr('for', function (i, val) {
if ($(this).closest('.shortcode-options-group').hasClass('subgroup') && subGroup) {
return val.replace(/-([0-9]+)-([0-9a-zA-Z]+(?:-[0-9a-zA-Z]+)?)$/, cma_subgroup_id_replace);
} else {
return val.replace(/-([0-9]+)(-[0-9a-zA-Z]+-[0-9]+-[0-9a-zA-Z]+-?[0-9a-zA-Z]+)+$/, cma_group_id_replace);
}
});
}
});
return duplicate;
}
/**
* Adds element to grid
*
* @param element
* @param container
* @param position
* @param load
*/
CMA.addElementToGrid = function (element, container, position, load) {
if (container == null)
container = $('#cma-elements-container .grid.grid-selected .elements-container').eq(0);
if (container.length == 0)
container = $('#cma-elements-container .grid .elements-container').eq(0);
if (container.length == 0)
return;
if (position == null) {
container.append(element);
} else {
var current = container.find('.element').eq(position);
if (current.length == 0) {
container.append(element);
} else {
element.insertBefore(current);
}
}
//container.sortable("refresh").trigger('refreshcells');
// container.sortable("refresh");
container.closest('.row-container').rowsResizeGrids();
// if element is created on page load, don't create dialog
if (!load) {
CMA.setElementPosition(element, newElementId, position);
}
CMA.saveLayoutDataInHTML();
}
/**
* Setup rows, grids and elements
*
* @param layout
*/
CMA.loadLayout = function (layout, partialImport) {
// remove all rows
$('#cma-elements-container .row-container').remove();
if (!partialImport) {
// find and set last section id
CMA.setInitialSectionId();
}
// Create all the content
for (var rowId in layout.rows) {
var gridSizes = [];
var gridsCount = layout.rows[rowId].grids.length;
var grids = layout.rows[rowId].grids;
// Get grid sizes
for (var gridId in grids) {
gridSizes[gridSizes.length] = Number(grids[gridId].size);
}
// Create rows and sections
var row = CMA.createRow(gridsCount, gridSizes, true);
var sectionId = layout.rows[rowId].section;
// if element is in section call function to add required classes
if (sectionId && sectionId !== "") {
row.rowToSection(false, sectionId);
}
for (var gridId in grids) {
gridSizes[gridSizes.length] = Number(grids[gridId].size);
for (var elmId in grids[gridId].elements) {
//elements[elements.length] = grids[gridId].elements[elmId];
var element = grids[gridId].elements[elmId];
// create element HTML
var $element = CMA.createElement(element.name, element.options, element.type);
if ($element != null) {
// set new element ID
CMA.layout.rows[rowId].grids[gridId].elements[elmId].id = $element.data('id');
// append element to grid
var container = row.find('.grid').eq(gridId).find('.elements-container');
CMA.addElementToGrid($element, container, null, true);
}
}
}
}
$('#content-maker').refreshSectionsClasses();
window.CMA.activateSectionMode(true);
}
})(jQuery); |