From fa7a46389c7bb1efbc6b673d9ab31b7fc54fc934 Mon Sep 17 00:00:00 2001 From: Jan Skovgaard Date: Mon, 14 Oct 2019 15:03:46 +0200 Subject: [PATCH] Split events.directive into separate event directives (#6533) --- .../components/events/deepBlur.directive.js | 45 +++ .../components/events/events.directive.js | 273 ------------------ .../events/onDelayedMouseleave.directive.js | 49 ++++ .../components/events/onDragEnd.directive.js | 24 ++ .../events/onDragEnter.directive.js | 24 ++ .../events/onDragLeave.directive.js | 40 +++ .../components/events/onDragOver.directive.js | 24 ++ .../events/onDragStart.directive.js | 24 ++ .../components/events/onDrop.directive.js | 24 ++ .../events/onOutsideClick.directive.js | 86 ++++++ .../events/onRightClick.directive.js | 30 ++ 11 files changed, 370 insertions(+), 273 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js delete mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js new file mode 100644 index 0000000000..fdff6459c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js @@ -0,0 +1,45 @@ + // A slightly modified version of https://github.com/myplanet/angular-deep-blur/blob/master/angular-deep-blur.js - Kudos to Ufuk Kayserilioglu (paracycle) + (function () { + 'use strict'; + + function DeepBlurDirective($timeout){ + + function controller($scope, $element, $attrs) { + var leaveExpr = $attrs.deepBlur, + dom = $element[0]; + + function containsDom(parent, dom) { + while (dom) { + if (dom === parent) { + return true; + } + dom = dom.parentNode; + } + return false; + } + + function onBlur(e) { + var targetElement = e.relatedTarget; + + if (!containsDom(dom, targetElement)) { + $timeout(function () { + $scope.$apply(leaveExpr); + }, 10); + } + } + + dom.addEventListener('blur', onBlur, true); + } + + var directive = { + restrict: 'A', + controller: controller + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('deepBlur', DeepBlurDirective); + + })(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js deleted file mode 100644 index 53aa7475c4..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js +++ /dev/null @@ -1,273 +0,0 @@ -/** -* @description Utillity directives for key and field events -**/ -angular.module('umbraco.directives') - - .directive('onDragEnter', function () { - return { - link: function (scope, elm, attrs) { - var f = function () { - scope.$apply(attrs.onDragEnter); - }; - elm.on("dragenter", f); - scope.$on("$destroy", function () { elm.off("dragenter", f); }); - } - }; - }) - - .directive('onDragLeave', function () { - return function (scope, elm, attrs) { - var f = function (event) { - var rect = this.getBoundingClientRect(); - var getXY = function getCursorPosition(event) { - var x, y; - - if (typeof event.clientX === 'undefined') { - // try touch screen - x = event.pageX + document.documentElement.scrollLeft; - y = event.pageY + document.documentElement.scrollTop; - } else { - x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; - y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; - } - - return { x: x, y: y }; - }; - - var e = getXY(event.originalEvent); - - // Check the mouseEvent coordinates are outside of the rectangle - if (e.x > rect.left + rect.width - 1 || e.x < rect.left || e.y > rect.top + rect.height - 1 || e.y < rect.top) { - scope.$apply(attrs.onDragLeave); - } - }; - - elm.on("dragleave", f); - scope.$on("$destroy", function () { elm.off("dragleave", f); }); - }; - }) - - .directive('onDragOver', function () { - return { - link: function (scope, elm, attrs) { - var f = function () { - scope.$apply(attrs.onDragOver); - }; - elm.on("dragover", f); - scope.$on("$destroy", function () { elm.off("dragover", f); }); - } - }; - }) - - .directive('onDragStart', function () { - return { - link: function (scope, elm, attrs) { - var f = function () { - scope.$apply(attrs.onDragStart); - }; - elm.on("dragstart", f); - scope.$on("$destroy", function () { elm.off("dragstart", f); }); - } - }; - }) - - .directive('onDragEnd', function () { - return { - link: function (scope, elm, attrs) { - var f = function () { - scope.$apply(attrs.onDragEnd); - }; - elm.on("dragend", f); - scope.$on("$destroy", function () { elm.off("dragend", f); }); - } - }; - }) - - .directive('onDrop', function () { - return { - link: function (scope, elm, attrs) { - var f = function () { - scope.$apply(attrs.onDrop); - }; - elm.on("drop", f); - scope.$on("$destroy", function () { elm.off("drop", f); }); - } - }; - }) - - .directive('onOutsideClick', function ($timeout, angularHelper) { - return function (scope, element, attrs) { - - var eventBindings = []; - - function oneTimeClick(event) { - var el = event.target.nodeName; - - //ignore link and button clicks - var els = ["INPUT", "A", "BUTTON"]; - if (els.indexOf(el) >= 0) { return; } - - // ignore clicks on new overlay - var parents = $(event.target).parents("a,button,.umb-overlay,.umb-tour"); - if (parents.length > 0) { - return; - } - - // ignore clicks on dialog from old dialog service - var oldDialog = $(event.target).parents("#old-dialog-service"); - if (oldDialog.length === 1) { - return; - } - - // ignore clicks in tinyMCE dropdown(floatpanel) - var floatpanel = $(event.target).closest(".mce-floatpanel"); - if (floatpanel.length === 1) { - return; - } - - // ignore clicks in flatpickr datepicker - var flatpickr = $(event.target).closest(".flatpickr-calendar"); - if (flatpickr.length === 1) { - return; - } - - //ignore clicks inside this element - if ($(element).has($(event.target)).length > 0) { - return; - } - - // please to not use angularHelper.safeApply here, it won't work - scope.$apply(attrs.onOutsideClick); - } - - - $timeout(function () { - - if ("bindClickOn" in attrs) { - - eventBindings.push(scope.$watch(function () { - return attrs.bindClickOn; - }, function (newValue) { - if (newValue === "true") { - $(document).on("click", oneTimeClick); - } else { - $(document).off("click", oneTimeClick); - } - })); - - } else { - $(document).on("click", oneTimeClick); - } - - scope.$on("$destroy", function () { - $(document).off("click", oneTimeClick); - - // unbind watchers - for (var e in eventBindings) { - eventBindings[e](); - } - - }); - }); // Temp removal of 1 sec timeout to prevent bug where overlay does not open. We need to find a better solution. - - }; - }) - - .directive('onRightClick', function ($parse) { - - document.oncontextmenu = function (e) { - if (e.target.hasAttribute('on-right-click')) { - e.preventDefault(); - e.stopPropagation(); - return false; - } - }; - - return function (scope, el, attrs) { - el.on('contextmenu', function (e) { - e.preventDefault(); - e.stopPropagation(); - var fn = $parse(attrs.onRightClick); - scope.$apply(function () { - fn(scope, { $event: e }); - }); - return false; - }); - }; - }) - - .directive('onDelayedMouseleave', function ($timeout, $parse) { - return { - - restrict: 'A', - - link: function (scope, element, attrs, ctrl) { - var active = false; - var fn = $parse(attrs.onDelayedMouseleave); - - var leave_f = function (event) { - var callback = function () { - fn(scope, { $event: event }); - }; - - active = false; - $timeout(function () { - if (active === false) { - scope.$apply(callback); - } - }, 650); - }; - - var enter_f = function (event, args) { - active = true; - }; - - - element.on("mouseleave", leave_f); - element.on("mouseenter", enter_f); - - //unsub events - scope.$on("$destroy", function () { - element.off("mouseleave", leave_f); - element.off("mouseenter", enter_f); - }); - } - }; - }) - - // A slightly modified version of https://github.com/myplanet/angular-deep-blur/blob/master/angular-deep-blur.js - Kudos to Ufuk Kayserilioglu (paracycle) - .directive('deepBlur', function ($timeout) { - return { - - restrict: 'A', - - controller: function ($scope, $element, $attrs) { - var leaveExpr = $attrs.deepBlur, - dom = $element[0]; - - function containsDom(parent, dom) { - while (dom) { - if (dom === parent) { - return true; - } - dom = dom.parentNode; - } - return false; - } - - function onBlur(e) { - var targetElement = e.relatedTarget; - - if (!containsDom(dom, targetElement)) { - $timeout(function () { - $scope.$apply(leaveExpr); - }, 10); - } - } - - dom.addEventListener('blur', onBlur, true); - } - }; - }); - - diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js new file mode 100644 index 0000000000..8493e49d77 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js @@ -0,0 +1,49 @@ +(function () { + 'use strict'; + + function onDelayedMouseleaveDirective($timeout, $parse){ + + function link(scope, element, attrs, ctrl) { + var active = false; + var fn = $parse(attrs.onDelayedMouseleave); + + var leave_f = function (event) { + var callback = function () { + fn(scope, { $event: event }); + }; + + active = false; + $timeout(function () { + if (active === false) { + scope.$apply(callback); + } + }, 650); + }; + + var enter_f = function (event, args) { + active = true; + }; + + + element.on("mouseleave", leave_f); + element.on("mouseenter", enter_f); + + //unsub events + scope.$on("$destroy", function () { + element.off("mouseleave", leave_f); + element.off("mouseenter", enter_f); + }); + } + + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDelayedMouseleave', onDelayedMouseleaveDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js new file mode 100644 index 0000000000..84501e10d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + function onDragEndDirective(){ + + function link(scope, elm, attrs) { + var f = function () { + scope.$apply(attrs.onDragEnd); + }; + elm.on("dragend", f); + scope.$on("$destroy", function () { elm.off("dragend", f); }); + } + + var directive = { + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDragEnd', onDragEndDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js new file mode 100644 index 0000000000..03ae9465d0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + function onDragEnterDirective(){ + + function link(scope, elm, attrs) { + var f = function () { + scope.$apply(attrs.onDragEnter); + }; + elm.on("dragenter", f); + scope.$on("$destroy", function () { elm.off("dragenter", f); }); + } + + var directive = { + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDragEnter', onDragEnterDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js new file mode 100644 index 0000000000..cd05ed9289 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js @@ -0,0 +1,40 @@ +(function () { + 'use strict'; + + function onDragLeaveDirective($timeout){ + + return function (scope, elm, attrs) { + var f = function (event) { + var rect = this.getBoundingClientRect(); + var getXY = function getCursorPosition(event) { + var x, y; + + if (typeof event.clientX === 'undefined') { + // try touch screen + x = event.pageX + document.documentElement.scrollLeft; + y = event.pageY + document.documentElement.scrollTop; + } else { + x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + return { x: x, y: y }; + }; + + var e = getXY(event.originalEvent); + + // Check the mouseEvent coordinates are outside of the rectangle + if (e.x > rect.left + rect.width - 1 || e.x < rect.left || e.y > rect.top + rect.height - 1 || e.y < rect.top) { + scope.$apply(attrs.onDragLeave); + } + }; + + elm.on("dragleave", f); + scope.$on("$destroy", function () { elm.off("dragleave", f); }); + }; + + } + + angular.module('umbraco.directives').directive('onDragLeave', onDragLeaveDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js new file mode 100644 index 0000000000..faf9050b8e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + function onDragOverDirective(){ + + function link(scope, elm, attrs) { + var f = function () { + scope.$apply(attrs.onDragOver); + }; + elm.on("dragover", f); + scope.$on("$destroy", function () { elm.off("dragover", f); }); + } + + var directive = { + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDragOver', onDragOverDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js new file mode 100644 index 0000000000..8da6211c08 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + function onDragStartDirective($timeout){ + + function link(scope, elm, attrs) { + var f = function () { + scope.$apply(attrs.onDragStart); + }; + elm.on("dragstart", f); + scope.$on("$destroy", function () { elm.off("dragstart", f); }); + } + + var directive = { + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDragStart', onDragStartDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js new file mode 100644 index 0000000000..632549f21b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + function onDropDirective(){ + + function link(scope, elm, attrs) { + var f = function () { + scope.$apply(attrs.onDrop); + }; + elm.on("drop", f); + scope.$on("$destroy", function () { elm.off("drop", f); }); + } + + var directive = { + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('onDrop', onDropDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js new file mode 100644 index 0000000000..a657fcbc55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js @@ -0,0 +1,86 @@ +(function () { + 'use strict'; + + function onOutsideClickDirective($timeout, angularHelper){ + + return function (scope, element, attrs) { + + var eventBindings = []; + + function oneTimeClick(event) { + var el = event.target.nodeName; + + //ignore link and button clicks + var els = ["INPUT", "A", "BUTTON"]; + if (els.indexOf(el) >= 0) { return; } + + // ignore clicks on new overlay + var parents = $(event.target).parents("a,button,.umb-overlay,.umb-tour"); + if (parents.length > 0) { + return; + } + + // ignore clicks on dialog from old dialog service + var oldDialog = $(event.target).parents("#old-dialog-service"); + if (oldDialog.length === 1) { + return; + } + + // ignore clicks in tinyMCE dropdown(floatpanel) + var floatpanel = $(event.target).closest(".mce-floatpanel"); + if (floatpanel.length === 1) { + return; + } + + // ignore clicks in flatpickr datepicker + var flatpickr = $(event.target).closest(".flatpickr-calendar"); + if (flatpickr.length === 1) { + return; + } + + //ignore clicks inside this element + if ($(element).has($(event.target)).length > 0) { + return; + } + + // please to not use angularHelper.safeApply here, it won't work + scope.$apply(attrs.onOutsideClick); + } + + + $timeout(function () { + + if ("bindClickOn" in attrs) { + + eventBindings.push(scope.$watch(function () { + return attrs.bindClickOn; + }, function (newValue) { + if (newValue === "true") { + $(document).on("click", oneTimeClick); + } else { + $(document).off("click", oneTimeClick); + } + })); + + } else { + $(document).on("click", oneTimeClick); + } + + scope.$on("$destroy", function () { + $(document).off("click", oneTimeClick); + + // unbind watchers + for (var e in eventBindings) { + eventBindings[e](); + } + + }); + }); // Temp removal of 1 sec timeout to prevent bug where overlay does not open. We need to find a better solution. + + }; + + } + + angular.module('umbraco.directives').directive('onOutsideClick', onOutsideClickDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js new file mode 100644 index 0000000000..6b818997d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js @@ -0,0 +1,30 @@ +(function () { + 'use strict'; + + function onRightClickDirective($parse){ + + document.oncontextmenu = function (e) { + if (e.target.hasAttribute('on-right-click')) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + }; + + return function (scope, el, attrs) { + el.on('contextmenu', function (e) { + e.preventDefault(); + e.stopPropagation(); + var fn = $parse(attrs.onRightClick); + scope.$apply(function () { + fn(scope, { $event: e }); + }); + return false; + }); + }; + + } + + angular.module('umbraco.directives').directive('onRightClick', onRightClickDirective); + +})();