diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 1bd4d409e7..506bba8990 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -48,27 +48,29 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not element.addClass(className); } + var unsubscribe = []; + //listen for the forms saving event - scope.$on(savingEventName, function (ev, args) { + unsubscribe.push(scope.$on(savingEventName, function(ev, args) { element.addClass(className); //set the flag so we can check to see if we should display the error. isSavingNewItem = $routeParams.create; - }); + })); //listen for the forms saved event - scope.$on(savedEvent, function (ev, args) { + unsubscribe.push(scope.$on(savedEvent, function(ev, args) { //remove validation class element.removeClass(className); //clear form state as at this point we retrieve new data from the server //and all validation will have cleared at this point formCtrl.$setPristine(); - }); + })); //This handles the 'unsaved changes' dialog which is triggered when a route is attempting to be changed but // the form has pending changes - var locationEvent = $rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) { + unsubscribe.push($rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) { if (!formCtrl.$dirty || isSavingNewItem) { return; } @@ -91,11 +93,11 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not eventsService.emit("valFormManager.pendingChanges", true); } - }); + })); //Ensure to remove the event handler when this instance is destroyted scope.$on('$destroy', function() { - if(locationEvent){ - locationEvent(); + for (var u in unsubscribe) { + unsubscribe[u](); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index a8d546bc36..eba308d830 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -96,8 +96,10 @@ function valPropertyMsg(serverValidationManager) { //create properties on our custom scope so we can use it in our template scope.errorMsg = ""; + var unsubscribe = []; + //listen for form error changes - scope.$on("valStatusChanged", function (evt, args) { + unsubscribe.push(scope.$on("valStatusChanged", function(evt, args) { if (args.form.$invalid) { //first we need to check if the valPropertyMsg validity is invalid @@ -123,10 +125,10 @@ function valPropertyMsg(serverValidationManager) { hasError = false; scope.errorMsg = ""; } - }, true); + }, true)); //listen for the forms saving event - scope.$on("formSubmitting", function (ev, args) { + unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { showValidation = true; if (hasError && scope.errorMsg === "") { scope.errorMsg = getErrorMsg(); @@ -135,15 +137,15 @@ function valPropertyMsg(serverValidationManager) { scope.errorMsg = ""; stopWatch(); } - }); + })); //listen for the forms saved event - scope.$on("formSubmitted", function (ev, args) { + unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { showValidation = false; scope.errorMsg = ""; formCtrl.$setValidity('valPropertyMsg', true); stopWatch(); - }); + })); //listen for server validation changes // NOTE: we pass in "" in order to listen for all validation changes to the content property, not for @@ -179,7 +181,16 @@ function valPropertyMsg(serverValidationManager) { serverValidationManager.unsubscribe(scope.property.alias, ""); }); } + + //when the scope is disposed we need to unsubscribe + scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); } + + }; } angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js index cdcfbcfe2a..43792a708a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js @@ -43,8 +43,10 @@ function valToggleMsg(serverValidationManager) { } }); + var unsubscribe = []; + //listen for the saving event (the result is a callback method which is called to unsubscribe) - var unsubscribeSaving = scope.$on("formSubmitting", function (ev, args) { + unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { showValidation = true; if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg]) { element.show(); @@ -56,20 +58,21 @@ function valToggleMsg(serverValidationManager) { else { element.hide(); } - }); + })); //listen for the saved event (the result is a callback method which is called to unsubscribe) - var unsubscribeSaved = scope.$on("formSubmitted", function (ev, args) { + unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { showValidation = false; element.hide(); - }); + })); //when the element is disposed we need to unsubscribe! // NOTE: this is very important otherwise if this directive is part of a modal, the listener still exists because the dom // element might still be there even after the modal has been hidden. element.bind('$destroy', function () { - unsubscribeSaving(); - unsubscribeSaved(); + for (var u in unsubscribe) { + unsubscribe[u](); + } }); } 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 5746fd022c..e79b6f8f78 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 @@ -537,6 +537,13 @@ angular.module('umbraco.services') template: 'views/common/dialogs/ysod.html', show: true }); + }, + + confirmDialog: function (ysodError) { + + options.template = 'views/common/dialogs/confirm.html'; + options.show = true; + return openDialog(options); } }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js index 664c246b14..baf7ada8a8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js @@ -49,13 +49,18 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon } }; - $scope.$on("formSubmitting", function (ev, args) { + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { return i.id; }); $scope.model.value = trim(currIds.join(), ","); }); + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); + //load media data var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) { diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js index 5dc615b449..7bb02ba751 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js @@ -58,10 +58,15 @@ angular.module('umbraco') }; - $scope.$on("formSubmitting", function (ev, args) { + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { $scope.model.value = trim($scope.ids.join(), ","); }); + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); + function trim(str, chr) { var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^'+chr+'+|'+chr+'+$', 'g'); return str.replace(rgxtrim, ''); diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js index 1797bf1de1..087447b184 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js @@ -43,13 +43,18 @@ angular.module('umbraco') //we always need to ensure we dont submit anything broken - $scope.$on("formSubmitting", function (ev, args) { + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { if($scope.model.value.type === "member"){ $scope.model.value.id = -1; $scope.model.value.query = ""; } }); + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); + function populate(item){ $scope.clear(); item.icon = iconHelper.convertFromLegacyIcon(item.icon); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js index 8ae6b137d6..9c322f3f5d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js @@ -91,15 +91,17 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont //set model to null $scope.model.value = null; }; - + + var unsubscribe = []; + //listen for the saved event, when that occurs we'll //change to changing = false; - $scope.$on("formSubmitted", function () { + unsubscribe.push($scope.$on("formSubmitted", function() { if ($scope.model.config.disableToggle === false) { $scope.changing = false; - } - }); - $scope.$on("formSubmitting", function() { + } + })); + unsubscribe.push($scope.$on("formSubmitting", function() { //if there was a previously generated password displaying, clear it if ($scope.changing && $scope.model.value) { $scope.model.value.generatedPassword = null; @@ -108,6 +110,13 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont //we are not changing, so the model needs to be null $scope.model.value = null; } + })); + + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } }); $scope.showReset = function() { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 8847db455b..9c37a9a2a9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -158,13 +158,18 @@ function contentPickerController($scope, dialogService, entityResource, editorSt $scope.renderModel = []; }; - $scope.$on("formSubmitting", function (ev, args) { + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { return i.id; }); $scope.model.value = trim(currIds.join(), ","); }); + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); + //load current data var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; entityResource.getByIds(modelIds, entityType).then(function (data) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html new file mode 100644 index 0000000000..b22b6baf83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html @@ -0,0 +1,31 @@ +