mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
#21240: Layouts/DynamicForms: switch to Angular "inline array" DI annotation
Work Item: 21240
This commit is contained in:

committed by
Sipke Schoorstra

parent
8101542d9e
commit
6e7d82bd29
@@ -1,28 +1,30 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutForm", function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
if (args.cancel)
|
||||
return;
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.name = args.elementEditorModel.name;
|
||||
$scope.element.formBindingContentType = args.elementEditorModel.formBindingContentType;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Form"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutForm", ["$compile", "scopeConfigurator", "environment",
|
||||
function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
if (args.cancel)
|
||||
return;
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.name = args.elementEditorModel.name;
|
||||
$scope.element.formBindingContentType = args.elementEditorModel.formBindingContentType;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Form"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
||||
var LayoutEditor;
|
||||
(function ($, LayoutEditor) {
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<!--Determines if the bundle file should be automatically optimized after creation/update.-->
|
||||
<minify>true</minify>
|
||||
<!--Determine whether to generate/re-generate this bundle on building the solution.-->
|
||||
<runOnBuild>false</runOnBuild>
|
||||
<runOnBuild>true</runOnBuild>
|
||||
<!--Specifies a custom subfolder to save files to. By default, compiled output will be placed in the same folder and nested under the original file.-->
|
||||
<outputDirectory />
|
||||
</settings>
|
||||
|
@@ -1 +1 @@
|
||||
angular.module("LayoutEditor").directive("orcLayoutForm",function(n,t,i){return{restrict:"E",scope:{element:"="},controller:function(n,i){t.configureForElement(n,i);t.configureForContainer(n,i);n.sortableOptions.axis="y";n.edit=function(){n.$root.editElement(n.element).then(function(t){t.cancel||(n.element.data=decodeURIComponent(t.element.data),n.element.name=t.elementEditorModel.name,n.element.formBindingContentType=t.elementEditorModel.formBindingContentType,n.$apply())})}},templateUrl:i.templateUrl("Form"),replace:!0}});var LayoutEditor;(function(n,t){t.Form=function(i,r,u,f,e,o,s,h,c,l,a,v){var y,p;t.Element.call(this,"Form",i,r,u,f,e);t.Container.call(this,["Grid","Content"],v);y=this;this.isContainable=!0;this.dropTargetClass="layout-common-holder";this.contentType=h;this.contentTypeLabel=c;this.contentTypeClass=l;this.name=o||"Untitled";this.formBindingContentType=s;this.hasEditor=a;this.toObject=function(){var n=this.elementToObject();return n.name=this.name,n.formBindingContentType=this.formBindingContentType,n.children=this.childrenToObject(),n};p=this.getEditorObject;this.getEditorObject=function(){var t=p();return n.extend(t,{FormName:this.name,FormBindingContentType:this.formBindingContentType})};this.setChildren=function(n){this.children=n;_(this.children).each(function(n){n.parent=y;y.linkChild(n)})};this.linkChild=function(t){var i=t.getEditorObject;t.getEditorObject=function(){var t=i();return n.extend(t,{FormBindingContentType:y.formBindingContentType})}};this.setChildren(v)};t.Form.from=function(n){return new t.Form(n.data,n.htmlId,n.htmlClass,n.htmlStyle,n.isTemplated,n.name,n.formBindingContentType,n.contentType,n.contentTypeLabel,n.contentTypeClass,n.hasEditor,t.childrenFrom(n.children))};t.registerFactory("Form",function(n){return t.Form.from(n)})})(jQuery,LayoutEditor||(LayoutEditor={}));
|
||||
angular.module("LayoutEditor").directive("orcLayoutForm",["$compile","scopeConfigurator","environment",function(n,t,i){return{restrict:"E",scope:{element:"="},controller:function(n,i){t.configureForElement(n,i);t.configureForContainer(n,i);n.sortableOptions.axis="y";n.edit=function(){n.$root.editElement(n.element).then(function(t){t.cancel||(n.element.data=decodeURIComponent(t.element.data),n.element.name=t.elementEditorModel.name,n.element.formBindingContentType=t.elementEditorModel.formBindingContentType,n.$apply())})}},templateUrl:i.templateUrl("Form"),replace:!0}}]);var LayoutEditor;(function(n,t){t.Form=function(i,r,u,f,e,o,s,h,c,l,a,v){var y,p;t.Element.call(this,"Form",i,r,u,f,e);t.Container.call(this,["Grid","Content"],v);y=this;this.isContainable=!0;this.dropTargetClass="layout-common-holder";this.contentType=h;this.contentTypeLabel=c;this.contentTypeClass=l;this.name=o||"Untitled";this.formBindingContentType=s;this.hasEditor=a;this.toObject=function(){var n=this.elementToObject();return n.name=this.name,n.formBindingContentType=this.formBindingContentType,n.children=this.childrenToObject(),n};p=this.getEditorObject;this.getEditorObject=function(){var t=p();return n.extend(t,{FormName:this.name,FormBindingContentType:this.formBindingContentType})};this.setChildren=function(n){this.children=n;_(this.children).each(function(n){n.parent=y;y.linkChild(n)})};this.linkChild=function(t){var i=t.getEditorObject;t.getEditorObject=function(){var t=i();return n.extend(t,{FormBindingContentType:y.formBindingContentType})}};this.setChildren(v)};t.Form.from=function(n){return new t.Form(n.data,n.htmlId,n.htmlClass,n.htmlStyle,n.isTemplated,n.name,n.formBindingContentType,n.contentType,n.contentTypeLabel,n.contentTypeClass,n.hasEditor,t.childrenFrom(n.children))};t.registerFactory("Form",function(n){return t.Form.from(n)})})(jQuery,LayoutEditor||(LayoutEditor={}));
|
@@ -1,25 +1,27 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutForm", function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
if (args.cancel)
|
||||
return;
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.name = args.elementEditorModel.name;
|
||||
$scope.element.formBindingContentType = args.elementEditorModel.formBindingContentType;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Form"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutForm", ["$compile", "scopeConfigurator", "environment",
|
||||
function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
if (args.cancel)
|
||||
return;
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.name = args.elementEditorModel.name;
|
||||
$scope.element.formBindingContentType = args.elementEditorModel.formBindingContentType;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Form"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -9,9 +9,8 @@ namespace Orchard.Layouts {
|
||||
manifest.DefineScript("AngularSanitize").SetUrl("Lib/angular-sanitize.js").SetDependencies("Angular");
|
||||
manifest.DefineScript("AngularResource").SetUrl("Lib/angular-resource.js").SetDependencies("Angular");
|
||||
manifest.DefineScript("Layouts.Models").SetUrl("Models.min.js", "Models.js").SetDependencies("jQuery", "Underscore");
|
||||
|
||||
// For some reason the minified version doesn't work and causes AngularJS to complain about some directive not being found, so we're only registering the debug version of LayoutEditor.js.
|
||||
manifest.DefineScript("Layouts.LayoutEditor").SetUrl(/*"LayoutEditor.min.js",*/ "LayoutEditor.js").SetDependencies("Layouts.Models", "AngularResource", "AngularSanitize", "Angular", "jQuery", "Underscore");
|
||||
|
||||
manifest.DefineScript("Layouts.LayoutEditor").SetUrl("LayoutEditor.min.js", "LayoutEditor.js").SetDependencies("Layouts.Models", "AngularResource", "AngularSanitize", "Angular", "jQuery", "Underscore");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,15 +1,17 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutCanvas", function (scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element, $attrs) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Canvas"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutCanvas", ["scopeConfigurator", "environment",
|
||||
function (scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element, $attrs) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Canvas"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,13 +1,15 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutChild", function ($compile) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
link: function (scope, element) {
|
||||
var template = "<orc-layout-" + scope.element.type.toLowerCase() + " element='element' />";
|
||||
var html = $compile(template)(scope);
|
||||
$(element).replaceWith(html);
|
||||
}
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutChild", ["$compile",
|
||||
function ($compile) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
link: function (scope, element) {
|
||||
var template = "<orc-layout-" + scope.element.type.toLowerCase() + " element='element' />";
|
||||
var html = $compile(template)(scope);
|
||||
$(element).replaceWith(html);
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,64 +1,66 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutColumn", function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Column"),
|
||||
replace: true,
|
||||
link: function (scope, element, attrs) {
|
||||
element.find(".layout-column-resize-bar").draggable({
|
||||
axis: "x",
|
||||
helper: "clone",
|
||||
revert: true,
|
||||
start: function (e, ui) {
|
||||
scope.$apply(function () {
|
||||
scope.element.editor.isResizing = true;
|
||||
});
|
||||
},
|
||||
drag: function (e, ui) {
|
||||
var columnElement = element.parent();
|
||||
var columnSize = columnElement.width() / scope.element.width;
|
||||
var connectAdjacent = !e.ctrlKey;
|
||||
if ($(e.target).hasClass("layout-column-resize-bar-left")) {
|
||||
var delta = ui.offset.left - columnElement.offset().left;
|
||||
if (delta < -columnSize && scope.element.canExpandLeft(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.expandLeft(connectAdjacent);
|
||||
});
|
||||
.directive("orcLayoutColumn", ["$compile", "scopeConfigurator", "environment",
|
||||
function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Column"),
|
||||
replace: true,
|
||||
link: function (scope, element, attrs) {
|
||||
element.find(".layout-column-resize-bar").draggable({
|
||||
axis: "x",
|
||||
helper: "clone",
|
||||
revert: true,
|
||||
start: function (e, ui) {
|
||||
scope.$apply(function () {
|
||||
scope.element.editor.isResizing = true;
|
||||
});
|
||||
},
|
||||
drag: function (e, ui) {
|
||||
var columnElement = element.parent();
|
||||
var columnSize = columnElement.width() / scope.element.width;
|
||||
var connectAdjacent = !e.ctrlKey;
|
||||
if ($(e.target).hasClass("layout-column-resize-bar-left")) {
|
||||
var delta = ui.offset.left - columnElement.offset().left;
|
||||
if (delta < -columnSize && scope.element.canExpandLeft(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.expandLeft(connectAdjacent);
|
||||
});
|
||||
}
|
||||
else if (delta > columnSize && scope.element.canContractLeft(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.contractLeft(connectAdjacent);
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (delta > columnSize && scope.element.canContractLeft(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.contractLeft(connectAdjacent);
|
||||
});
|
||||
else if ($(e.target).hasClass("layout-column-resize-bar-right")) {
|
||||
var delta = ui.offset.left - columnElement.width() - columnElement.offset().left;
|
||||
if (delta > columnSize && scope.element.canExpandRight(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.expandRight(connectAdjacent);
|
||||
});
|
||||
}
|
||||
else if (delta < -columnSize && scope.element.canContractRight(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.contractRight(connectAdjacent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($(e.target).hasClass("layout-column-resize-bar-right")) {
|
||||
var delta = ui.offset.left - columnElement.width() - columnElement.offset().left;
|
||||
if (delta > columnSize && scope.element.canExpandRight(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.expandRight(connectAdjacent);
|
||||
});
|
||||
}
|
||||
else if (delta < -columnSize && scope.element.canContractRight(connectAdjacent)) {
|
||||
scope.$apply(function () {
|
||||
scope.element.contractRight(connectAdjacent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
scope.$apply(function () {
|
||||
scope.element.editor.isResizing = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
scope.$apply(function () {
|
||||
scope.element.editor.isResizing = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,44 +1,46 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutContent", function ($sce, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
$scope.$apply(function () {
|
||||
if (args.cancel)
|
||||
return;
|
||||
.directive("orcLayoutContent", ["$sce", "scopeConfigurator", "environment",
|
||||
function ($sce, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
$scope.$apply(function () {
|
||||
if (args.cancel)
|
||||
return;
|
||||
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.setHtml(decodeURIComponent(args.element.html.replace(/\+/g, "%20")));
|
||||
$scope.element.data = decodeURIComponent(args.element.data);
|
||||
$scope.element.setHtml(decodeURIComponent(args.element.html.replace(/\+/g, "%20")));
|
||||
});
|
||||
});
|
||||
};
|
||||
$scope.updateContent = function (e) {
|
||||
$scope.element.setHtml(e.target.innerHTML);
|
||||
};
|
||||
|
||||
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
|
||||
$scope.element.setHtml = function (html) {
|
||||
$scope.element.html = html;
|
||||
$scope.element.htmlUnsafe = $sce.trustAsHtml(html);
|
||||
};
|
||||
|
||||
$scope.element.setHtml(decodeURIComponent($scope.element.html.replace(/\+/g, "%20")));
|
||||
},
|
||||
templateUrl: environment.templateUrl("Content"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
|
||||
// otherwise clicks in inline editors will have no effect.
|
||||
element.find(".layout-content-markup").mousedown(function (e) {
|
||||
if (scope.element.editor.inlineEditingIsActive) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.updateContent = function (e) {
|
||||
$scope.element.setHtml(e.target.innerHTML);
|
||||
};
|
||||
|
||||
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
|
||||
$scope.element.setHtml = function (html) {
|
||||
$scope.element.html = html;
|
||||
$scope.element.htmlUnsafe = $sce.trustAsHtml(html);
|
||||
};
|
||||
|
||||
$scope.element.setHtml(decodeURIComponent($scope.element.html.replace(/\+/g, "%20")));
|
||||
},
|
||||
templateUrl: environment.templateUrl("Content"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
|
||||
// otherwise clicks in inline editors will have no effect.
|
||||
element.find(".layout-content-markup").mousedown(function (e) {
|
||||
if (scope.element.editor.inlineEditingIsActive) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,172 +1,174 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutEditor", function (environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: {},
|
||||
controller: function ($scope, $element, $attrs, $compile, clipboard) {
|
||||
if (!!$attrs.model)
|
||||
$scope.element = eval($attrs.model);
|
||||
else
|
||||
throw new Error("The 'model' attribute must evaluate to a LayoutEditor.Editor object.");
|
||||
.directive("orcLayoutEditor", ["environment",
|
||||
function (environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: {},
|
||||
controller: function ($scope, $element, $attrs, $compile, clipboard) {
|
||||
if (!!$attrs.model)
|
||||
$scope.element = eval($attrs.model);
|
||||
else
|
||||
throw new Error("The 'model' attribute must evaluate to a LayoutEditor.Editor object.");
|
||||
|
||||
$scope.click = function (canvas, e) {
|
||||
if (!canvas.editor.isDragging)
|
||||
canvas.setIsFocused();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
$scope.getClasses = function (canvas) {
|
||||
var result = ["layout-element", "layout-container", "layout-canvas"];
|
||||
|
||||
if (canvas.getIsActive())
|
||||
result.push("layout-element-active");
|
||||
if (canvas.getIsFocused())
|
||||
result.push("layout-element-focused");
|
||||
if (canvas.getIsSelected())
|
||||
result.push("layout-element-selected");
|
||||
if (canvas.getIsDropTarget())
|
||||
result.push("layout-element-droptarget");
|
||||
if (canvas.isTemplated)
|
||||
result.push("layout-element-templated");
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// An unfortunate side-effect of the next hack on line 54 is that the created elements aren't added to the DOM yet, so we can't use it to get to the parent ".layout-desiger" element.
|
||||
// Work around: access that element directly (which efectively turns multiple layout editors on a single page impossible).
|
||||
// //var layoutDesignerHost = $element.closest(".layout-designer").data("layout-designer-host");
|
||||
var layoutDesignerHost = $(".layout-designer").data("layout-designer-host");
|
||||
|
||||
$scope.$root.layoutDesignerHost = layoutDesignerHost;
|
||||
|
||||
layoutDesignerHost.element.on("replacecanvas", function (e, args) {
|
||||
var editor = $scope.element;
|
||||
var canvasData = {
|
||||
data: args.canvas.data,
|
||||
htmlId: args.canvas.htmlId,
|
||||
htmlClass: args.canvas.htmlClass,
|
||||
htmlStyle: args.canvas.htmlStyle,
|
||||
isTemplated: args.canvas.isTemplated,
|
||||
children: args.canvas.children
|
||||
$scope.click = function (canvas, e) {
|
||||
if (!canvas.editor.isDragging)
|
||||
canvas.setIsFocused();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// HACK: Instead of simply updating the $scope.element with a new instance, we need to replace the entire orc-layout-editor markup
|
||||
// in order for angular to rebind starting with the Canvas element. Otherwise, for some reason, it will rebind starting with the first child of Canvas.
|
||||
// You can see this happening when setting a breakpoint in ScopeConfigurator where containers are initialized with drag & drop: on page load, the first element
|
||||
// is a Canvas (good), but after having selected another template, the first element is (typically) a Grid (bad).
|
||||
// Simply recompiling the orc-layout-editor directive will cause the entire thing to be generated, which works just fine as well (even though not is nice as simply leveraging model binding).
|
||||
layoutDesignerHost.editor = window.layoutEditor = new LayoutEditor.Editor(editor.config, canvasData);
|
||||
var template = "<orc-layout-editor" + " model='window.layoutEditor' />";
|
||||
var html = $compile(template)($scope);
|
||||
$(".layout-editor-holder").html(html);
|
||||
});
|
||||
$scope.getClasses = function (canvas) {
|
||||
var result = ["layout-element", "layout-container", "layout-canvas"];
|
||||
|
||||
$scope.$root.editElement = function (element) {
|
||||
var host = $scope.$root.layoutDesignerHost;
|
||||
return host.editElement(element);
|
||||
};
|
||||
if (canvas.getIsActive())
|
||||
result.push("layout-element-active");
|
||||
if (canvas.getIsFocused())
|
||||
result.push("layout-element-focused");
|
||||
if (canvas.getIsSelected())
|
||||
result.push("layout-element-selected");
|
||||
if (canvas.getIsDropTarget())
|
||||
result.push("layout-element-droptarget");
|
||||
if (canvas.isTemplated)
|
||||
result.push("layout-element-templated");
|
||||
|
||||
$scope.$root.addElement = function (contentType) {
|
||||
var host = $scope.$root.layoutDesignerHost;
|
||||
return host.addElement(contentType);
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
$scope.toggleInlineEditing = function () {
|
||||
if (!$scope.element.inlineEditingIsActive) {
|
||||
$scope.element.inlineEditingIsActive = true;
|
||||
$element.find(".layout-toolbar-container").show();
|
||||
var selector = "#layout-editor-" + $scope.$id + " .layout-content-h-t-m-l .layout-content-markup[data-templated=false]";
|
||||
var firstContentEditorId = $(selector).first().attr("id");
|
||||
tinymce.init({
|
||||
selector: selector,
|
||||
theme: "modern",
|
||||
schema: "html5",
|
||||
plugins: [
|
||||
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
|
||||
"searchreplace wordcount visualblocks visualchars code fullscreen",
|
||||
"insertdatetime media nonbreaking table contextmenu directionality",
|
||||
"emoticons template paste textcolor colorpicker textpattern",
|
||||
"fullscreen autoresize"
|
||||
],
|
||||
toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close",
|
||||
convert_urls: false,
|
||||
valid_elements: "*[*]",
|
||||
// Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it.
|
||||
extended_valid_elements: "script[type|defer|src|language]",
|
||||
statusbar: false,
|
||||
skin: "orchardlightgray",
|
||||
inline: true,
|
||||
fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container",
|
||||
init_instance_callback: function (editor) {
|
||||
if (editor.id == firstContentEditorId)
|
||||
tinymce.execCommand("mceFocus", false, editor.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup");
|
||||
$element.find(".layout-toolbar-container").hide();
|
||||
$scope.element.inlineEditingIsActive = false;
|
||||
}
|
||||
};
|
||||
// An unfortunate side-effect of the next hack on line 54 is that the created elements aren't added to the DOM yet, so we can't use it to get to the parent ".layout-desiger" element.
|
||||
// Work around: access that element directly (which efectively turns multiple layout editors on a single page impossible).
|
||||
// //var layoutDesignerHost = $element.closest(".layout-designer").data("layout-designer-host");
|
||||
var layoutDesignerHost = $(".layout-designer").data("layout-designer-host");
|
||||
|
||||
$(document).on("cut copy paste", function (e) {
|
||||
// The real clipboard is supported, so disable the peudo clipboard.
|
||||
clipboard.disable();
|
||||
var focusedElement = $scope.element.focusedElement;
|
||||
if (!!focusedElement) {
|
||||
$scope.$apply(function () {
|
||||
switch (e.type) {
|
||||
case "copy":
|
||||
focusedElement.copy(e.originalEvent.clipboardData);
|
||||
break;
|
||||
case "cut":
|
||||
focusedElement.cut(e.originalEvent.clipboardData);
|
||||
break;
|
||||
case "paste":
|
||||
focusedElement.paste(e.originalEvent.clipboardData);
|
||||
break;
|
||||
}
|
||||
});
|
||||
$scope.$root.layoutDesignerHost = layoutDesignerHost;
|
||||
|
||||
// HACK: Workaround because of how Angular treats the DOM when elements are shifted around - input focus is sometimes lost.
|
||||
window.setTimeout(function () {
|
||||
$scope.$apply(function () {
|
||||
if (!!$scope.element.focusedElement)
|
||||
$scope.element.focusedElement.setIsFocused();
|
||||
layoutDesignerHost.element.on("replacecanvas", function (e, args) {
|
||||
var editor = $scope.element;
|
||||
var canvasData = {
|
||||
data: args.canvas.data,
|
||||
htmlId: args.canvas.htmlId,
|
||||
htmlClass: args.canvas.htmlClass,
|
||||
htmlStyle: args.canvas.htmlStyle,
|
||||
isTemplated: args.canvas.isTemplated,
|
||||
children: args.canvas.children
|
||||
};
|
||||
|
||||
// HACK: Instead of simply updating the $scope.element with a new instance, we need to replace the entire orc-layout-editor markup
|
||||
// in order for angular to rebind starting with the Canvas element. Otherwise, for some reason, it will rebind starting with the first child of Canvas.
|
||||
// You can see this happening when setting a breakpoint in ScopeConfigurator where containers are initialized with drag & drop: on page load, the first element
|
||||
// is a Canvas (good), but after having selected another template, the first element is (typically) a Grid (bad).
|
||||
// Simply recompiling the orc-layout-editor directive will cause the entire thing to be generated, which works just fine as well (even though not is nice as simply leveraging model binding).
|
||||
layoutDesignerHost.editor = window.layoutEditor = new LayoutEditor.Editor(editor.config, canvasData);
|
||||
var template = "<orc-layout-editor" + " model='window.layoutEditor' />";
|
||||
var html = $compile(template)($scope);
|
||||
$(".layout-editor-holder").html(html);
|
||||
});
|
||||
|
||||
$scope.$root.editElement = function (element) {
|
||||
var host = $scope.$root.layoutDesignerHost;
|
||||
return host.editElement(element);
|
||||
};
|
||||
|
||||
$scope.$root.addElement = function (contentType) {
|
||||
var host = $scope.$root.layoutDesignerHost;
|
||||
return host.addElement(contentType);
|
||||
};
|
||||
|
||||
$scope.toggleInlineEditing = function () {
|
||||
if (!$scope.element.inlineEditingIsActive) {
|
||||
$scope.element.inlineEditingIsActive = true;
|
||||
$element.find(".layout-toolbar-container").show();
|
||||
var selector = "#layout-editor-" + $scope.$id + " .layout-content-h-t-m-l .layout-content-markup[data-templated=false]";
|
||||
var firstContentEditorId = $(selector).first().attr("id");
|
||||
tinymce.init({
|
||||
selector: selector,
|
||||
theme: "modern",
|
||||
schema: "html5",
|
||||
plugins: [
|
||||
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
|
||||
"searchreplace wordcount visualblocks visualchars code fullscreen",
|
||||
"insertdatetime media nonbreaking table contextmenu directionality",
|
||||
"emoticons template paste textcolor colorpicker textpattern",
|
||||
"fullscreen autoresize"
|
||||
],
|
||||
toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close",
|
||||
convert_urls: false,
|
||||
valid_elements: "*[*]",
|
||||
// Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it.
|
||||
extended_valid_elements: "script[type|defer|src|language]",
|
||||
statusbar: false,
|
||||
skin: "orchardlightgray",
|
||||
inline: true,
|
||||
fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container",
|
||||
init_instance_callback: function (editor) {
|
||||
if (editor.id == firstContentEditorId)
|
||||
tinymce.execCommand("mceFocus", false, editor.id);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
else {
|
||||
tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup");
|
||||
$element.find(".layout-toolbar-container").hide();
|
||||
$scope.element.inlineEditingIsActive = false;
|
||||
}
|
||||
};
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
templateUrl: environment.templateUrl("Editor"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// No clicks should propagate from the TinyMCE toolbars.
|
||||
element.find(".layout-toolbar-container").click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
// Intercept mousedown on editor while in inline editing mode to
|
||||
// prevent current editor from losing focus.
|
||||
element.mousedown(function (e) {
|
||||
if (scope.element.inlineEditingIsActive) {
|
||||
e.preventDefault();
|
||||
$(document).on("cut copy paste", function (e) {
|
||||
// The real clipboard is supported, so disable the peudo clipboard.
|
||||
clipboard.disable();
|
||||
var focusedElement = $scope.element.focusedElement;
|
||||
if (!!focusedElement) {
|
||||
$scope.$apply(function () {
|
||||
switch (e.type) {
|
||||
case "copy":
|
||||
focusedElement.copy(e.originalEvent.clipboardData);
|
||||
break;
|
||||
case "cut":
|
||||
focusedElement.cut(e.originalEvent.clipboardData);
|
||||
break;
|
||||
case "paste":
|
||||
focusedElement.paste(e.originalEvent.clipboardData);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// HACK: Workaround because of how Angular treats the DOM when elements are shifted around - input focus is sometimes lost.
|
||||
window.setTimeout(function () {
|
||||
$scope.$apply(function () {
|
||||
if (!!$scope.element.focusedElement)
|
||||
$scope.element.focusedElement.setIsFocused();
|
||||
});
|
||||
}, 100);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
templateUrl: environment.templateUrl("Editor"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// No clicks should propagate from the TinyMCE toolbars.
|
||||
element.find(".layout-toolbar-container").click(function (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
})
|
||||
// Unfocus and unselect everything on click outside of canvas.
|
||||
$(window).click(function (e) {
|
||||
// Except when in inline editing mode.
|
||||
if (!scope.element.inlineEditingIsActive) {
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
// Intercept mousedown on editor while in inline editing mode to
|
||||
// prevent current editor from losing focus.
|
||||
element.mousedown(function (e) {
|
||||
if (scope.element.inlineEditingIsActive) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
})
|
||||
// Unfocus and unselect everything on click outside of canvas.
|
||||
$(window).click(function (e) {
|
||||
// Except when in inline editing mode.
|
||||
if (!scope.element.inlineEditingIsActive) {
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,15 +1,17 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutGrid", function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Grid"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutGrid", ["$compile", "scopeConfigurator", "environment",
|
||||
function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "y";
|
||||
},
|
||||
templateUrl: environment.templateUrl("Grid"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,34 +1,36 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutPopup", function () {
|
||||
return {
|
||||
restrict: "A",
|
||||
link: function (scope, element, attrs) {
|
||||
var popup = $(element);
|
||||
var trigger = popup.closest(".layout-popup-trigger");
|
||||
var parentElement = popup.closest(".layout-element");
|
||||
trigger.click(function () {
|
||||
popup.toggle();
|
||||
if (popup.is(":visible")) {
|
||||
popup.position({
|
||||
my: attrs.orcLayoutPopupMy || "left top",
|
||||
at: attrs.orcLayoutPopupAt || "left bottom+4px",
|
||||
of: trigger
|
||||
});
|
||||
popup.find("input").first().focus();
|
||||
}
|
||||
});
|
||||
popup.click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
parentElement.click(function (e) {
|
||||
popup.hide();
|
||||
});
|
||||
popup.keydown(function (e) {
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 27) // Esc
|
||||
.directive("orcLayoutPopup", [
|
||||
function () {
|
||||
return {
|
||||
restrict: "A",
|
||||
link: function (scope, element, attrs) {
|
||||
var popup = $(element);
|
||||
var trigger = popup.closest(".layout-popup-trigger");
|
||||
var parentElement = popup.closest(".layout-element");
|
||||
trigger.click(function () {
|
||||
popup.toggle();
|
||||
if (popup.is(":visible")) {
|
||||
popup.position({
|
||||
my: attrs.orcLayoutPopupMy || "left top",
|
||||
at: attrs.orcLayoutPopupAt || "left bottom+4px",
|
||||
of: trigger
|
||||
});
|
||||
popup.find("input").first().focus();
|
||||
}
|
||||
});
|
||||
popup.click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
parentElement.click(function (e) {
|
||||
popup.hide();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
popup.keydown(function (e) {
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 27) // Esc
|
||||
popup.hide();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,16 +1,18 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutRow", function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "x";
|
||||
$scope.sortableOptions["ui-floating"] = true;
|
||||
},
|
||||
templateUrl: environment.templateUrl("Row"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutRow", ["$compile", "scopeConfigurator", "environment",
|
||||
function ($compile, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
scopeConfigurator.configureForContainer($scope, $element);
|
||||
$scope.sortableOptions["axis"] = "x";
|
||||
$scope.sortableOptions["ui-floating"] = true;
|
||||
},
|
||||
templateUrl: environment.templateUrl("Row"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,168 +1,170 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutToolbox", function ($compile, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
controller: function ($scope, $element) {
|
||||
.directive("orcLayoutToolbox", ["$compile", "environment",
|
||||
function ($compile, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
controller: function ($scope, $element) {
|
||||
|
||||
$scope.resetElements = function () {
|
||||
$scope.resetElements = function () {
|
||||
|
||||
$scope.gridElements = [
|
||||
LayoutEditor.Grid.from({
|
||||
toolboxIcon: "\uf00a",
|
||||
toolboxLabel: "Grid",
|
||||
toolboxDescription: "Empty grid.",
|
||||
children: []
|
||||
})
|
||||
];
|
||||
|
||||
$scope.rowElements = [
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (1 column)",
|
||||
toolboxDescription: "Row with 1 column.",
|
||||
children: LayoutEditor.Column.times(1)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (2 columns)",
|
||||
toolboxDescription: "Row with 2 columns.",
|
||||
children: LayoutEditor.Column.times(2)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (3 columns)",
|
||||
toolboxDescription: "Row with 3 columns.",
|
||||
children: LayoutEditor.Column.times(3)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (4 columns)",
|
||||
toolboxDescription: "Row with 4 columns.",
|
||||
children: LayoutEditor.Column.times(4)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (6 columns)",
|
||||
toolboxDescription: "Row with 6 columns.",
|
||||
children: LayoutEditor.Column.times(6)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (12 columns)",
|
||||
toolboxDescription: "Row with 12 columns.",
|
||||
children: LayoutEditor.Column.times(12)
|
||||
}), LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (empty)",
|
||||
toolboxDescription: "Empty row.",
|
||||
children: []
|
||||
})
|
||||
];
|
||||
|
||||
$scope.columnElements = [
|
||||
LayoutEditor.Column.from({
|
||||
toolboxIcon: "\uf0db",
|
||||
toolboxLabel: "Column",
|
||||
toolboxDescription: "Empty column.",
|
||||
width: 1,
|
||||
offset: 0,
|
||||
children: []
|
||||
})
|
||||
];
|
||||
|
||||
$scope.contentElementCategories = _($scope.element.config.categories).map(function (category) {
|
||||
return {
|
||||
name: category.name,
|
||||
elements: _(category.contentTypes).map(function (contentType) {
|
||||
var type = contentType.type;
|
||||
var factory = LayoutEditor.factories[type] || LayoutEditor.factories["Content"];
|
||||
var item = {
|
||||
isTemplated: false,
|
||||
contentType: contentType.id,
|
||||
contentTypeLabel: contentType.label,
|
||||
contentTypeClass: contentType.typeClass,
|
||||
data: null,
|
||||
hasEditor: contentType.hasEditor,
|
||||
html: contentType.html
|
||||
};
|
||||
var element = factory(item);
|
||||
element.toolboxIcon = contentType.icon || "\uf1c9";
|
||||
element.toolboxLabel = contentType.label;
|
||||
element.toolboxDescription = contentType.description;
|
||||
return element;
|
||||
$scope.gridElements = [
|
||||
LayoutEditor.Grid.from({
|
||||
toolboxIcon: "\uf00a",
|
||||
toolboxLabel: "Grid",
|
||||
toolboxDescription: "Empty grid.",
|
||||
children: []
|
||||
})
|
||||
};
|
||||
});
|
||||
];
|
||||
|
||||
};
|
||||
$scope.rowElements = [
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (1 column)",
|
||||
toolboxDescription: "Row with 1 column.",
|
||||
children: LayoutEditor.Column.times(1)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (2 columns)",
|
||||
toolboxDescription: "Row with 2 columns.",
|
||||
children: LayoutEditor.Column.times(2)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (3 columns)",
|
||||
toolboxDescription: "Row with 3 columns.",
|
||||
children: LayoutEditor.Column.times(3)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (4 columns)",
|
||||
toolboxDescription: "Row with 4 columns.",
|
||||
children: LayoutEditor.Column.times(4)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (6 columns)",
|
||||
toolboxDescription: "Row with 6 columns.",
|
||||
children: LayoutEditor.Column.times(6)
|
||||
}),
|
||||
LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (12 columns)",
|
||||
toolboxDescription: "Row with 12 columns.",
|
||||
children: LayoutEditor.Column.times(12)
|
||||
}), LayoutEditor.Row.from({
|
||||
toolboxIcon: "\uf0c9",
|
||||
toolboxLabel: "Row (empty)",
|
||||
toolboxDescription: "Empty row.",
|
||||
children: []
|
||||
})
|
||||
];
|
||||
|
||||
$scope.resetElements();
|
||||
$scope.columnElements = [
|
||||
LayoutEditor.Column.from({
|
||||
toolboxIcon: "\uf0db",
|
||||
toolboxLabel: "Column",
|
||||
toolboxDescription: "Empty column.",
|
||||
width: 1,
|
||||
offset: 0,
|
||||
children: []
|
||||
})
|
||||
];
|
||||
|
||||
$scope.getSortableOptions = function (type) {
|
||||
var editorId = $element.closest(".layout-editor").attr("id");
|
||||
var parentClasses;
|
||||
var placeholderClasses;
|
||||
var floating = false;
|
||||
$scope.contentElementCategories = _($scope.element.config.categories).map(function (category) {
|
||||
return {
|
||||
name: category.name,
|
||||
elements: _(category.contentTypes).map(function (contentType) {
|
||||
var type = contentType.type;
|
||||
var factory = LayoutEditor.factories[type] || LayoutEditor.factories["Content"];
|
||||
var item = {
|
||||
isTemplated: false,
|
||||
contentType: contentType.id,
|
||||
contentTypeLabel: contentType.label,
|
||||
contentTypeClass: contentType.typeClass,
|
||||
data: null,
|
||||
hasEditor: contentType.hasEditor,
|
||||
html: contentType.html
|
||||
};
|
||||
var element = factory(item);
|
||||
element.toolboxIcon = contentType.icon || "\uf1c9";
|
||||
element.toolboxLabel = contentType.label;
|
||||
element.toolboxDescription = contentType.description;
|
||||
return element;
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
switch (type) {
|
||||
case "Grid":
|
||||
parentClasses = [".layout-canvas", ".layout-column", ".layout-common-holder"];
|
||||
placeholderClasses = "layout-element layout-container layout-grid ui-sortable-placeholder";
|
||||
break;
|
||||
case "Row":
|
||||
parentClasses = [".layout-grid"];
|
||||
placeholderClasses = "layout-element layout-container layout-row row ui-sortable-placeholder";
|
||||
break;
|
||||
case "Column":
|
||||
parentClasses = [".layout-row:not(.layout-row-full)"];
|
||||
placeholderClasses = "layout-element layout-container layout-column ui-sortable-placeholder";
|
||||
floating = true; // To ensure a smooth horizontal-list reordering. https://github.com/angular-ui/ui-sortable#floating
|
||||
break;
|
||||
case "Content":
|
||||
parentClasses = [".layout-canvas", ".layout-column", ".layout-common-holder"];
|
||||
placeholderClasses = "layout-element layout-content ui-sortable-placeholder";
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
cursor: "move",
|
||||
connectWith: _(parentClasses).map(function (e) { return "#" + editorId + " " + e + ":not(.layout-container-sealed) > .layout-element-wrapper > .layout-children"; }).join(", "),
|
||||
placeholder: placeholderClasses,
|
||||
"ui-floating": floating,
|
||||
create: function (e, ui) {
|
||||
e.target.isToolbox = true; // Will indicate to connected sortables that dropped items were sent from toolbox.
|
||||
},
|
||||
start: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.isDragging = true;
|
||||
});
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.isDragging = false;
|
||||
$scope.resetElements();
|
||||
});
|
||||
},
|
||||
over: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.canvas.setIsDropTarget(false);
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
$scope.resetElements();
|
||||
|
||||
var layoutIsCollapsedCookieName = "layoutToolboxCategory_Layout_IsCollapsed";
|
||||
$scope.layoutIsCollapsed = $.cookie(layoutIsCollapsedCookieName) === "true";
|
||||
$scope.getSortableOptions = function (type) {
|
||||
var editorId = $element.closest(".layout-editor").attr("id");
|
||||
var parentClasses;
|
||||
var placeholderClasses;
|
||||
var floating = false;
|
||||
|
||||
$scope.toggleLayoutIsCollapsed = function (e) {
|
||||
$scope.layoutIsCollapsed = !$scope.layoutIsCollapsed;
|
||||
$.cookie(layoutIsCollapsedCookieName, $scope.layoutIsCollapsed, { expires: 365 }); // Remember collapsed state for a year.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Toolbox"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
switch (type) {
|
||||
case "Grid":
|
||||
parentClasses = [".layout-canvas", ".layout-column", ".layout-common-holder"];
|
||||
placeholderClasses = "layout-element layout-container layout-grid ui-sortable-placeholder";
|
||||
break;
|
||||
case "Row":
|
||||
parentClasses = [".layout-grid"];
|
||||
placeholderClasses = "layout-element layout-container layout-row row ui-sortable-placeholder";
|
||||
break;
|
||||
case "Column":
|
||||
parentClasses = [".layout-row:not(.layout-row-full)"];
|
||||
placeholderClasses = "layout-element layout-container layout-column ui-sortable-placeholder";
|
||||
floating = true; // To ensure a smooth horizontal-list reordering. https://github.com/angular-ui/ui-sortable#floating
|
||||
break;
|
||||
case "Content":
|
||||
parentClasses = [".layout-canvas", ".layout-column", ".layout-common-holder"];
|
||||
placeholderClasses = "layout-element layout-content ui-sortable-placeholder";
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
cursor: "move",
|
||||
connectWith: _(parentClasses).map(function (e) { return "#" + editorId + " " + e + ":not(.layout-container-sealed) > .layout-element-wrapper > .layout-children"; }).join(", "),
|
||||
placeholder: placeholderClasses,
|
||||
"ui-floating": floating,
|
||||
create: function (e, ui) {
|
||||
e.target.isToolbox = true; // Will indicate to connected sortables that dropped items were sent from toolbox.
|
||||
},
|
||||
start: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.isDragging = true;
|
||||
});
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.isDragging = false;
|
||||
$scope.resetElements();
|
||||
});
|
||||
},
|
||||
over: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
$scope.element.canvas.setIsDropTarget(false);
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var layoutIsCollapsedCookieName = "layoutToolboxCategory_Layout_IsCollapsed";
|
||||
$scope.layoutIsCollapsed = $.cookie(layoutIsCollapsedCookieName) === "true";
|
||||
|
||||
$scope.toggleLayoutIsCollapsed = function (e) {
|
||||
$scope.layoutIsCollapsed = !$scope.layoutIsCollapsed;
|
||||
$.cookie(layoutIsCollapsedCookieName, $scope.layoutIsCollapsed, { expires: 365 }); // Remember collapsed state for a year.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("Toolbox"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -1,20 +1,22 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutToolboxGroup", function ($compile, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { category: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
var isCollapsedCookieName = "layoutToolboxCategory_" + $scope.category.name + "_IsCollapsed";
|
||||
$scope.isCollapsed = $.cookie(isCollapsedCookieName) === "true";
|
||||
$scope.toggleIsCollapsed = function (e) {
|
||||
$scope.isCollapsed = !$scope.isCollapsed;
|
||||
$.cookie(isCollapsedCookieName, $scope.isCollapsed, { expires: 365 }); // Remember collapsed state for a year.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("ToolboxGroup"),
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
.directive("orcLayoutToolboxGroup", ["$compile", "environment",
|
||||
function ($compile, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { category: "=" },
|
||||
controller: function ($scope, $element) {
|
||||
var isCollapsedCookieName = "layoutToolboxCategory_" + $scope.category.name + "_IsCollapsed";
|
||||
$scope.isCollapsed = $.cookie(isCollapsedCookieName) === "true";
|
||||
$scope.toggleIsCollapsed = function (e) {
|
||||
$scope.isCollapsed = !$scope.isCollapsed;
|
||||
$.cookie(isCollapsedCookieName, $scope.isCollapsed, { expires: 365 }); // Remember collapsed state for a year.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
},
|
||||
templateUrl: environment.templateUrl("ToolboxGroup"),
|
||||
replace: true
|
||||
};
|
||||
}
|
||||
]);
|
@@ -20,11 +20,13 @@
|
||||
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.factory("clipboard", function() {
|
||||
return {
|
||||
setData: LayoutEditor.Clipboard.setData,
|
||||
getData: LayoutEditor.Clipboard.getData,
|
||||
disable: LayoutEditor.Clipboard.disable
|
||||
};
|
||||
});
|
||||
.factory("clipboard", [
|
||||
function() {
|
||||
return {
|
||||
setData: LayoutEditor.Clipboard.setData,
|
||||
getData: LayoutEditor.Clipboard.getData,
|
||||
disable: LayoutEditor.Clipboard.disable
|
||||
};
|
||||
}
|
||||
]);
|
||||
})(LayoutEditor || (LayoutEditor = {}));
|
@@ -1,317 +1,319 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.factory("scopeConfigurator", function ($timeout, clipboard) {
|
||||
return {
|
||||
.factory("scopeConfigurator", ["$timeout", "clipboard",
|
||||
function ($timeout, clipboard) {
|
||||
return {
|
||||
|
||||
configureForElement: function ($scope, $element) {
|
||||
configureForElement: function ($scope, $element) {
|
||||
|
||||
$element.find(".layout-panel").click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
$element.find(".layout-panel").click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$element.parent().keydown(function (e) {
|
||||
var handled = false;
|
||||
var resetFocus = false;
|
||||
var element = $scope.element;
|
||||
$element.parent().keydown(function (e) {
|
||||
var handled = false;
|
||||
var resetFocus = false;
|
||||
var element = $scope.element;
|
||||
|
||||
|
||||
if (element.editor.isDragging || element.editor.inlineEditingIsActive)
|
||||
return;
|
||||
if (element.editor.isDragging || element.editor.inlineEditingIsActive)
|
||||
return;
|
||||
|
||||
// If the "real" clipboard works, then the pseudo-clipboard will have been disabled.
|
||||
if (!clipboard.disabled) {
|
||||
var focusedElement = element.editor.focusedElement;
|
||||
if (!!focusedElement) {
|
||||
// Pseudo clipboard handling for browsers not allowing real clipboard operations.
|
||||
if (e.ctrlKey) {
|
||||
switch (e.which) {
|
||||
case 67: // C
|
||||
focusedElement.copy(clipboard);
|
||||
break;
|
||||
case 88: // X
|
||||
focusedElement.cut(clipboard);
|
||||
break;
|
||||
case 86: // V
|
||||
focusedElement.paste(clipboard);
|
||||
break;
|
||||
// If the "real" clipboard works, then the pseudo-clipboard will have been disabled.
|
||||
if (!clipboard.disabled) {
|
||||
var focusedElement = element.editor.focusedElement;
|
||||
if (!!focusedElement) {
|
||||
// Pseudo clipboard handling for browsers not allowing real clipboard operations.
|
||||
if (e.ctrlKey) {
|
||||
switch (e.which) {
|
||||
case 67: // C
|
||||
focusedElement.copy(clipboard);
|
||||
break;
|
||||
case 88: // X
|
||||
focusedElement.cut(clipboard);
|
||||
break;
|
||||
case 86: // V
|
||||
focusedElement.paste(clipboard);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 46) { // Del
|
||||
$scope.delete(element);
|
||||
handled = true;
|
||||
} else if (!e.ctrlKey && !e.shiftKey && !e.altKey && (e.which == 32 || e.which == 27)) { // Space or Esc
|
||||
$element.find(".layout-panel-action-properties").first().click();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (element.type == "Content") { // This is a content element.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 13) { // Enter
|
||||
$element.find(".layout-panel-action-edit").first().click();
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 46) { // Del
|
||||
$scope.delete(element);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!!element.children) { // This is a container.
|
||||
if (!e.ctrlKey && !e.shiftKey && e.altKey && e.which == 40) { // Alt+Down
|
||||
if (element.children.length > 0)
|
||||
element.children[0].setIsFocused();
|
||||
} else if (!e.ctrlKey && !e.shiftKey && !e.altKey && (e.which == 32 || e.which == 27)) { // Space or Esc
|
||||
$element.find(".layout-panel-action-properties").first().click();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (element.type == "Column") { // This is a column.
|
||||
var connectAdjacent = !e.ctrlKey;
|
||||
if (e.which == 37) { // Left
|
||||
if (e.altKey)
|
||||
element.expandLeft(connectAdjacent);
|
||||
if (e.shiftKey)
|
||||
element.contractRight(connectAdjacent);
|
||||
handled = true;
|
||||
} else if (e.which == 39) { // Right
|
||||
if (e.altKey)
|
||||
element.contractLeft(connectAdjacent);
|
||||
if (e.shiftKey)
|
||||
element.expandRight(connectAdjacent);
|
||||
if (element.type == "Content") { // This is a content element.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 13) { // Enter
|
||||
$element.find(".layout-panel-action-edit").first().click();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!!element.children) { // This is a container.
|
||||
if (!e.ctrlKey && !e.shiftKey && e.altKey && e.which == 40) { // Alt+Down
|
||||
if (element.children.length > 0)
|
||||
element.children[0].setIsFocused();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (element.type == "Column") { // This is a column.
|
||||
var connectAdjacent = !e.ctrlKey;
|
||||
if (e.which == 37) { // Left
|
||||
if (e.altKey)
|
||||
element.expandLeft(connectAdjacent);
|
||||
if (e.shiftKey)
|
||||
element.contractRight(connectAdjacent);
|
||||
handled = true;
|
||||
} else if (e.which == 39) { // Right
|
||||
if (e.altKey)
|
||||
element.contractLeft(connectAdjacent);
|
||||
if (e.shiftKey)
|
||||
element.expandRight(connectAdjacent);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!!element.parent) { // This is a child.
|
||||
if (e.altKey && e.which == 38) { // Alt+Up
|
||||
element.parent.setIsFocused();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (element.parent.type == "Row") { // Parent is a horizontal container.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 37) { // Left
|
||||
element.parent.moveFocusPrevChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 39) { // Right
|
||||
element.parent.moveFocusNextChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 37) { // Ctrl+Left
|
||||
element.moveUp();
|
||||
resetFocus = true;
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 39) { // Ctrl+Right
|
||||
element.moveDown();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else { // Parent is a vertical container.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 38) { // Up
|
||||
element.parent.moveFocusPrevChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 40) { // Down
|
||||
element.parent.moveFocusNextChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 38) { // Ctrl+Up
|
||||
element.moveUp();
|
||||
resetFocus = true;
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 40) { // Ctrl+Down
|
||||
element.moveDown();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
$scope.$apply(); // Event is not triggered by Angular directive but raw event handler on element.
|
||||
|
||||
// HACK: Workaround because of how Angular treats the DOM when elements are shifted around - input focus is sometimes lost.
|
||||
if (resetFocus) {
|
||||
window.setTimeout(function () {
|
||||
$scope.$apply(function () {
|
||||
element.editor.focusedElement.setIsFocused();
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.element.setIsFocusedEventHandlers.push(function () {
|
||||
$element.parent().focus();
|
||||
});
|
||||
|
||||
$scope.delete = function (element) {
|
||||
element.delete();
|
||||
}
|
||||
},
|
||||
|
||||
if (!!element.parent) { // This is a child.
|
||||
if (e.altKey && e.which == 38) { // Alt+Up
|
||||
element.parent.setIsFocused();
|
||||
handled = true;
|
||||
}
|
||||
configureForContainer: function ($scope, $element) {
|
||||
var element = $scope.element;
|
||||
|
||||
if (element.parent.type == "Row") { // Parent is a horizontal container.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 37) { // Left
|
||||
element.parent.moveFocusPrevChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 39) { // Right
|
||||
element.parent.moveFocusNextChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 37) { // Ctrl+Left
|
||||
element.moveUp();
|
||||
resetFocus = true;
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 39) { // Ctrl+Right
|
||||
element.moveDown();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else { // Parent is a vertical container.
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 38) { // Up
|
||||
element.parent.moveFocusPrevChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (!e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 40) { // Down
|
||||
element.parent.moveFocusNextChild(element);
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 38) { // Ctrl+Up
|
||||
element.moveUp();
|
||||
resetFocus = true;
|
||||
handled = true;
|
||||
}
|
||||
else if (e.ctrlKey && !e.shiftKey && !e.altKey && e.which == 40) { // Ctrl+Down
|
||||
element.moveDown();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//$scope.isReceiving = false; // True when container is receiving an external element via drag/drop.
|
||||
$scope.getShowChildrenPlaceholder = function () {
|
||||
return $scope.element.children.length === 0 && !$scope.element.getIsDropTarget();
|
||||
};
|
||||
|
||||
if (handled) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
$scope.$apply(); // Event is not triggered by Angular directive but raw event handler on element.
|
||||
|
||||
// HACK: Workaround because of how Angular treats the DOM when elements are shifted around - input focus is sometimes lost.
|
||||
if (resetFocus) {
|
||||
window.setTimeout(function () {
|
||||
$scope.sortableOptions = {
|
||||
cursor: "move",
|
||||
delay: 150,
|
||||
disabled: element.getIsSealed(),
|
||||
distance: 5,
|
||||
//handle: element.children.length < 2 ? ".imaginary-class" : false, // For some reason doesn't get re-evaluated after adding more children.
|
||||
start: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
element.editor.focusedElement.setIsFocused();
|
||||
element.setIsDropTarget(true);
|
||||
element.editor.isDragging = true;
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.element.setIsFocusedEventHandlers.push(function () {
|
||||
$element.parent().focus();
|
||||
});
|
||||
|
||||
$scope.delete = function (element) {
|
||||
element.delete();
|
||||
}
|
||||
},
|
||||
|
||||
configureForContainer: function ($scope, $element) {
|
||||
var element = $scope.element;
|
||||
|
||||
//$scope.isReceiving = false; // True when container is receiving an external element via drag/drop.
|
||||
$scope.getShowChildrenPlaceholder = function () {
|
||||
return $scope.element.children.length === 0 && !$scope.element.getIsDropTarget();
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
cursor: "move",
|
||||
delay: 150,
|
||||
disabled: element.getIsSealed(),
|
||||
distance: 5,
|
||||
//handle: element.children.length < 2 ? ".imaginary-class" : false, // For some reason doesn't get re-evaluated after adding more children.
|
||||
start: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
element.setIsDropTarget(true);
|
||||
element.editor.isDragging = true;
|
||||
});
|
||||
// Make the drop target placeholder as high as the item being dragged.
|
||||
ui.placeholder.height(ui.item.height() - 4);
|
||||
ui.placeholder.css("min-height", 0);
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
element.editor.isDragging = false;
|
||||
element.setIsDropTarget(false);
|
||||
});
|
||||
},
|
||||
over: function (e, ui) {
|
||||
if (!!ui.sender && !!ui.sender[0].isToolbox) {
|
||||
if (!!ui.sender[0].dropTargetTimeout) {
|
||||
$timeout.cancel(ui.sender[0].dropTargetTimeout);
|
||||
ui.sender[0].dropTargetTimeout = null;
|
||||
}
|
||||
$timeout(function () {
|
||||
if (element.type == "Row") {
|
||||
// If there was a previous drop target and it was a row, roll back any pending column adds to it.
|
||||
var previousDropTarget = element.editor.dropTargetElement;
|
||||
if (!!previousDropTarget && previousDropTarget.type == "Row")
|
||||
previousDropTarget.rollbackAddColumn();
|
||||
}
|
||||
// Make the drop target placeholder as high as the item being dragged.
|
||||
ui.placeholder.height(ui.item.height() - 4);
|
||||
ui.placeholder.css("min-height", 0);
|
||||
},
|
||||
stop: function (e, ui) {
|
||||
$scope.$apply(function () {
|
||||
element.editor.isDragging = false;
|
||||
element.setIsDropTarget(false);
|
||||
});
|
||||
ui.sender[0].dropTargetTimeout = $timeout(function () {
|
||||
if (element.type == "Row") {
|
||||
var receivedColumn = ui.item.sortable.model;
|
||||
var receivedColumnWidth = Math.floor(12 / (element.children.length + 1));
|
||||
receivedColumn.width = receivedColumnWidth;
|
||||
receivedColumn.offset = 0;
|
||||
element.beginAddColumn(receivedColumnWidth);
|
||||
// Make the drop target placeholder the correct width and as high as the highest existing column in the row.
|
||||
var maxHeight = _.max(_($element.find("> .layout-children > .layout-column:not(.ui-sortable-placeholder)")).map(function (e) {
|
||||
return $(e).height();
|
||||
}));
|
||||
for (i = 1; i <= 12; i++)
|
||||
ui.placeholder.removeClass("col-xs-" + i);
|
||||
ui.placeholder.addClass("col-xs-" + receivedColumn.width);
|
||||
if (maxHeight > 0) {
|
||||
ui.placeholder.height(maxHeight);
|
||||
ui.placeholder.css("min-height", 0);
|
||||
}
|
||||
else {
|
||||
ui.placeholder.height(0);
|
||||
ui.placeholder.css("min-height", "");
|
||||
}
|
||||
}
|
||||
element.setIsDropTarget(true);
|
||||
}, 150);
|
||||
}
|
||||
},
|
||||
receive: function (e, ui) {
|
||||
if (!!ui.sender && !!ui.sender[0].isToolbox) {
|
||||
$scope.$apply(function () {
|
||||
var receivedElement = ui.item.sortable.model;
|
||||
if (!!receivedElement) {
|
||||
if (element.type == "Row")
|
||||
element.commitAddColumn();
|
||||
// Should ideally call LayoutEditor.Container.addChild() instead, but since this handler
|
||||
// is run *before* the ui-sortable directive's handler, if we try to add the child to the
|
||||
// array that handler will get an exception when trying to do the same.
|
||||
// Because of this, we need to invoke "setParent" so that specific container types can perform element speficic initialization.
|
||||
receivedElement.setEditor(element.editor);
|
||||
receivedElement.setParent(element);
|
||||
if (receivedElement.type == "Content" && !!receivedElement.hasEditor) {
|
||||
$scope.$root.editElement(receivedElement).then(function (args) {
|
||||
if (!args.cancel) {
|
||||
receivedElement.data = decodeURIComponent(args.element.data);
|
||||
receivedElement.setHtml(decodeURIComponent(args.element.html.replace(/\+/g, "%20")));
|
||||
}
|
||||
$timeout(function () {
|
||||
if (!!args.cancel)
|
||||
receivedElement.delete();
|
||||
else
|
||||
receivedElement.setIsFocused();
|
||||
//$scope.isReceiving = false;
|
||||
element.setIsDropTarget(false);
|
||||
|
||||
});
|
||||
return;
|
||||
});
|
||||
}
|
||||
},
|
||||
over: function (e, ui) {
|
||||
if (!!ui.sender && !!ui.sender[0].isToolbox) {
|
||||
if (!!ui.sender[0].dropTargetTimeout) {
|
||||
$timeout.cancel(ui.sender[0].dropTargetTimeout);
|
||||
ui.sender[0].dropTargetTimeout = null;
|
||||
}
|
||||
$timeout(function () {
|
||||
//$scope.isReceiving = false;
|
||||
if (element.type == "Row") {
|
||||
// If there was a previous drop target and it was a row, roll back any pending column adds to it.
|
||||
var previousDropTarget = element.editor.dropTargetElement;
|
||||
if (!!previousDropTarget && previousDropTarget.type == "Row")
|
||||
previousDropTarget.rollbackAddColumn();
|
||||
}
|
||||
element.setIsDropTarget(false);
|
||||
if (!!receivedElement)
|
||||
receivedElement.setIsFocused();
|
||||
});
|
||||
});
|
||||
ui.sender[0].dropTargetTimeout = $timeout(function () {
|
||||
if (element.type == "Row") {
|
||||
var receivedColumn = ui.item.sortable.model;
|
||||
var receivedColumnWidth = Math.floor(12 / (element.children.length + 1));
|
||||
receivedColumn.width = receivedColumnWidth;
|
||||
receivedColumn.offset = 0;
|
||||
element.beginAddColumn(receivedColumnWidth);
|
||||
// Make the drop target placeholder the correct width and as high as the highest existing column in the row.
|
||||
var maxHeight = _.max(_($element.find("> .layout-children > .layout-column:not(.ui-sortable-placeholder)")).map(function (e) {
|
||||
return $(e).height();
|
||||
}));
|
||||
for (i = 1; i <= 12; i++)
|
||||
ui.placeholder.removeClass("col-xs-" + i);
|
||||
ui.placeholder.addClass("col-xs-" + receivedColumn.width);
|
||||
if (maxHeight > 0) {
|
||||
ui.placeholder.height(maxHeight);
|
||||
ui.placeholder.css("min-height", 0);
|
||||
}
|
||||
else {
|
||||
ui.placeholder.height(0);
|
||||
ui.placeholder.css("min-height", "");
|
||||
}
|
||||
}
|
||||
element.setIsDropTarget(true);
|
||||
}, 150);
|
||||
}
|
||||
},
|
||||
receive: function (e, ui) {
|
||||
if (!!ui.sender && !!ui.sender[0].isToolbox) {
|
||||
$scope.$apply(function () {
|
||||
var receivedElement = ui.item.sortable.model;
|
||||
if (!!receivedElement) {
|
||||
if (element.type == "Row")
|
||||
element.commitAddColumn();
|
||||
// Should ideally call LayoutEditor.Container.addChild() instead, but since this handler
|
||||
// is run *before* the ui-sortable directive's handler, if we try to add the child to the
|
||||
// array that handler will get an exception when trying to do the same.
|
||||
// Because of this, we need to invoke "setParent" so that specific container types can perform element speficic initialization.
|
||||
receivedElement.setEditor(element.editor);
|
||||
receivedElement.setParent(element);
|
||||
if (receivedElement.type == "Content" && !!receivedElement.hasEditor) {
|
||||
$scope.$root.editElement(receivedElement).then(function (args) {
|
||||
if (!args.cancel) {
|
||||
receivedElement.data = decodeURIComponent(args.element.data);
|
||||
receivedElement.setHtml(decodeURIComponent(args.element.html.replace(/\+/g, "%20")));
|
||||
}
|
||||
$timeout(function () {
|
||||
if (!!args.cancel)
|
||||
receivedElement.delete();
|
||||
else
|
||||
receivedElement.setIsFocused();
|
||||
//$scope.isReceiving = false;
|
||||
element.setIsDropTarget(false);
|
||||
|
||||
});
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
$timeout(function () {
|
||||
//$scope.isReceiving = false;
|
||||
element.setIsDropTarget(false);
|
||||
if (!!receivedElement)
|
||||
receivedElement.setIsFocused();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$scope.click = function (child, e) {
|
||||
if (!child.editor.isDragging)
|
||||
child.setIsFocused();
|
||||
e.stopPropagation();
|
||||
};
|
||||
$scope.click = function (child, e) {
|
||||
if (!child.editor.isDragging)
|
||||
child.setIsFocused();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
$scope.getClasses = function (child) {
|
||||
var result = ["layout-element"];
|
||||
$scope.getClasses = function (child) {
|
||||
var result = ["layout-element"];
|
||||
|
||||
if (!!child.children) {
|
||||
result.push("layout-container");
|
||||
if (child.getIsSealed())
|
||||
result.push("layout-container-sealed");
|
||||
}
|
||||
if (!!child.children) {
|
||||
result.push("layout-container");
|
||||
if (child.getIsSealed())
|
||||
result.push("layout-container-sealed");
|
||||
}
|
||||
|
||||
result.push("layout-" + child.type.toLowerCase());
|
||||
result.push("layout-" + child.type.toLowerCase());
|
||||
|
||||
if (!!child.dropTargetClass)
|
||||
result.push(child.dropTargetClass);
|
||||
if (!!child.dropTargetClass)
|
||||
result.push(child.dropTargetClass);
|
||||
|
||||
// TODO: Move these to either the Column directive or the Column model class.
|
||||
if (child.type == "Row") {
|
||||
result.push("row");
|
||||
if (!child.canAddColumn())
|
||||
result.push("layout-row-full");
|
||||
}
|
||||
if (child.type == "Column") {
|
||||
result.push("col-xs-" + child.width);
|
||||
result.push("col-xs-offset-" + child.offset);
|
||||
}
|
||||
if (child.type == "Content")
|
||||
result.push("layout-content-" + child.contentTypeClass);
|
||||
// TODO: Move these to either the Column directive or the Column model class.
|
||||
if (child.type == "Row") {
|
||||
result.push("row");
|
||||
if (!child.canAddColumn())
|
||||
result.push("layout-row-full");
|
||||
}
|
||||
if (child.type == "Column") {
|
||||
result.push("col-xs-" + child.width);
|
||||
result.push("col-xs-offset-" + child.offset);
|
||||
}
|
||||
if (child.type == "Content")
|
||||
result.push("layout-content-" + child.contentTypeClass);
|
||||
|
||||
if (child.getIsActive())
|
||||
result.push("layout-element-active");
|
||||
if (child.getIsFocused())
|
||||
result.push("layout-element-focused");
|
||||
if (child.getIsSelected())
|
||||
result.push("layout-element-selected");
|
||||
if (child.getIsDropTarget())
|
||||
result.push("layout-element-droptarget");
|
||||
if (child.isTemplated)
|
||||
result.push("layout-element-templated");
|
||||
if (child.getIsActive())
|
||||
result.push("layout-element-active");
|
||||
if (child.getIsFocused())
|
||||
result.push("layout-element-focused");
|
||||
if (child.getIsSelected())
|
||||
result.push("layout-element-selected");
|
||||
if (child.getIsDropTarget())
|
||||
result.push("layout-element-droptarget");
|
||||
if (child.isTemplated)
|
||||
result.push("layout-element-templated");
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
]);
|
Reference in New Issue
Block a user