diff --git a/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js b/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js index 64f3830048..20e71fdc05 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js @@ -30,15 +30,18 @@ angular.module('umbraco.services') .factory('dialogService', ['$rootScope', '$compile', '$http', '$timeout', '$q', '$templateCache', function ($rootScope, $compile, $http, $timeout, $q, $templateCache) { - var _dialogs = []; + + var dialogs = []; + $rootScope.$on("closeDialogs", function () { - for (var i = 0; i < _dialogs.length; i++) { - var dialog = _dialogs[i]; + for (var i = 0; i < dialogs.length; i++) { + var dialog = dialogs[i]; removeDialog(dialog); - _dialogs.splice(i, 1); + dialogs.splice(i, 1); } }); + /** Internal method that handles closing a specific dialog */ function removeDialog(dialog) { dialog.modal("hide"); @@ -48,8 +51,8 @@ angular.module('umbraco.services') }, 250); } - //internal method that handles opening all dialogs - function _open(options) { + /** Internal method that handles opening all dialogs */ + function openDialog(options) { if (!options) { options = {}; } @@ -58,7 +61,7 @@ angular.module('umbraco.services') container = options.container || $("body"), animationClass = options.animation || "fade", modalClass = options.modalClass || "umb-modal", - width = options.width || "100%"; + width = options.width || "100%", templateUrl = options.template || "views/common/notfound.html"; //if a callback is available @@ -84,7 +87,7 @@ angular.module('umbraco.services') .addClass(modalClass); //push the modal into the global modal collection - _dialogs.push($modal); + dialogs.push($modal); //if iframe is enabled, inject that instead of a template if (options.iframe) { @@ -99,9 +102,7 @@ angular.module('umbraco.services') $compile($modal)(scope); }); - if (width) { - $modal.css("width", width); - } + $modal.css("width", width); //Autoshow if (options.show) { @@ -109,82 +110,89 @@ angular.module('umbraco.services') } return $modal; - } else { - return $q.when($templateCache.get(templateUrl) || $http.get(templateUrl, { cache: true }).then(function (res) { return res.data; })) - .then(function onSuccess(template) { + } + else { + + //We need to load the template with an httpget and once it's loaded we'll compile and assign the result to the container + // object. However since the result could be a promise or just data we need to use a $q.when. We still need to return the + // $modal object so we'll actually return the modal object synchronously without waiting for the promise. Otherwise this openDialog + // method will always need to return a promise which gets nasty because of promises in promises plus the result just needs a reference + // to the $modal object which will not change (only it's contents will change). + $q.when($templateCache.get(templateUrl) || $http.get(templateUrl, { cache: true }).then(function(res) { return res.data; })) + .then(function onSuccess(template) { - // Build modal object - $modal - .html(template); + // Build modal object + $modal.html(template); - //append to body or other container element - container.append($modal); + //append to body or other container element + container.append($modal); - // Compile modal content - $timeout(function () { - $compile($modal)(scope); - }); + // Compile modal content + $timeout(function() { + $compile($modal)(scope); + }); - //Scope to handle data from the modal form - scope.dialogData = {}; - scope.dialogData.selection = []; + //Scope to handle data from the modal form + scope.dialogData = {}; + scope.dialogData.selection = []; - // Provide scope display functions - //this passes the modal to the current scope - scope.$modal = function (name) { - $modal.modal(name); - }; + // Provide scope display functions + //this passes the modal to the current scope + scope.$modal = function(name) { + $modal.modal(name); + }; - scope.hide = function () { - $modal.modal('hide'); + scope.hide = function() { + $modal.modal('hide'); - $modal.remove(); - $("#" + $modal.attr("id")).remove(); - }; + $modal.remove(); + $("#" + $modal.attr("id")).remove(); + }; - scope.show = function () { - $modal.modal('show'); - }; + scope.show = function() { + $modal.modal('show'); + }; - scope.submit = function (data) { - if (callback) { - callback(data); - } - - $modal.modal('hide'); - - $modal.remove(); - $("#" + $modal.attr("id")).remove(); - }; - - scope.select = function (item) { - if (scope.dialogData.selection.indexOf(item) < 0) { - scope.dialogData.selection.push(item); - } - }; - - scope.dismiss = scope.hide; - - // Emit modal events - angular.forEach(['show', 'shown', 'hide', 'hidden'], function (name) { - $modal.on(name, function (ev) { - scope.$emit('modal-' + name, ev); - }); - }); - - // Support autofocus attribute - $modal.on('shown', function (event) { - $('input[autofocus]', $modal).first().trigger('focus'); - }); - - //Autoshow - if (options.show) { - $modal.modal('show'); + scope.submit = function(data) { + if (callback) { + callback(data); } - //Return the modal object - return $modal; + $modal.modal('hide'); + + $modal.remove(); + $("#" + $modal.attr("id")).remove(); + }; + + scope.select = function(item) { + if (scope.dialogData.selection.indexOf(item) < 0) { + scope.dialogData.selection.push(item); + } + }; + + scope.dismiss = scope.hide; + + // Emit modal events + angular.forEach(['show', 'shown', 'hide', 'hidden'], function(name) { + $modal.on(name, function(ev) { + scope.$emit('modal-' + name, ev); + }); }); + + // Support autofocus attribute + $modal.on('shown', function(event) { + $('input[autofocus]', $modal).first().trigger('focus'); + }); + + //Autoshow + if (options.show) { + $modal.modal('show'); + } + + }); + + //Return the modal object outside of the promise! + return $modal; } @@ -197,7 +205,8 @@ angular.module('umbraco.services') * @methodOf umbraco.services.dialogService * * @description - * Opens a modal rendering a given template url + * Opens a modal rendering a given template url. + * * @param {Object} options rendering options * @param {DomElement} options.container the DOM element to inject the modal into, by default set to body * @param {Function} options.callback function called when the modal is submitted @@ -208,10 +217,24 @@ angular.module('umbraco.services') * @param {Int} options.width set a width on the modal, only needed for iframes */ open: function (options) { - return _open(options); + return openDialog(options); }, + + /** + * @ngdoc method + * @name umbraco.services.dialogService#close + * @methodOf umbraco.services.dialogService + * + * @description + * Closes a specific dialog + * @param {Object} dialog the dialog object to close + */ + close: function(dialog) { + removeDialog(dialog); + }, + mediaPicker: function (options) { - return _open({ + return openDialog({ scope: options.scope, callback: options.callback, template: 'views/common/dialogs/mediaPicker.html', @@ -219,7 +242,7 @@ angular.module('umbraco.services') }); }, contentPicker: function (options) { - return _open({ + return openDialog({ scope: options.scope, callback: options.callback, template: 'views/common/dialogs/contentPicker.html', @@ -227,7 +250,7 @@ angular.module('umbraco.services') }); }, macroPicker: function (options) { - return _open({ + return openDialog({ scope: options.scope, callback: options.callback, template: 'views/common/dialogs/macroPicker.html', @@ -235,7 +258,7 @@ angular.module('umbraco.services') }); }, propertyDialog: function (options) { - return _open({ + return openDialog({ scope: options.scope, callback: options.callback, template: 'views/common/dialogs/property.html', @@ -246,7 +269,7 @@ angular.module('umbraco.services') //deprecated append: function (options) { - return _open(options); + return openDialog(options); /* var scope = options.scope || $rootScope.$new(), diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index a1c368deb9..49f3365522 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -17,7 +17,7 @@ */ angular.module('umbraco.services') -.factory('navigationService', function ($rootScope, $routeParams, $log, $location, dialogService, treeService, sectionResource) { +.factory('navigationService', function ($rootScope, $routeParams, $log, $location, $q, dialogService, treeService, sectionResource) { var currentSection = $routeParams.section; var currentId = $routeParams.id; @@ -203,7 +203,7 @@ angular.module('umbraco.services') * template is located in views/common/dialogs/user.html */ showUserDialog: function () { - var d = dialogService.open( + return dialogService.open( { template: "views/common/dialogs/user.html", modalClass: "umb-modal-left", @@ -243,15 +243,15 @@ angular.module('umbraco.services') iframe = true; } - var d = dialogService.open( - { - container: $("#dialog div.umb-panel-body"), - scope: scope, - inline: true, - show: true, - iframe: iframe, - template: templateUrl - }); + return dialogService.open( + { + container: $("#dialog div.umb-panel-body"), + scope: scope, + inline: true, + show: true, + iframe: iframe, + template: templateUrl + }); }, /** diff --git a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js index b880fcd9b7..5a20be30f2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js @@ -9,7 +9,10 @@ * * @param {navigationService} navigationService A reference to the navigationService */ -function NavigationController($scope,$rootScope, $location, navigationService, historyService, sectionResource) { +function NavigationController($scope,$rootScope, $location, navigationService, dialogService, historyService, sectionResource) { + + var actionDialog = null; + //load navigation service handlers $scope.changeSection = navigationService.changeSection; $scope.showTree = navigationService.showTree; @@ -90,7 +93,13 @@ function NavigationController($scope,$rootScope, $location, navigationService, h }); $scope.openDialog = function (currentNode, action, currentSection) { - navigationService.showDialog({ + + //ensure the actionDialog is cleared before opening another! + if (actionDialog) { + dialogService.close(actionDialog); + } + + actionDialog = navigationService.showDialog({ scope: $scope, node: currentNode, action: action,