Fixes: U4-4952 RTE: macro editing - parameter dialog blank

This commit is contained in:
Shannon
2014-05-21 15:27:10 +10:00
parent 976d1b1ff6
commit 9f16bee040
28 changed files with 102 additions and 151 deletions

View File

@@ -38,10 +38,42 @@ angular.module('umbraco.services')
for (var i = 0; i < dialogs.length; i++) {
var dialog = dialogs[i];
dialog.close(args);
dialogs.splice(i, 1);
}
}
/** Internal method that closes the dialog properly and cleans up resources */
function closeDialog(dialog) {
if (dialog.element) {
dialog.element.modal('hide');
//this is not entirely enough since the damn webforms scriploader still complains
if (dialog.iframe) {
dialog.element.find("iframe").attr("src", "about:blank");
$timeout(function () {
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.element.remove();
//SD: No idea why this is required but was there before - pretty sure it's not required
$("#" + dialog.element.attr("id")).remove();
dialog.scope.$destroy();
}, 1000);
} else {
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.element.remove();
//SD: No idea why this is required but was there before - pretty sure it's not required
$("#" + dialog.element.attr("id")).remove();
dialog.scope.$destroy();
}
}
//remove 'this' dialog from the dialogs array
dialogs = _.reject(dialogs, function (i) { return i === dialog; });
}
/** Internal method that handles opening all dialogs */
function openDialog(options) {
var defaults = {
@@ -55,13 +87,19 @@ angular.module('umbraco.services')
template: "views/common/notfound.html",
callback: undefined,
closeCallback: undefined,
element: undefined,
//this allows us to pass in data to the dialog if required which can be used to configure the dialog
//and re-use it for different purposes. It will set on to the $scope.dialogData if it is defined.
element: undefined,
// It will set this value as a property on the dialog controller's scope as dialogData,
// used to pass in custom data to the dialog controller's $scope. Though this is near identical to
// the dialogOptions property that is also set the the dialog controller's $scope object.
// So there's basically 2 ways of doing the same thing which we're now stuck with and in fact
// dialogData has another specially attached property called .selection which gets used.
dialogData: undefined
};
var dialog = angular.extend(defaults, options);
//NOTE: People should NOT pass in a scope object that is legacy functoinality and causes problems. We will ALWAYS
// destroy the scope when the dialog is closed regardless if it is in use elsewhere which is why it shouldn't be done.
var scope = options.scope || $rootScope.$new();
//Modal dom obj and unique id
@@ -94,28 +132,7 @@ angular.module('umbraco.services')
dialog.closeCallback(data);
}
if (dialog.element) {
dialog.element.modal('hide');
//this is not entirely enough since the damn
//webforms scriploader still complains
if (dialog.iframe) {
dialog.element.find("iframe").attr("src", "about:blank");
$timeout(function () {
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.element.remove();
dialog.scope.$destroy();
}, 1000);
} else {
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.element.remove();
dialog.scope.$destroy();
}
}
closeDialog(dialog);
};
//if iframe is enabled, inject that instead of a template
@@ -183,15 +200,9 @@ angular.module('umbraco.services')
}
};
//NOTE: Same as 'close' without the callbacks
scope.hide = function () {
dialog.element.modal('hide');
dialog.element.remove();
$("#" + dialog.element.attr("id")).remove();
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.scope.$destroy();
closeDialog(dialog);
};
//basic events for submitting and closing
@@ -200,19 +211,16 @@ angular.module('umbraco.services')
dialog.callback(data);
}
dialog.element.modal('hide');
dialog.element.remove();
$("#" + dialog.element.attr("id")).remove();
//we need to do more than just remove the element, this will not destroy the
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
// take care of this ourselves we have memory leaks.
dialog.scope.$destroy();
closeDialog(dialog);
};
scope.close = function (data) {
dialog.close(data);
};
//NOTE: This can ONLY ever be used to show the dialog if dialog.show is false (autoshow).
// You CANNOT call show() after you call hide(). hide = close, they are the same thing and once
// a dialog is closed it's resources are disposed of.
scope.show = function () {
dialog.element.modal('show');
};
@@ -226,6 +234,7 @@ angular.module('umbraco.services')
}
};
//NOTE: Same as 'close' without the callbacks
scope.dismiss = scope.hide;
// Emit modal events
@@ -274,7 +283,6 @@ angular.module('umbraco.services')
* @param {String} options.animation animation csss class, by default set to "fade"
* @param {String} options.modalClass modal css class, by default "umb-modal"
* @param {Bool} options.show show the modal instantly
* @param {Object} options.scope scope to attach the modal to, by default rootScope.new()
* @param {Bool} options.iframe load template in an iframe, only needed for serverside templates
* @param {Int} options.width set a width on the modal, only needed for iframes
* @param {Bool} options.inline strips the modal from any animation and wrappers, used when you want to inject a dialog into an existing container
@@ -321,7 +329,6 @@ angular.module('umbraco.services')
* @description
* Opens a media picker in a modal, the callback returns an array of selected media items
* @param {Object} options mediapicker dialog options object
* @param {$scope} options.scope dialog scope
* @param {Boolean} options.onlyImages Only display files that have an image file-extension
* @param {Function} options.callback callback function
* @returns {Object} modal object
@@ -341,8 +348,7 @@ angular.module('umbraco.services')
* @description
* Opens a content picker tree in a modal, the callback returns an array of selected documents
* @param {Object} options content picker dialog options object
* @param {$scope} options.scope dialog scope
* @param {$scope} options.multipicker should the picker return one or multiple items
* @param {Boolean} options.multipicker should the picker return one or multiple items
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -360,7 +366,6 @@ angular.module('umbraco.services')
* @description
* Opens a link picker tree in a modal, the callback returns a single link
* @param {Object} options content picker dialog options object
* @param {$scope} options.scope dialog scope
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -378,7 +383,6 @@ angular.module('umbraco.services')
* @description
* Opens a mcaro picker in a modal, the callback returns a object representing the macro and it's parameters
* @param {Object} options macropicker dialog options object
* @param {$scope} options.scope dialog scope
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -397,8 +401,7 @@ angular.module('umbraco.services')
* @description
* Opens a member picker in a modal, the callback returns a object representing the selected member
* @param {Object} options member picker dialog options object
* @param {$scope} options.scope dialog scope
* @param {$scope} options.multiPicker should the tree pick one or multiple members before returning
* @param {Boolean} options.multiPicker should the tree pick one or multiple members before returning
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -416,8 +419,7 @@ angular.module('umbraco.services')
* @description
* Opens a member group picker in a modal, the callback returns a object representing the selected member
* @param {Object} options member group picker dialog options object
* @param {$scope} options.scope dialog scope
* @param {$scope} options.multiPicker should the tree pick one or multiple members before returning
* @param {Boolean} options.multiPicker should the tree pick one or multiple members before returning
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -435,7 +437,6 @@ angular.module('umbraco.services')
* @description
* Opens a icon picker in a modal, the callback returns a object representing the selected icon
* @param {Object} options iconpicker dialog options object
* @param {$scope} options.scope dialog scope
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -453,10 +454,9 @@ angular.module('umbraco.services')
* @description
* Opens a tree picker in a modal, the callback returns a object representing the selected tree item
* @param {Object} options iconpicker dialog options object
* @param {$scope} options.scope dialog scope
* @param {$scope} options.section tree section to display
* @param {$scope} options.treeAlias specific tree to display
* @param {$scope} options.multiPicker should the tree pick one or multiple items before returning
* @param {String} options.section tree section to display
* @param {String} options.treeAlias specific tree to display
* @param {Boolean} options.multiPicker should the tree pick one or multiple items before returning
* @param {Function} options.callback callback function
* @returns {Object} modal object
*/
@@ -474,7 +474,6 @@ angular.module('umbraco.services')
* @description
* Opens a dialog with a chosen property editor in, a value can be passed to the modal, and this value is returned in the callback
* @param {Object} options mediapicker dialog options object
* @param {$scope} options.scope dialog scope
* @param {Function} options.callback callback function
* @param {String} editor editor to use to edit a given value and return on callback
* @param {Object} value value sent to the property editor

