off-click.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. 'use strict';
  2. /**
  3. * It's like click, but when you don't click on your element.
  4. */
  5. app.directive('offClick', ['$document', '$timeout', function ($document, $timeout) {
  6. function targetInFilter(target, filter) {
  7. if (!target || !filter) return false;
  8. var elms = angular.element(document.querySelectorAll(filter));
  9. var elmsLen = elms.length;
  10. for (var i = 0; i < elmsLen; ++i)
  11. if (elms[i].contains(target)) return true;
  12. return false;
  13. }
  14. return {
  15. restrict: 'A',
  16. scope: {
  17. offClick: '&',
  18. offClickIf: '&'
  19. },
  20. link: function (scope, elm, attr) {
  21. if (attr.offClickIf) {
  22. scope.$watch(scope.offClickIf, function (newVal, oldVal) {
  23. if (newVal && !oldVal) {
  24. $timeout(function () {
  25. $document.on('click', handler);
  26. });
  27. } else if (!newVal) {
  28. $document.off('click', handler);
  29. }
  30. }
  31. );
  32. } else {
  33. $document.on('click', handler);
  34. }
  35. scope.$on('$destroy', function () {
  36. $document.off('click', handler);
  37. });
  38. function handler(event) {
  39. // This filters out artificial click events. Example: If you hit enter on a form to submit it, an
  40. // artificial click event gets triggered on the form's submit button.
  41. if (event.pageX == 0 && event.pageY == 0) return;
  42. var target = event.target || event.srcElement;
  43. if (!(elm[0].contains(target) || targetInFilter(target, attr.offClickFilter))) {
  44. scope.$apply(scope.offClick());
  45. }
  46. }
  47. }
  48. };
  49. }]);