551 lines
18 KiB
JavaScript
551 lines
18 KiB
JavaScript
angular.module("umbraco")
|
|
.controller("Umbraco.PropertyEditors.GridController",
|
|
function ($scope, $http, assetsService, $rootScope, dialogService, gridService, mediaResource, imageHelper, $timeout) {
|
|
|
|
// Grid status variables
|
|
$scope.currentRow = null;
|
|
$scope.currentCell = null;
|
|
$scope.currentToolsControl = null;
|
|
$scope.currentControl = null;
|
|
$scope.openRTEToolbarId = null;
|
|
$scope.hasSettings = false;
|
|
|
|
// *********************************************
|
|
// Sortable options
|
|
// *********************************************
|
|
|
|
$scope.sortableOptions = {
|
|
distance: 10,
|
|
cursor: "move",
|
|
placeholder: 'ui-sortable-placeholder',
|
|
handle: '.cell-tools-move',
|
|
forcePlaceholderSize: true,
|
|
tolerance: "pointer",
|
|
zIndex: 999999999999999999,
|
|
scrollSensitivity: 100,
|
|
cursorAt: {
|
|
top: 45,
|
|
left: 90
|
|
},
|
|
|
|
start: function (e, ui) {
|
|
ui.item.find('.mceNoEditor').each(function () {
|
|
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
|
|
});
|
|
},
|
|
|
|
stop: function (e, ui) {
|
|
ui.item.parents(".usky-column").find('.mceNoEditor').each(function () {
|
|
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
|
|
tinyMCE.execCommand('mceAddEditor', false, $(this).attr('id'));
|
|
});
|
|
}
|
|
|
|
};
|
|
|
|
var notIncludedRte = [];
|
|
var cancelMove = false;
|
|
|
|
$scope.sortableOptionsCell = {
|
|
|
|
distance: 10,
|
|
cursor: "move",
|
|
placeholder: "ui-sortable-placeholder",
|
|
handle: '.cell-tools-move',
|
|
connectWith: ".usky-cell",
|
|
forcePlaceholderSize: true,
|
|
tolerance:"pointer",
|
|
zIndex: 999999999999999999,
|
|
scrollSensitivity: 100,
|
|
cursorAt: {
|
|
top: 45,
|
|
left: 90
|
|
},
|
|
|
|
over: function (event, ui) {
|
|
allowedEditors = $(event.target).scope().area.allowed;
|
|
|
|
if ($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) {
|
|
ui.placeholder.hide();
|
|
cancelMove = true;
|
|
}
|
|
else {
|
|
ui.placeholder.show();
|
|
cancelMove = false;
|
|
}
|
|
|
|
},
|
|
|
|
update: function (event, ui) {
|
|
if (!ui.sender) {
|
|
if (cancelMove) {
|
|
ui.item.sortable.cancel();
|
|
}
|
|
ui.item.parents(".usky-cell").find('.mceNoEditor').each(function () {
|
|
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
|
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
$(event.target).find('.mceNoEditor').each(function () {
|
|
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
|
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
|
}
|
|
});
|
|
}
|
|
|
|
},
|
|
|
|
start: function (e, ui) {
|
|
ui.item.find('.mceNoEditor').each(function () {
|
|
notIncludedRte = [];
|
|
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
|
|
});
|
|
},
|
|
|
|
stop: function (e, ui) {
|
|
ui.item.parents(".usky-cell").find('.mceNoEditor').each(function () {
|
|
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
|
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
|
}
|
|
});
|
|
$timeout(function () {
|
|
_.forEach(notIncludedRte, function (id) {
|
|
tinyMCE.execCommand('mceRemoveEditor', false, id);
|
|
tinyMCE.execCommand('mceAddEditor', false, id);
|
|
console.info("stop " + id);
|
|
});
|
|
}, 500, false);
|
|
}
|
|
|
|
};
|
|
|
|
// *********************************************
|
|
// Add items overlay menu
|
|
// *********************************************
|
|
$scope.overlayMenu = {
|
|
show: false,
|
|
style: {},
|
|
area: undefined,
|
|
key: undefined
|
|
};
|
|
|
|
$scope.addItemOverlay = function(event, area, index, key){
|
|
$scope.overlayMenu.area = area;
|
|
$scope.overlayMenu.index = index;
|
|
$scope.overlayMenu.style = {};
|
|
$scope.overlayMenu.key = key;
|
|
|
|
//todo calculate position...
|
|
var offset = $(event.target).offset();
|
|
var height = $(window).height();
|
|
var width = $(window).width();
|
|
|
|
if((height-offset.top) < 250){
|
|
$scope.overlayMenu.style.bottom = 0;
|
|
$scope.overlayMenu.style.top = "initial";
|
|
}else if(offset.top < 300){
|
|
$scope.overlayMenu.style.top = 190;
|
|
}
|
|
|
|
$scope.overlayMenu.show = true;
|
|
};
|
|
|
|
$scope.closeItemOverlay = function () {
|
|
$scope.currentControl = null;
|
|
$scope.overlayMenu.show = false;
|
|
$scope.overlayMenu.key = undefined;
|
|
};
|
|
|
|
// *********************************************
|
|
// Template management functions
|
|
// *********************************************
|
|
|
|
$scope.addTemplate = function (template) {
|
|
$scope.model.value = angular.copy(template);
|
|
|
|
//default row data
|
|
_.forEach($scope.model.value.sections, function(section){
|
|
$scope.initSection(section);
|
|
});
|
|
};
|
|
|
|
|
|
// *********************************************
|
|
// Row management function
|
|
// *********************************************
|
|
|
|
$scope.setCurrentRow = function (row) {
|
|
$scope.currentRow = row;
|
|
};
|
|
|
|
$scope.disableCurrentRow = function () {
|
|
$scope.currentRow = null;
|
|
};
|
|
|
|
$scope.setWarnighlightRow = function (row) {
|
|
$scope.currentWarnhighlightRow = row;
|
|
};
|
|
|
|
$scope.disableWarnhighlightRow = function () {
|
|
$scope.currentWarnhighlightRow = null;
|
|
};
|
|
|
|
$scope.setInfohighlightRow = function (row) {
|
|
$scope.currentInfohighlightRow = row;
|
|
};
|
|
|
|
$scope.disableInfohighlightRow = function () {
|
|
$scope.currentInfohighlightRow = null;
|
|
};
|
|
|
|
$scope.getAllowedLayouts = function(column){
|
|
var layouts = $scope.model.config.items.layouts;
|
|
|
|
if(column.allowed && column.allowed.length > 0){
|
|
return _.filter(layouts, function(layout){
|
|
return _.indexOf(column.allowed, layout.name) >= 0;
|
|
});
|
|
}else{
|
|
return layouts;
|
|
}
|
|
};
|
|
|
|
$scope.addRow = function (section, layout) {
|
|
|
|
//copy the selected layout into the rows collection
|
|
var row = angular.copy(layout);
|
|
|
|
// Init row value
|
|
row = $scope.initRow(row);
|
|
|
|
// Push the new row
|
|
if(row){
|
|
section.rows.push(row);
|
|
}
|
|
};
|
|
|
|
$scope.removeRow = function (section, $index) {
|
|
if (section.rows.length > 0) {
|
|
section.rows.splice($index, 1);
|
|
$scope.currentRow = null;
|
|
$scope.openRTEToolbarId = null;
|
|
$scope.initContent();
|
|
}
|
|
};
|
|
|
|
$scope.editGridItemSettings = function (gridItem) {
|
|
|
|
dialogService.open(
|
|
{
|
|
template: "views/propertyeditors/grid/dialogs/config.html",
|
|
gridItem: gridItem,
|
|
config: $scope.model.config,
|
|
callback: function(data){
|
|
|
|
gridItem.styles = data.styles;
|
|
gridItem.config = data.config;
|
|
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
// *********************************************
|
|
// Area management functions
|
|
// *********************************************
|
|
|
|
$scope.setCurrentCell = function (cell) {
|
|
$scope.currentCell = cell;
|
|
};
|
|
|
|
$scope.disableCurrentCell = function () {
|
|
$scope.currentCell = null;
|
|
};
|
|
|
|
$scope.cellPreview = function(cell){
|
|
if(cell && cell.$allowedEditors){
|
|
var editor = cell.$allowedEditors[0];
|
|
return editor.icon;
|
|
}else{
|
|
return "icon-layout";
|
|
}
|
|
};
|
|
|
|
$scope.setInfohighlightArea = function (cell) {
|
|
$scope.currentInfohighlightArea = cell;
|
|
};
|
|
|
|
$scope.disableInfohighlightArea = function () {
|
|
$scope.currentInfohighlightArea = null;
|
|
};
|
|
|
|
|
|
// *********************************************
|
|
// Control management functions
|
|
// *********************************************
|
|
$scope.setCurrentControl = function (Control) {
|
|
$scope.currentControl = Control;
|
|
};
|
|
|
|
$scope.disableCurrentControl = function (Control) {
|
|
$scope.currentControl = null;
|
|
};
|
|
|
|
$scope.setCurrentToolsControl = function (Control) {
|
|
$scope.currentToolsControl = Control;
|
|
};
|
|
|
|
$scope.disableCurrentToolsControl = function (Control) {
|
|
$scope.currentToolsControl = null;
|
|
};
|
|
|
|
$scope.setWarnhighlightControl = function (Control) {
|
|
$scope.currentWarnhighlightControl = Control;
|
|
};
|
|
|
|
$scope.disableWarnhighlightControl = function (Control) {
|
|
$scope.currentWarnhighlightControl = null;
|
|
};
|
|
|
|
$scope.setInfohighlightControl = function (Control) {
|
|
$scope.currentInfohighlightControl = Control;
|
|
};
|
|
|
|
$scope.disableInfohighlightControl = function (Control) {
|
|
$scope.currentInfohighlightControl = null;
|
|
};
|
|
|
|
$scope.setUniqueId = function (cell, index) {
|
|
return guid();
|
|
};
|
|
|
|
var guid = (function () {
|
|
function s4() {
|
|
return Math.floor((1 + Math.random()) * 0x10000)
|
|
.toString(16)
|
|
.substring(1);
|
|
}
|
|
return function () {
|
|
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
|
s4() + '-' + s4() + s4() + s4();
|
|
};
|
|
})();
|
|
|
|
$scope.addControl = function (editor, cell, index){
|
|
$scope.closeItemOverlay();
|
|
|
|
var newControl = {
|
|
value: null,
|
|
editor: editor
|
|
};
|
|
|
|
if (index === undefined) {
|
|
index = cell.controls.length;
|
|
}
|
|
|
|
//populate control
|
|
$scope.initControl(newControl, index+1);
|
|
|
|
cell.controls.splice(index + 1, 0, newControl);
|
|
};
|
|
|
|
$scope.addTinyMce = function(cell){
|
|
var rte = $scope.getEditor("rte");
|
|
$scope.addControl(rte, cell);
|
|
};
|
|
|
|
$scope.getEditor = function(alias){
|
|
return _.find($scope.availableEditors, function(editor){return editor.alias === alias});
|
|
};
|
|
|
|
$scope.removeControl = function (cell, $index) {
|
|
$scope.currentControl = null;
|
|
cell.controls.splice($index, 1);
|
|
};
|
|
|
|
$scope.percentage = function(spans){
|
|
return ((spans/12)*100).toFixed(1);
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// *********************************************
|
|
// INITIALISATION
|
|
// these methods are called from ng-init on the template
|
|
// so we can controll their first load data
|
|
//
|
|
// intialisation sets non-saved data like percentage sizing, allowed editors and
|
|
// other data that should all be pre-fixed with $ to strip it out on save
|
|
// *********************************************
|
|
|
|
// *********************************************
|
|
// Init template + sections
|
|
// *********************************************
|
|
$scope.initContent = function() {
|
|
var clear = true;
|
|
|
|
//settings indicator shortcut
|
|
if($scope.model.config.items.config || $scope.model.config.items.styles){
|
|
$scope.hasSettings = true;
|
|
}
|
|
|
|
if ($scope.model.value && $scope.model.value.sections && $scope.model.value.sections.length > 0) {
|
|
_.forEach($scope.model.value.sections, function(section){
|
|
|
|
$scope.initSection(section);
|
|
|
|
//we do this to ensure that the grid can be reset by deleting the last row
|
|
if(section.rows.length > 0){
|
|
clear = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
if(clear){
|
|
$scope.model.value = undefined;
|
|
}
|
|
};
|
|
|
|
$scope.initSection = function(section){
|
|
section.$percentage = $scope.percentage(section.grid);
|
|
|
|
var layouts = $scope.model.config.items.layouts;
|
|
|
|
if(section.allowed && section.allowed.length > 0){
|
|
section.$allowedLayouts = _.filter(layouts, function(layout){
|
|
return _.indexOf(section.allowed, layout.name) >= 0;
|
|
});
|
|
}else{
|
|
section.$allowedLayouts = layouts;
|
|
}
|
|
|
|
if(!section.rows){
|
|
section.rows = [];
|
|
}else{
|
|
_.forEach(section.rows, function(row, index){
|
|
if(!row.$initialized){
|
|
var initd = $scope.initRow(row);
|
|
|
|
//if init fails, remove
|
|
if(!initd){
|
|
section.rows.splic(index, 1);
|
|
}else{
|
|
section.rows[index] = initd;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
// *********************************************
|
|
// Init layout / row
|
|
// *********************************************
|
|
$scope.initRow = function(row){
|
|
|
|
//merge the layout data with the original config data
|
|
//if there are no config info on this, splice it out
|
|
var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; });
|
|
|
|
if(!original){
|
|
return null;
|
|
}else{
|
|
//make a copy to not touch the original config
|
|
original = angular.copy(original);
|
|
original.styles = row.styles;
|
|
original.config = row.config;
|
|
|
|
//sync area configuration
|
|
_.each(original.areas, function(area, areaIndex){
|
|
|
|
var currentArea = row.areas[areaIndex];
|
|
area.config = currentArea.config;
|
|
area.styles = currentArea.styles;
|
|
|
|
//copy over existing controls into the new areas
|
|
if(row.areas.length > areaIndex && row.areas[areaIndex].controls){
|
|
area.controls = currentArea.controls;
|
|
|
|
_.forEach(area.controls, function(control, controlIndex){
|
|
$scope.initControl(control, controlIndex);
|
|
});
|
|
|
|
}else{
|
|
area.controls = [];
|
|
}
|
|
|
|
//set width
|
|
area.$percentage = $scope.percentage(area.grid);
|
|
area.$uniqueId = $scope.setUniqueId();
|
|
|
|
//set editor permissions
|
|
if(!area.allowed || area.allowAll === true){
|
|
area.$allowedEditors = $scope.availableEditors;
|
|
area.$allowsRTE = true;
|
|
}else{
|
|
area.$allowedEditors = _.filter($scope.availableEditors, function(editor){
|
|
return _.indexOf(area.allowed, editor.alias) >= 0;
|
|
});
|
|
|
|
if(_.indexOf(area.allowed,"rte")>=0){
|
|
area.$allowsRTE = true;
|
|
}
|
|
}
|
|
});
|
|
|
|
//replace the old row
|
|
original.$initialized = true;
|
|
|
|
//set a disposable unique ID
|
|
original.$uniqueId = $scope.setUniqueId();
|
|
|
|
//set a no disposable unique ID (util for row styling)
|
|
original.id = !row.id ? $scope.setUniqueId() : row.id;
|
|
|
|
return original;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// *********************************************
|
|
// Init control
|
|
// *********************************************
|
|
|
|
$scope.initControl = function(control, index){
|
|
control.$index = index;
|
|
control.$uniqueId = $scope.setUniqueId();
|
|
|
|
if(!control.$editorPath){
|
|
//if its a path
|
|
if(_.indexOf(control.editor.view, "/") >= 0){
|
|
control.$editorPath = control.editor.view;
|
|
}else{
|
|
//use convention
|
|
control.$editorPath = "views/propertyeditors/grid/editors/" + control.editor.view + ".html";
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
gridService.getGridEditors().then(function(response){
|
|
$scope.availableEditors = response.data;
|
|
|
|
$scope.contentReady = true;
|
|
|
|
// *********************************************
|
|
// Init grid
|
|
// *********************************************
|
|
$scope.initContent();
|
|
|
|
});
|
|
});
|