diff --git a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
index 8ce699a537..542b454f2c 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
@@ -1,45 +1,54 @@
-/* pubsub - based on https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js*/
-function eventsService($q) {
- var cache = {};
+/** Used to broadcast and listen for global events and allow the ability to add async listeners to the callbacks */
+function eventsService($q, $rootScope) {
+
+ return {
+
+ /** raise an event with a given name, returns an array of promises for each listener */
+ publish: function (name, args) {
- return {
- publish: function(){
-
- var args = [].splice.call(arguments,0);
- var topic = args[0];
- var deferred = $q.defer();
- args.splice(0,1);
+ //there are no listeners
+ if (!$rootScope.$$listeners[name]) {
+ return [];
+ }
- if(cache[topic]){
- $.each(cache[topic], function() {
- this.apply(null, args || []);
- });
- deferred.resolve.apply(null, args);
- }else{
- deferred.resolve.apply(null, args);
- }
+ //setup a deferred promise for each listener
+ var deferred = [];
+ for (var i = 0; i < $rootScope.$$listeners[name].length; i++) {
+ deferred.push($q.defer());
+ }
+ //create a new event args object to pass to the
+ // $broadcast containing methods that will allow listeners
+ // to return data in an async if required
+ var eventArgs = {
+ args: args,
+ reject: function (a) {
+ deferred.pop().reject(a);
+ },
+ resolve: function (a) {
+ deferred.pop().resolve(a);
+ }
+ };
+
+ //send the event
+ $rootScope.$broadcast(name, eventArgs);
+
+ //return an array of promises
+ var promises = _.map(deferred, function(p) {
+ return p.promise;
+ });
+ return promises;
+ },
- return deferred.promise;
- },
-
- subscribe: function(topic, callback) {
- if(!cache[topic]) {
- cache[topic] = [];
- }
- cache[topic].push(callback);
- return [topic, callback];
+ /** subscribe to a method, or use scope.$on = same thing */
+ subscribe: function(name, callback) {
+ return $rootScope.$on(name, callback);
},
+ /** pass in the result of subscribe to this method, or just call the method returned from subscribe to unsubscribe */
unsubscribe: function(handle) {
- var t = handle[0];
-
- if(cache[t]){
- $.each(cache[t], function(idx){
- if(this === handle[1]){
- cache[t].splice(idx, 1);
- }
- });
- }
+ if (angular.isFunction(handle)) {
+ handle();
+ }
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/contentpicker.controller.js
index 2dd47ff5cd..3c9ce94bf9 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/contentpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/contentpicker.controller.js
@@ -43,34 +43,33 @@ angular.module("umbraco").controller("Umbraco.Dialogs.ContentPickerController",
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Dialogs.ContentPickerController.Select", args).then(function(args){
- if(dialogOptions && dialogOptions.multiPicker){
-
- var c = $(args.event.target.parentElement);
- if(!args.node.selected){
- args.node.selected = true;
-
- var temp = "";
- var icon = c.find("i.umb-tree-icon");
- if(icon.length > 0){
- icon.hide().after(temp);
- }else{
- c.prepend(temp);
- }
-
- }else{
- args.node.selected = false;
- c.find(".temporary").remove();
- c.find("i.umb-tree-icon").show();
- }
+ eventsService.publish("Umbraco.Dialogs.ContentPickerController.Select", args);
+
+ if (dialogOptions && dialogOptions.multiPicker) {
- $scope.select(args.node);
+ var c = $(args.event.target.parentElement);
+ if (!args.node.selected) {
+ args.node.selected = true;
- }else{
- $scope.submit(args.node);
- }
-
- });
+ var temp = "";
+ var icon = c.find("i.umb-tree-icon");
+ if (icon.length > 0) {
+ icon.hide().after(temp);
+ } else {
+ c.prepend(temp);
+ }
+
+ } else {
+ args.node.selected = false;
+ c.find(".temporary").remove();
+ c.find("i.umb-tree-icon").show();
+ }
+
+ $scope.select(args.node);
+
+ } else {
+ $scope.submit(args.node);
+ }
});
});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js
index a40fb110fb..ff75f595bf 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js
@@ -30,40 +30,40 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Dialogs.LinkPickerController.Select", args).then(function(args){
- var c = $(args.event.target.parentElement);
+ eventsService.publish("Umbraco.Dialogs.LinkPickerController.Select", args);
+
+ var c = $(args.event.target.parentElement);
- //renewing
- if(args.node !== $scope.target){
- if($scope.selectedEl){
- $scope.selectedEl.find(".temporary").remove();
- $scope.selectedEl.find("i.umb-tree-icon").show();
- }
+ //renewing
+ if (args.node !== $scope.target) {
+ if ($scope.selectedEl) {
+ $scope.selectedEl.find(".temporary").remove();
+ $scope.selectedEl.find("i.umb-tree-icon").show();
+ }
- $scope.selectedEl = c;
- $scope.target = args.node;
- $scope.target.name = args.node.name;
+ $scope.selectedEl = c;
+ $scope.target = args.node;
+ $scope.target.name = args.node.name;
- $scope.selectedEl.find("i.umb-tree-icon")
- .hide()
- .after("");
-
- if(args.node.id < 0){
- $scope.target.url = "/";
- }else{
- contentResource.getNiceUrl(args.node.id).then(function(url){
- $scope.target.url = angular.fromJson(url);
- });
- }
- }else{
- $scope.target = undefined;
- //resetting
- if($scope.selectedEl){
- $scope.selectedEl.find(".temporary").remove();
- $scope.selectedEl.find("i.umb-tree-icon").show();
- }
- }
- });
+ $scope.selectedEl.find("i.umb-tree-icon")
+ .hide()
+ .after("");
+
+ if (args.node.id < 0) {
+ $scope.target.url = "/";
+ } else {
+ contentResource.getNiceUrl(args.node.id).then(function (url) {
+ $scope.target.url = angular.fromJson(url);
+ });
+ }
+ } else {
+ $scope.target = undefined;
+ //resetting
+ if ($scope.selectedEl) {
+ $scope.selectedEl.find(".temporary").remove();
+ $scope.selectedEl.find("i.umb-tree-icon").show();
+ }
+ }
});
});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.controller.js
index ba834e5e9e..8e1de23cf9 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.controller.js
@@ -77,15 +77,16 @@ angular.module("umbraco")
$scope.gotoFolder(image.id);
}
else if (image.contentTypeAlias.toLowerCase() == 'image') {
- eventsService.publish("Umbraco.Dialogs.MediaPickerController.Select", image).then(function (img) {
- if (dialogOptions && dialogOptions.multiPicker) {
- $scope.select(img);
- img.cssclass = ($scope.dialogData.selection.indexOf(img) > -1) ? "selected" : "";
- }
- else {
- $scope.submit(img);
- }
- });
+
+ eventsService.publish("Umbraco.Dialogs.MediaPickerController.Select", image);
+
+ if (dialogOptions && dialogOptions.multiPicker) {
+ $scope.select(image);
+ image.cssclass = ($scope.dialogData.selection.indexOf(image) > -1) ? "selected" : "";
+ }
+ else {
+ $scope.submit(image);
+ }
}
ev.preventDefault();
@@ -98,14 +99,14 @@ angular.module("umbraco")
}
else if (image.contentTypeAlias.toLowerCase() == 'image') {
- eventsService.publish("Umbraco.Dialogs.MediaPickerController.Select", image).then(function(img) {
- if (dialogOptions && dialogOptions.multiPicker) {
- $scope.select(img);
- }
- else {
- $scope.submit(img);
- }
- });
+ eventsService.publish("Umbraco.Dialogs.MediaPickerController.Select", image);
+
+ if (dialogOptions && dialogOptions.multiPicker) {
+ $scope.select(image);
+ }
+ else {
+ $scope.submit(image);
+ }
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/membergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/membergrouppicker.controller.js
index df9f7bc729..3b3fac0d11 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/membergrouppicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/membergrouppicker.controller.js
@@ -40,29 +40,28 @@ angular.module("umbraco").controller("Umbraco.Dialogs.MemberGroupPickerControlle
args.event.stopPropagation();
- eventsService.publish("Umbraco.Dialogs.MemberGroupPickerController.Select", args).then(function(a) {
+ eventsService.publish("Umbraco.Dialogs.MemberGroupPickerController.Select", args);
+
+ //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
+ //from the server in this method.
+ select(args.node.name, args.node.id);
- //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
- //from the server in this method.
- select(a.node.name, a.node.id);
-
- if (dialogOptions.multiPicker) {
- var c = $(a.event.target.parentElement);
- if (!a.node.selected) {
- a.node.selected = true;
- c.find("i.umb-tree-icon").hide()
- .after("");
- }
- else {
-
- remove(a.node.name, a.node.id);
-
- a.node.selected = false;
- c.find(".temporary").remove();
- c.find("i.umb-tree-icon").show();
- }
+ if (dialogOptions.multiPicker) {
+ var c = $(args.event.target.parentElement);
+ if (!args.node.selected) {
+ args.node.selected = true;
+ c.find("i.umb-tree-icon").hide()
+ .after("");
}
- });
+ else {
+
+ remove(args.node.name, args.node.id);
+
+ args.node.selected = false;
+ c.find(".temporary").remove();
+ c.find("i.umb-tree-icon").show();
+ }
+ }
});
});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js
index 39b03dca57..8731c62e44 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js
@@ -62,27 +62,26 @@ angular.module("umbraco").controller("Umbraco.Dialogs.MemberPickerController",
return;
}
- eventsService.publish("Umbraco.Dialogs.MemberPickerController.Select", args).then(function(a) {
+ eventsService.publish("Umbraco.Dialogs.MemberPickerController.Select", args);
+
+ //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
+ //from the server in this method.
+ select(args.node.name, args.node.id);
- //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
- //from the server in this method.
- select(a.node.name, a.node.id);
+ if (dialogOptions && dialogOptions.multipicker) {
- if (dialogOptions && dialogOptions.multipicker) {
-
- var c = $(a.event.target.parentElement);
- if (!a.node.selected) {
- a.node.selected = true;
- c.find("i.umb-tree-icon").hide()
- .after("");
- }
- else {
- a.node.selected = false;
- c.find(".temporary").remove();
- c.find("i.umb-tree-icon").show();
- }
+ var c = $(args.event.target.parentElement);
+ if (!args.node.selected) {
+ args.node.selected = true;
+ c.find("i.umb-tree-icon").hide()
+ .after("");
}
- });
+ else {
+ args.node.selected = false;
+ c.find(".temporary").remove();
+ c.find("i.umb-tree-icon").show();
+ }
+ }
});
});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js
index 9358ea08b8..6030a52629 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js
@@ -167,35 +167,35 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Dialogs.TreePickerController.Select", args).then(function (a) {
- if (a.node.filtered) {
- return;
- }
+ eventsService.publish("Umbraco.Dialogs.TreePickerController.Select", args);
+
+ if (args.node.filtered) {
+ return;
+ }
- //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
- //from the server in this method.
- select(a.node.name, a.node.id);
+ //This is a tree node, so we don't have an entity to pass in, it will need to be looked up
+ //from the server in this method.
+ select(args.node.name, args.node.id);
- //ui...
- if ($scope.multiPicker) {
- var c = $(a.event.target.parentElement);
- if (!a.node.selected) {
- a.node.selected = true;
- var temp = "";
- var icon = c.find("i.umb-tree-icon");
- if (icon.length > 0) {
- icon.hide().after(temp);
- }
- else {
- c.prepend(temp);
- }
- }
- else {
- a.node.selected = false;
- c.find(".temporary").remove();
- c.find("i.umb-tree-icon").show();
- }
- }
- });
+ //ui...
+ if ($scope.multiPicker) {
+ var c = $(args.event.target.parentElement);
+ if (!args.node.selected) {
+ args.node.selected = true;
+ var temp = "";
+ var icon = c.find("i.umb-tree-icon");
+ if (icon.length > 0) {
+ icon.hide().after(temp);
+ }
+ else {
+ c.prepend(temp);
+ }
+ }
+ else {
+ args.node.selected = false;
+ c.find(".temporary").remove();
+ c.find("i.umb-tree-icon").show();
+ }
+ }
});
});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
index 3b4a2cdbed..486c1dda10 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
@@ -10,24 +10,25 @@ angular.module("umbraco")
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Editors.Content.CopyController.Select", args).then(function(args){
- var c = $(args.event.target.parentElement);
- if($scope.selectedEl){
- $scope.selectedEl.find(".temporary").remove();
- $scope.selectedEl.find("i.umb-tree-icon").show();
- }
+ eventsService.publish("Umbraco.Editors.Content.CopyController.Select", args);
+
+ var c = $(args.event.target.parentElement);
+ if ($scope.selectedEl) {
+ $scope.selectedEl.find(".temporary").remove();
+ $scope.selectedEl.find("i.umb-tree-icon").show();
+ }
+
+ var temp = "";
+ var icon = c.find("i.umb-tree-icon");
+ if (icon.length > 0) {
+ icon.hide().after(temp);
+ } else {
+ c.prepend(temp);
+ }
+
+ $scope.target = args.node;
+ $scope.selectedEl = c;
- var temp = "";
- var icon = c.find("i.umb-tree-icon");
- if(icon.length > 0){
- icon.hide().after(temp);
- }else{
- c.prepend(temp);
- }
-
- $scope.target = args.node;
- $scope.selectedEl = c;
- });
});
$scope.copy = function(){
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js
index cedb409117..7283a90073 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js
@@ -10,26 +10,26 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Editors.Content.MoveController.Select", args).then(function(args){
- var c = $(args.event.target.parentElement);
-
- if($scope.selectedEl){
- $scope.selectedEl.find(".temporary").remove();
- $scope.selectedEl.find("i.umb-tree-icon").show();
- }
+ eventsService.publish("Umbraco.Editors.Content.MoveController.Select", args);
+
+ var c = $(args.event.target.parentElement);
- var temp = "";
- var icon = c.find("i.umb-tree-icon");
- if(icon.length > 0){
- icon.hide().after(temp);
- }else{
- c.prepend(temp);
- }
+ if ($scope.selectedEl) {
+ $scope.selectedEl.find(".temporary").remove();
+ $scope.selectedEl.find("i.umb-tree-icon").show();
+ }
-
- $scope.target = args.node;
- $scope.selectedEl = c;
- });
+ var temp = "";
+ var icon = c.find("i.umb-tree-icon");
+ if (icon.length > 0) {
+ icon.hide().after(temp);
+ } else {
+ c.prepend(temp);
+ }
+
+
+ $scope.target = args.node;
+ $scope.selectedEl = c;
});
$scope.move = function(){
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.move.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.move.controller.js
index 8a7d807c59..a705229221 100644
--- a/src/Umbraco.Web.UI.Client/src/views/media/media.move.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/media/media.move.controller.js
@@ -10,19 +10,20 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
args.event.preventDefault();
args.event.stopPropagation();
- eventsService.publish("Umbraco.Editors.Media.MoveController.Select", args).then(function(args){
- var c = $(args.event.target.parentElement);
- if($scope.selectedEl){
- $scope.selectedEl.find(".temporary").remove();
- $scope.selectedEl.find("i.umb-tree-icon").show();
- }
+ eventsService.publish("Umbraco.Editors.Media.MoveController.Select", args);
+
+ var c = $(args.event.target.parentElement);
+ if ($scope.selectedEl) {
+ $scope.selectedEl.find(".temporary").remove();
+ $scope.selectedEl.find("i.umb-tree-icon").show();
+ }
- c.find("i.umb-tree-icon").hide()
- .after("");
-
- $scope.target = args.node;
- $scope.selectedEl = c;
- });
+ c.find("i.umb-tree-icon").hide()
+ .after("");
+
+ $scope.target = args.node;
+ $scope.selectedEl = c;
+
});
$scope.move = function(){
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/events-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/events-service.spec.js
index 49738bbccd..a696bdd0e4 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/common/services/events-service.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/events-service.spec.js
@@ -17,41 +17,67 @@ describe('angular event tests', function () {
val: ""
};
- eventsService.subscribe("testEvent", function (args) {
- args.val = "changed";
+ eventsService.subscribe("testEvent", function (e, args) {
+ args.args.val = "changed";
});
- eventsService.publish("testEvent", eventArgs).then(function (args) {
- expect(eventArgs.val).toBe("changed");
- expect(args.val).toBe("changed");
- });
+ eventsService.publish("testEvent", eventArgs);
+
+ expect(eventArgs.val).toBe("changed");
$rootScope.$digest();
});
- //NOTE: This will fail because our eventsService doesn't actually wait for async events to finish.
+ it('will handle 2 non async process', function () {
+ var eventArgs = {
+ val: ""
+ };
- //it('will handle one async process', function () {
- // var eventArgs = {
- // val: ""
- // };
+ eventsService.subscribe("testEvent", function (e, args) {
+ args.args.val = "changed";
+ });
+
+ eventsService.subscribe("testEvent", function (e, args) {
+ args.args.val = "changed1";
+ });
- // eventsService.subscribe("testEvent", function (args) {
- // $timeout(function() {
- // args.val = "changed";
- // }, 1000);
- // });
+ eventsService.publish("testEvent", eventArgs);
- // eventsService.publish("testEvent", eventArgs).then(function (args) {
- // expect(eventArgs.val).toBe("changed");
- // expect(args.val).toBe("changed");
- // });
+ expect(eventArgs.val).toBe("changed1");
- // $rootScope.$digest();
- // $timeout.flush();
- //});
+ $rootScope.$digest();
+ });
+
+ it('will handle one async process', function () {
+ var eventArgs = {
+ val: ""
+ };
+
+ eventsService.subscribe("testEvent", function (e, msg) {
+ $timeout(function () {
+ msg.args.val = "changed";
+ //NOTE: We could resolve anything here
+ msg.resolve(msg.args);
+ }, 1000);
+ });
+
+ var promises = eventsService.publish("testEvent", eventArgs);
+
+ //this won't be changed yet
+ expect(eventArgs.val).toBe("");
+
+ promises[0].then(function (args) {
+ console.log("WOOT");
+ expect(args.val).toBe("changed");
+ expect(eventArgs.val).toBe("changed");
+ });
+
+ $rootScope.$digest();
+ $timeout.flush();
+ });
- it('will wait to execute after all handlers', function () {
+ //NOTE: This logic has been merged into the eventsService
+ it('POC will wait to execute after all handlers', function () {
//assign multiple listeners