View File

@@ -400,7 +400,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
}
var dialog = self.showDialog({
scope: args.scope,
node: args.node,
action: found,
section: appState.getSectionState("currentSection")
@@ -569,12 +568,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
* into #dialog div.umb-panel-body
* the path to the dialog view is determined by:
* "views/" + current tree + "/" + action alias + ".html"
* The dialog controller will get passed a scope object that is created here. This scope
* object may be injected as part of the args object, if one is not found then a new scope
* is created. Regardless of whether a scope is created or re-used, a few properties and methods
* will be added to it so that they can be used in any dialog controller:
* The dialog controller will get passed a scope object that is created here with the properties:
* scope.currentNode = the selected tree node
* scope.currentAction = the selected menu item
* so that the dialog controllers can use these properties
*
* @param {Object} args arguments passed to the function
* @param {Scope} args.scope current scope passed to the dialog
* @param {Object} args.action the clicked action containing `name` and `alias`
@@ -598,8 +596,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
setMode("dialog");
//set up the scope object and assign properties
var dialogScope = args.scope || $rootScope.$new();
//NOTE: Set up the scope object and assign properties, this is legacy functionality but we have to live with it now.
// we should be passing in currentNode and currentAction using 'dialogData' for the dialog, not attaching it to a scope.
// This scope instance will be destroyed by the dialog so it cannot be a scope that exists outside of the dialog.
// If a scope instance has been passed in, we'll have to create a child scope of it, otherwise a new root scope.
var dialogScope = args.scope ? args.scope.$new() : $rootScope.$new();
dialogScope.currentNode = args.node;
dialogScope.currentAction = args.action;
@@ -657,14 +658,19 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
var dialog = dialogService.open(
{
container: $("#dialog div.umb-modalcolumn-body"),
//The ONLY reason we're passing in scope to the dialogService (which is legacy functionality) is
// for backwards compatibility since many dialogs require $scope.currentNode or $scope.currentAction
// to exist
scope: dialogScope,
currentNode: args.node,
currentAction: args.action,
inline: true,
show: true,
iframe: iframe,
modalClass: "umb-dialog",
template: templateUrl
template: templateUrl,
//These will show up on the dialog controller's $scope under dialogOptions
currentNode: args.node,
currentAction: args.action,
});
//save the currently assigned dialog so it can be removed before a new one is created

View File

@@ -61,7 +61,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
tooltip: 'Embed',
onclick: function () {
dialogService.embedDialog({
scope: $scope, callback: function (data) {
callback: function (data) {
editor.insertContent(data);
}
});
@@ -80,7 +80,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
* @param {Object} editor the TinyMCE editor instance
* @param {Object} $scope the current controller scope
*/
createMediaPicker: function (editor, $scope) {
createMediaPicker: function (editor) {
editor.addButton('umbmediapicker', {
icon: 'custom icon-picture',
tooltip: 'Media Picker',
@@ -103,7 +103,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
currentTarget: currentTarget,
onlyImages: true,
showDetails: true,
scope: $scope, callback: function (img) {
callback: function (img) {
if (img) {
@@ -139,49 +139,6 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
});
},
/**
* @ngdoc method
* @name umbraco.services.tinyMceService#createLinkPicker
* @methodOf umbraco.services.tinyMceService
*
* @description
* Creates the umbrco insert link tinymce plugin
*
* @param {Object} editor the TinyMCE editor instance
* @param {Object} $scope the current controller scope
*/
createLinkPicker: function (editor, $scope) {
/*
editor.addButton('link', {
icon: 'custom icon-link',
tooltip: 'Link Picker',
onclick: function () {
dialogService.linkPicker({
scope: $scope, callback: function (link) {
if (link) {
var data = {
title: "Some description",
href: "",
id: '__mcenew'
};
editor.execCommand("mceInsertLink", false, {
href: "wat",
title: "muh",
target: null,
"class": null
});
//editor.insertContent(editor.dom.createHTML('a', data));
}
}
});
}
});*/
},
/**
* @ngdoc method
* @name umbraco.services.tinyMceService#createUmbracoMacro
@@ -496,7 +453,6 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
}
dialogService.macroPicker({
scope: $scope,
dialogData : dialogData,
callback: function(data) {

View File

@@ -107,9 +107,6 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
//this reacts to the options item in the tree
//todo, migrate to nav service
$scope.searchShowMenu = function (ev, args) {
$scope.currentNode = args.node;
args.scope = $scope;
//always skip default
args.skipDefault = true;
navigationService.showMenu(ev, args);

View File

@@ -26,8 +26,10 @@ function SearchController($scope, searchService, $log, $location, navigationServ
iterateResults(false);
break;
case 13:
$location.path($scope.selectedItem.editorPath);
navigationService.hideSearch();
if ($scope.selectedItem) {
$location.path($scope.selectedItem.editorPath);
navigationService.hideSearch();
}
break;
}
};

View File

@@ -4,7 +4,7 @@ function ContentEditDialogController($scope) {
$scope.model.defaultButton = null;
$scope.model.subButtons = [];
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
if(dialogOptions.entity){
$scope.model.entity = dialogOptions.entity;
$scope.loaded = true;

View File

@@ -1,7 +1,7 @@
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.ContentPickerController",
function ($scope, eventsService, entityResource, searchService, $log) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
$scope.results = [];

View File

@@ -1,7 +1,7 @@
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, $log) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
$scope.target = {};

View File

@@ -3,7 +3,7 @@ angular.module("umbraco")
.controller("Umbraco.Dialogs.MediaPickerController",
function ($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, eventsService, treeService, $cookies) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.onlyImages = dialogOptions.onlyImages;
$scope.showDetails = dialogOptions.showDetails;

View File

@@ -1,7 +1,7 @@
//used for the member picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.MemberGroupPickerController",
function($scope, eventsService, entityResource, searchService, $log) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
$scope.results = [];
$scope.dialogData = [];

View File

@@ -1,7 +1,7 @@
//used for the member picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.MemberPickerController",
function($scope, eventsService, entityResource, searchService, $log) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
$scope.results = [];

View File

@@ -2,7 +2,7 @@
angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
function ($scope, entityResource, eventsService, $log, searchService) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
$scope.section = dialogOptions.section;
$scope.treeAlias = dialogOptions.treeAlias;

View File

@@ -22,7 +22,7 @@ angular.module("umbraco")
var pendingChangeEvent = eventsService.on("valFormManager.pendingChanges", function (e, args) {
//one time listener, remove the event
pendingChangeEvent();
$scope.hide();
$scope.close();
});
//perform the path change, if it is successful then the promise will resolve otherwise it will fail
@@ -31,7 +31,7 @@ angular.module("umbraco")
$scope.gotoHistory = function (link) {
$location.path(link);
$scope.hide();
$scope.close();
};
//Manually update the remaining timeout seconds

View File

@@ -2,7 +2,7 @@ angular.module("umbraco")
.controller("Umbraco.Editors.Content.CopyController",
function ($scope, eventsService, contentResource, navigationService, appState, treeService) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.relateToOriginal = false;
$scope.dialogTreeEventHandler = $({});

View File

@@ -1,7 +1,7 @@
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
function ($scope, eventsService, contentResource, navigationService, appState, treeService) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
var node = dialogOptions.currentNode;

View File

@@ -22,7 +22,7 @@ function startupLatestEditsController($scope) {
angular.module("umbraco").controller("Umbraco.Dashboard.StartupLatestEditsController", startupLatestEditsController);
function MediaFolderBrowserDashboardController($rootScope, $scope, assetsService, $routeParams, $timeout, $element, $location, umbRequestHelper,navigationService, mediaResource, $cookies) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.filesUploading = [];
$scope.options = {

View File

@@ -1,7 +1,7 @@
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
function ($scope, eventsService, mediaResource, appState, treeService, navigationService) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.dialogTreeEventHandler = $({});
var node = dialogOptions.currentNode;

View File

@@ -29,7 +29,6 @@ angular.module('umbraco')
var d = dialogService.treePicker({
section: $scope.cfg.type,
treeAlias: $scope.cfg.type,
scope: $scope,
multiPicker: $scope.cfg.multiPicker,
callback: populate});
};

View File

@@ -30,7 +30,6 @@ angular.module('umbraco')
var d = dialogService.treePicker({
section: $scope.cfg.type,
treeAlias: $scope.cfg.type,
scope: $scope,
multiPicker: $scope.cfg.multiPicker,
callback: populate});
};

View File

@@ -31,7 +31,6 @@ angular.module('umbraco')
var d = dialogService.treePicker({
section: $scope.model.value.type,
treeAlias: $scope.model.value.type,
scope: $scope,
multiPicker: false,
callback: populate});
};

View File

@@ -12,7 +12,7 @@ angular.module("umbraco")
})
.controller("Umbraco.PropertyEditors.FolderBrowserController",
function ($rootScope, $scope, assetsService, $routeParams, $timeout, $element, $location, $log, umbRequestHelper, mediaResource, imageHelper, navigationService, editorState) {
var dialogOptions = $scope.$parent.dialogOptions;
var dialogOptions = $scope.dialogOptions;
$scope.creating = $routeParams.create;

View File

@@ -33,7 +33,7 @@ angular.module("umbraco")
google.maps.event.addListener(map, 'click', function (event) {
dialogService.mediaPicker({
scope: $scope, callback: function (data) {
callback: function (data) {
var image = data.selection[0].src;
var latLng = event.latLng;

View File

@@ -7,15 +7,15 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.GridController",
//we most likely will need some iframe-motherpage interop here
$scope.openMediaPicker =function(){
var d = dialogService.mediaPicker({scope: $scope, callback: renderImages});
var d = dialogService.mediaPicker({callback: renderImages});
};
$scope.openPropertyDialog =function(){
var d = dialogService.property({scope: $scope, callback: renderProperty});
var d = dialogService.property({callback: renderProperty});
};
$scope.openMacroDialog =function(){
var d = dialogService.macroPicker({scope: $scope, callback: renderMacro});
var d = dialogService.macroPicker({callback: renderMacro});
};
function renderProperty(data){
@@ -26,8 +26,8 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.GridController",
// $scope.currentElement.html( macroFactory.renderMacro(data.macro, -1) );
}
function renderImages(data){
var list = $("<ul class='thumbnails'></ul>")
function renderImages(data) {
var list = $("<ul class='thumbnails'></ul>");
$.each(data.selection, function(i, image) {
list.append( $("<li class='span2'><img class='thumbnail' src='" + image.src + "'></li>") );
});

View File

@@ -43,7 +43,6 @@ angular.module('umbraco')
}
dialogService.macroPicker({
scope: $scope,
dialogData : dialogData,
callback: function(data) {

View File

@@ -28,7 +28,6 @@ angular.module('umbraco')
$scope.openMemberGroupPicker =function(){
var d = dialogService.memberGroupPicker(
{
scope: $scope,
multiPicker: $scope.cfg.multiPicker,
filter: $scope.cfg.filter,
filterCssClass: "not-allowed",

View File

@@ -22,7 +22,6 @@ angular.module('umbraco')
$scope.openMemberPicker =function(){
var d = dialogService.memberPicker(
{
scope: $scope,
multiPicker: $scope.cfg.multiPicker,
filter: $scope.cfg.filter,
filterCssClass: "not-allowed",

View File

@@ -17,14 +17,14 @@
$scope.internal = function ($event) {
$scope.currentEditLink = null;
var d = dialogService.contentPicker({ scope: $scope, multipicker: false, callback: select });
var d = dialogService.contentPicker({ multipicker: false, callback: select });
$event.preventDefault();
};
$scope.selectInternal = function ($event, link) {
$scope.currentEditLink = link;
var d = dialogService.contentPicker({ scope: $scope, multipicker: false, callback: select });
var d = dialogService.contentPicker({ multipicker: false, callback: select });
$event.preventDefault();
};

View File

@@ -182,9 +182,6 @@ angular.module("umbraco")
//Create the embedded plugin
tinyMceService.createInsertEmbeddedMedia(editor, $scope);
//Create the insert link plugin
tinyMceService.createLinkPicker(editor, $scope);
//Create the insert macro plugin
tinyMceService.createInsertMacro(editor, $scope);
};