Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libs/bower_components/ngDialog/js/ngDialog.js')
-rw-r--r--libs/bower_components/ngDialog/js/ngDialog.js1291
1 files changed, 948 insertions, 343 deletions
diff --git a/libs/bower_components/ngDialog/js/ngDialog.js b/libs/bower_components/ngDialog/js/ngDialog.js
index 5c393901e8..ddd287c142 100644
--- a/libs/bower_components/ngDialog/js/ngDialog.js
+++ b/libs/bower_components/ngDialog/js/ngDialog.js
@@ -1,348 +1,953 @@
/*
* ngDialog - easy modals and popup windows
* http://github.com/likeastore/ngDialog
- * (c) 2013 MIT License, https://likeastore.com
+ * (c) 2013-2015 MIT License, https://likeastore.com
*/
-(function (window, angular, undefined) {
- 'use strict';
-
- var module = angular.module('ngDialog', []);
-
- var $el = angular.element;
- var isDef = angular.isDefined;
- var style = (document.body || document.documentElement).style;
- var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
- var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
- var forceBodyReload = false;
-
- module.provider('ngDialog', function () {
- var defaults = this.defaults = {
- className: 'ngdialog-theme-default',
- plain: false,
- showClose: true,
- closeByDocument: true,
- closeByEscape: true,
- appendTo: false
- };
-
- this.setForceBodyReload = function (_useIt) {
- forceBodyReload = _useIt || false;
- };
-
- this.setDefaults = function (newDefaults) {
- angular.extend(defaults, newDefaults);
- };
-
- var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};
-
- this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
- function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
- var $body = $document.find('body');
- if (forceBodyReload) {
- $rootScope.$on('$locationChangeSuccess', function () {
- $body = $document.find('body');
- });
- }
-
- var privateMethods = {
- onDocumentKeydown: function (event) {
- if (event.keyCode === 27) {
- publicMethods.close('$escape');
- }
- },
-
- setBodyPadding: function (width) {
- var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
- $body.css('padding-right', (originalBodyPadding + width) + 'px');
- $body.data('ng-dialog-original-padding', originalBodyPadding);
- },
-
- resetBodyPadding: function () {
- var originalBodyPadding = $body.data('ng-dialog-original-padding');
- if (originalBodyPadding) {
- $body.css('padding-right', originalBodyPadding + 'px');
- } else {
- $body.css('padding-right', '');
- }
- },
-
- closeDialog: function ($dialog, value) {
- var id = $dialog.attr('id');
- if (typeof window.Hammer !== 'undefined') {
- window.Hammer($dialog[0]).off('tap', closeByDocumentHandler);
- } else {
- $dialog.unbind('click');
- }
-
- if (dialogsCount === 1) {
- $body.unbind('keydown');
- }
-
- if (!$dialog.hasClass("ngdialog-closing")){
- dialogsCount -= 1;
- }
-
- if (animationEndSupport) {
- $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
- $dialog.scope().$destroy();
- $dialog.remove();
- if (dialogsCount === 0) {
- $body.removeClass('ngdialog-open');
- privateMethods.resetBodyPadding();
- }
- $rootScope.$broadcast('ngDialog.closed', $dialog);
- }).addClass('ngdialog-closing');
- } else {
- $dialog.scope().$destroy();
- $dialog.remove();
- if (dialogsCount === 0) {
- $body.removeClass('ngdialog-open');
- privateMethods.resetBodyPadding();
- }
- $rootScope.$broadcast('ngDialog.closed', $dialog);
- }
- if (defers[id]) {
- defers[id].resolve({
- id: id,
- value: value,
- $dialog: $dialog,
- remainingDialogs: dialogsCount
- });
- delete defers[id];
- }
- }
- };
-
- var publicMethods = {
-
- /*
- * @param {Object} options:
- * - template {String} - id of ng-template, url for partial, plain string (if enabled)
- * - plain {Boolean} - enable plain string templates, default false
- * - scope {Object}
- * - controller {String}
- * - className {String} - dialog theme class
- * - showClose {Boolean} - show close button, default true
- * - closeByEscape {Boolean} - default true
- * - closeByDocument {Boolean} - default true
- *
- * @return {Object} dialog
- */
- open: function (opts) {
- var self = this;
- var options = angular.copy(defaults);
-
- opts = opts || {};
- angular.extend(options, opts);
-
- globalID += 1;
-
- self.latestID = 'ngdialog' + globalID;
-
- var defer;
- defers[self.latestID] = defer = $q.defer();
-
- var scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
- var $dialog, $dialogParent;
-
- $q.when(loadTemplate(options.template)).then(function (template) {
- template = angular.isString(template) ?
- template :
- template.data && angular.isString(template.data) ?
- template.data :
- '';
-
- $templateCache.put(options.template, template);
-
- if (options.showClose) {
- template += '<div class="ngdialog-close"></div>';
- }
-
- self.$result = $dialog = $el('<div id="ngdialog' + globalID + '" class="ngdialog"></div>');
- $dialog.html('<div class="ngdialog-overlay"></div><div class="ngdialog-content">' + template + '</div>');
-
- if (options.data && angular.isString(options.data)) {
- var firstLetter = options.data.replace(/^\s*/, '')[0];
- scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : options.data;
- } else if (options.data && angular.isObject(options.data)) {
- scope.ngDialogData = angular.fromJson(angular.toJson(options.data));
- }
-
- if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
- var controllerInstance = $controller(options.controller, {
- $scope: scope,
- $element: $dialog
- });
- $dialog.data('$ngDialogControllerController', controllerInstance);
- }
-
- if (options.className) {
- $dialog.addClass(options.className);
- }
-
- if (options.appendTo && angular.isString(options.appendTo)) {
- $dialogParent = angular.element(document.querySelector(options.appendTo));
- } else {
- $dialogParent = $body;
- }
-
- scope.closeThisDialog = function (value) {
- privateMethods.closeDialog($dialog, value);
- };
-
- $timeout(function () {
- $compile($dialog)(scope);
-
- var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
- $body.addClass('ngdialog-open');
- var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
- if (scrollBarWidth > 0) {
- privateMethods.setBodyPadding(scrollBarWidth);
- }
- $dialogParent.append($dialog);
- $rootScope.$broadcast('ngDialog.opened', $dialog);
- });
-
- if (options.closeByEscape) {
- $body.bind('keydown', privateMethods.onDocumentKeydown);
- }
-
- closeByDocumentHandler = function (event) {
- var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
- var isCloseBtn = $el(event.target).hasClass('ngdialog-close');
-
- if (isOverlay || isCloseBtn) {
- publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
- }
- };
-
- if (typeof window.Hammer !== 'undefined') {
- window.Hammer($dialog[0]).on('tap', closeByDocumentHandler);
- } else {
- $dialog.bind('click', closeByDocumentHandler);
- }
-
- dialogsCount += 1;
-
- return publicMethods;
- });
-
- return {
- id: 'ngdialog' + globalID,
- closePromise: defer.promise,
- close: function(value) {
- privateMethods.closeDialog($dialog, value);
- }
- };
-
- function loadTemplate (tmpl) {
- if (!tmpl) {
- return 'Empty template';
- }
-
- if (angular.isString(tmpl) && options.plain) {
- return tmpl;
- }
-
- return $templateCache.get(tmpl) || $http.get(tmpl, { cache: true });
- }
- },
-
- /*
- * @param {Object} options:
- * - template {String} - id of ng-template, url for partial, plain string (if enabled)
- * - plain {Boolean} - enable plain string templates, default false
- * - scope {Object}
- * - controller {String}
- * - className {String} - dialog theme class
- * - showClose {Boolean} - show close button, default true
- * - closeByEscape {Boolean} - default false
- * - closeByDocument {Boolean} - default false
- *
- * @return {Object} dialog
- */
- openConfirm: function (opts) {
- var defer = $q.defer();
-
- var options = {
- closeByEscape: false,
- closeByDocument: false
- };
- angular.extend(options, opts);
-
- options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
- options.scope.confirm = function (value) {
- defer.resolve(value);
- openResult.close(value);
- };
-
- var openResult = publicMethods.open(options);
- openResult.closePromise.then(function (data) {
- if (data) {
- return defer.reject(data.value);
- }
- return defer.reject();
- });
-
- return defer.promise;
- },
-
- /*
- * @param {String} id
- * @return {Object} dialog
- */
- close: function (id, value) {
- var $dialog = $el(document.getElementById(id));
-
- if ($dialog.length) {
- privateMethods.closeDialog($dialog, value);
- } else {
- publicMethods.closeAll(value);
- }
-
- return publicMethods;
- },
-
- closeAll: function (value) {
- var $all = document.querySelectorAll('.ngdialog');
-
- angular.forEach($all, function (dialog) {
- privateMethods.closeDialog($el(dialog), value);
- });
- }
- };
-
- return publicMethods;
- }];
- });
-
- module.directive('ngDialog', ['ngDialog', function (ngDialog) {
- return {
- restrict: 'A',
- scope : {
- ngDialogScope : '='
- },
- link: function (scope, elem, attrs) {
- elem.on('click', function (e) {
- e.preventDefault();
-
- var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
- angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);
-
- ngDialog.open({
- template: attrs.ngDialog,
- className: attrs.ngDialogClass,
- controller: attrs.ngDialogController,
- scope: ngDialogScope ,
- data: attrs.ngDialogData,
- showClose: attrs.ngDialogShowClose === 'false' ? false : true,
- closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : true,
- closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : true
- });
- });
- }
- };
- }]);
-
-})(window, window.angular);
+(function (root, factory) {
+ if (typeof module !== 'undefined' && module.exports) {
+ // CommonJS
+ if (typeof angular === 'undefined') {
+ factory(require('angular'));
+ } else {
+ factory(angular);
+ }
+ module.exports = 'ngDialog';
+ } else if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(['angular'], factory);
+ } else {
+ // Global Variables
+ factory(root.angular);
+ }
+}(this, function (angular) {
+ 'use strict';
+
+ var m = angular.module('ngDialog', []);
+
+ var $el = angular.element;
+ var isDef = angular.isDefined;
+ var style = (document.body || document.documentElement).style;
+ var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
+ var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
+ var focusableElementSelector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
+ var disabledAnimationClass = 'ngdialog-disabled-animation';
+ var forceElementsReload = { html: false, body: false };
+ var scopes = {};
+ var openIdStack = [];
+ var activeBodyClasses = [];
+ var keydownIsBound = false;
+ var openOnePerName = false;
+ var closeByNavigationDialogStack = [];
+
+ var UI_ROUTER_VERSION_LEGACY = 'legacy';
+ var UI_ROUTER_VERSION_ONE_PLUS = '1.0.0+';
+
+ m.provider('ngDialog', function () {
+ var defaults = this.defaults = {
+ className: 'ngdialog-theme-default',
+ appendClassName: '',
+ disableAnimation: false,
+ plain: false,
+ showClose: true,
+ closeByDocument: true,
+ closeByEscape: true,
+ closeByNavigation: false,
+ appendTo: false,
+ preCloseCallback: false,
+ onOpenCallback: false,
+ overlay: true,
+ cache: true,
+ trapFocus: true,
+ preserveFocus: true,
+ ariaAuto: true,
+ ariaRole: null,
+ ariaLabelledById: null,
+ ariaLabelledBySelector: null,
+ ariaDescribedById: null,
+ ariaDescribedBySelector: null,
+ bodyClassName: 'ngdialog-open',
+ width: null,
+ height: null
+ };
+
+ this.setForceHtmlReload = function (_useIt) {
+ forceElementsReload.html = _useIt || false;
+ };
+
+ this.setForceBodyReload = function (_useIt) {
+ forceElementsReload.body = _useIt || false;
+ };
+
+ this.setDefaults = function (newDefaults) {
+ angular.extend(defaults, newDefaults);
+ };
+
+ this.setOpenOnePerName = function (isOpenOne) {
+ openOnePerName = isOpenOne || false;
+ };
+
+ var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};
+
+ this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller', '$injector',
+ function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller, $injector) {
+ var $elements = [];
+
+ var privateMethods = {
+ onDocumentKeydown: function (event) {
+ if (event.keyCode === 27) {
+ publicMethods.close('$escape');
+ }
+ },
+
+ activate: function($dialog) {
+ var options = $dialog.data('$ngDialogOptions');
+
+ if (options.trapFocus) {
+ $dialog.on('keydown', privateMethods.onTrapFocusKeydown);
+
+ // Catch rogue changes (eg. after unfocusing everything by clicking a non-focusable element)
+ $elements.body.on('keydown', privateMethods.onTrapFocusKeydown);
+ }
+ },
+
+ deactivate: function ($dialog) {
+ $dialog.off('keydown', privateMethods.onTrapFocusKeydown);
+ $elements.body.off('keydown', privateMethods.onTrapFocusKeydown);
+ },
+
+ deactivateAll: function (els) {
+ angular.forEach(els,function(el) {
+ var $dialog = angular.element(el);
+ privateMethods.deactivate($dialog);
+ });
+ },
+
+ setBodyPadding: function (width) {
+ var originalBodyPadding = parseInt(($elements.body.css('padding-right') || 0), 10);
+ $elements.body.css('padding-right', (originalBodyPadding + width) + 'px');
+ $elements.body.data('ng-dialog-original-padding', originalBodyPadding);
+ $rootScope.$broadcast('ngDialog.setPadding', width);
+ },
+
+ resetBodyPadding: function () {
+ var originalBodyPadding = $elements.body.data('ng-dialog-original-padding');
+ if (originalBodyPadding) {
+ $elements.body.css('padding-right', originalBodyPadding + 'px');
+ } else {
+ $elements.body.css('padding-right', '');
+ }
+ $rootScope.$broadcast('ngDialog.setPadding', 0);
+ },
+
+ performCloseDialog: function ($dialog, value) {
+ var options = $dialog.data('$ngDialogOptions');
+ var id = $dialog.attr('id');
+ var scope = scopes[id];
+ privateMethods.deactivate($dialog);
+
+ if (!scope) {
+ // Already closed
+ return;
+ }
+
+ if (typeof $window.Hammer !== 'undefined') {
+ var hammerTime = scope.hammerTime;
+ hammerTime.off('tap', closeByDocumentHandler);
+ hammerTime.destroy && hammerTime.destroy();
+ delete scope.hammerTime;
+ } else {
+ $dialog.unbind('click');
+ }
+
+ if (dialogsCount === 1) {
+ $elements.body.unbind('keydown', privateMethods.onDocumentKeydown);
+ }
+
+ if (!$dialog.hasClass('ngdialog-closing')){
+ dialogsCount -= 1;
+ }
+
+ var previousFocus = $dialog.data('$ngDialogPreviousFocus');
+ if (previousFocus && previousFocus.focus) {
+ previousFocus.focus();
+ }
+
+ $rootScope.$broadcast('ngDialog.closing', $dialog, value);
+ dialogsCount = dialogsCount < 0 ? 0 : dialogsCount;
+ if (animationEndSupport && !options.disableAnimation) {
+ scope.$destroy();
+ $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
+ privateMethods.closeDialogElement($dialog, value);
+ }).addClass('ngdialog-closing');
+ } else {
+ scope.$destroy();
+ privateMethods.closeDialogElement($dialog, value);
+ }
+ if (defers[id]) {
+ defers[id].resolve({
+ id: id,
+ value: value,
+ $dialog: $dialog,
+ remainingDialogs: dialogsCount
+ });
+ delete defers[id];
+ }
+ if (scopes[id]) {
+ delete scopes[id];
+ }
+ openIdStack.splice(openIdStack.indexOf(id), 1);
+ if (!openIdStack.length) {
+ $elements.body.unbind('keydown', privateMethods.onDocumentKeydown);
+ keydownIsBound = false;
+ }
+
+ if (dialogsCount == 0)
+ {
+ closeByDocumentHandler = undefined;
+ }
+ },
+
+ closeDialogElement: function($dialog, value) {
+ var options = $dialog.data('$ngDialogOptions');
+ $dialog.remove();
+
+ activeBodyClasses.splice(activeBodyClasses.indexOf(options.bodyClassName), 1);
+ if (activeBodyClasses.indexOf(options.bodyClassName) === -1) {
+ $elements.html.removeClass(options.bodyClassName);
+ $elements.body.removeClass(options.bodyClassName);
+ }
+
+ if (dialogsCount === 0) {
+ privateMethods.resetBodyPadding();
+ }
+
+ $rootScope.$broadcast('ngDialog.closed', $dialog, value);
+ },
+
+ closeDialog: function ($dialog, value) {
+ var preCloseCallback = $dialog.data('$ngDialogPreCloseCallback');
+
+ if (preCloseCallback && angular.isFunction(preCloseCallback)) {
+
+ var preCloseCallbackResult = preCloseCallback.call($dialog, value);
+
+ if (angular.isObject(preCloseCallbackResult)) {
+ if (preCloseCallbackResult.closePromise) {
+ preCloseCallbackResult.closePromise.then(function () {
+ privateMethods.performCloseDialog($dialog, value);
+ }, function () {
+ return false;
+ });
+ } else {
+ preCloseCallbackResult.then(function () {
+ privateMethods.performCloseDialog($dialog, value);
+ }, function () {
+ return false;
+ });
+ }
+ } else if (preCloseCallbackResult !== false) {
+ privateMethods.performCloseDialog($dialog, value);
+ } else {
+ return false;
+ }
+ } else {
+ privateMethods.performCloseDialog($dialog, value);
+ }
+ },
+
+ onTrapFocusKeydown: function(ev) {
+ var el = angular.element(ev.currentTarget);
+ var $dialog;
+
+ if (el.hasClass('ngdialog')) {
+ $dialog = el;
+ } else {
+ $dialog = privateMethods.getActiveDialog();
+
+ if ($dialog === null) {
+ return;
+ }
+ }
+
+ var isTab = (ev.keyCode === 9);
+ var backward = (ev.shiftKey === true);
+
+ if (isTab) {
+ privateMethods.handleTab($dialog, ev, backward);
+ }
+ },
+
+ handleTab: function($dialog, ev, backward) {
+ var focusableElements = privateMethods.getFocusableElements($dialog);
+
+ if (focusableElements.length === 0) {
+ if (document.activeElement && document.activeElement.blur) {
+ document.activeElement.blur();
+ }
+ return;
+ }
+
+ var currentFocus = document.activeElement;
+ var focusIndex = Array.prototype.indexOf.call(focusableElements, currentFocus);
+
+ var isFocusIndexUnknown = (focusIndex === -1);
+ var isFirstElementFocused = (focusIndex === 0);
+ var isLastElementFocused = (focusIndex === focusableElements.length - 1);
+
+ var cancelEvent = false;
+
+ if (backward) {
+ if (isFocusIndexUnknown || isFirstElementFocused) {
+ focusableElements[focusableElements.length - 1].focus();
+ cancelEvent = true;
+ }
+ } else {
+ if (isFocusIndexUnknown || isLastElementFocused) {
+ focusableElements[0].focus();
+ cancelEvent = true;
+ }
+ }
+
+ if (cancelEvent) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ },
+
+ autoFocus: function($dialog) {
+ var dialogEl = $dialog[0];
+
+ // Browser's (Chrome 40, Forefix 37, IE 11) don't appear to honor autofocus on the dialog, but we should
+ var autoFocusEl = dialogEl.querySelector('*[autofocus]');
+ if (autoFocusEl !== null) {
+ autoFocusEl.focus();
+
+ if (document.activeElement === autoFocusEl) {
+ return;
+ }
+
+ // Autofocus element might was display: none, so let's continue
+ }
+
+ var focusableElements = privateMethods.getFocusableElements($dialog);
+
+ if (focusableElements.length > 0) {
+ focusableElements[0].focus();
+ return;
+ }
+
+ // We need to focus something for the screen readers to notice the dialog
+ var contentElements = privateMethods.filterVisibleElements(dialogEl.querySelectorAll('h1,h2,h3,h4,h5,h6,p,span'));
+
+ if (contentElements.length > 0) {
+ var contentElement = contentElements[0];
+ $el(contentElement).attr('tabindex', '-1').css('outline', '0');
+ contentElement.focus();
+ }
+ },
+
+ getFocusableElements: function ($dialog) {
+ var dialogEl = $dialog[0];
+
+ var rawElements = dialogEl.querySelectorAll(focusableElementSelector);
+
+ // Ignore untabbable elements, ie. those with tabindex = -1
+ var tabbableElements = privateMethods.filterTabbableElements(rawElements);
+
+ return privateMethods.filterVisibleElements(tabbableElements);
+ },
+
+ filterTabbableElements: function (els) {
+ var tabbableFocusableElements = [];
+
+ for (var i = 0; i < els.length; i++) {
+ var el = els[i];
+
+ if ($el(el).attr('tabindex') !== '-1') {
+ tabbableFocusableElements.push(el);
+ }
+ }
+
+ return tabbableFocusableElements;
+ },
+
+ filterVisibleElements: function (els) {
+ var visibleFocusableElements = [];
+
+ for (var i = 0; i < els.length; i++) {
+ var el = els[i];
+
+ if (el.offsetWidth > 0 || el.offsetHeight > 0) {
+ visibleFocusableElements.push(el);
+ }
+ }
+
+ return visibleFocusableElements;
+ },
+
+ getActiveDialog: function () {
+ var dialogs = document.querySelectorAll('.ngdialog');
+
+ if (dialogs.length === 0) {
+ return null;
+ }
+
+ // TODO: This might be incorrect if there are a mix of open dialogs with different 'appendTo' values
+ return $el(dialogs[dialogs.length - 1]);
+ },
+
+ applyAriaAttributes: function ($dialog, options) {
+ if (options.ariaAuto) {
+ if (!options.ariaRole) {
+ var detectedRole = (privateMethods.getFocusableElements($dialog).length > 0) ?
+ 'dialog' :
+ 'alertdialog';
+
+ options.ariaRole = detectedRole;
+ }
+
+ if (!options.ariaLabelledBySelector) {
+ options.ariaLabelledBySelector = 'h1,h2,h3,h4,h5,h6';
+ }
+
+ if (!options.ariaDescribedBySelector) {
+ options.ariaDescribedBySelector = 'article,section,p';
+ }
+ }
+
+ if (options.ariaRole) {
+ $dialog.attr('role', options.ariaRole);
+ }
+
+ privateMethods.applyAriaAttribute(
+ $dialog, 'aria-labelledby', options.ariaLabelledById, options.ariaLabelledBySelector);
+
+ privateMethods.applyAriaAttribute(
+ $dialog, 'aria-describedby', options.ariaDescribedById, options.ariaDescribedBySelector);
+ },
+
+ applyAriaAttribute: function($dialog, attr, id, selector) {
+ if (id) {
+ $dialog.attr(attr, id);
+ return;
+ }
+
+ if (selector) {
+ var dialogId = $dialog.attr('id');
+
+ var firstMatch = $dialog[0].querySelector(selector);
+
+ if (!firstMatch) {
+ return;
+ }
+
+ var generatedId = dialogId + '-' + attr;
+
+ $el(firstMatch).attr('id', generatedId);
+
+ $dialog.attr(attr, generatedId);
+
+ return generatedId;
+ }
+ },
+
+ detectUIRouter: function() {
+ // Detect if ui-router module is installed
+ // Returns ui-router version string if installed
+ // Otherwise false
+
+ if ($injector.has('$transitions')) {
+ // Only 1.0.0+ ui.router allows us to inject $transitions
+ return UI_ROUTER_VERSION_ONE_PLUS;
+ }
+ else if ($injector.has('$state')) {
+ // The legacy ui.router allows us to inject $state
+ return UI_ROUTER_VERSION_LEGACY;
+ }
+ return false;
+ },
+
+ getRouterLocationEventName: function() {
+ if (privateMethods.detectUIRouter()) {
+ return '$stateChangeStart';
+ }
+ return '$locationChangeStart';
+ }
+ };
+
+ var publicMethods = {
+ __PRIVATE__: privateMethods,
+
+ /*
+ * @param {Object} options:
+ * - template {String} - id of ng-template, url for partial, plain string (if enabled)
+ * - plain {Boolean} - enable plain string templates, default false
+ * - scope {Object}
+ * - controller {String}
+ * - controllerAs {String}
+ * - className {String} - dialog theme class
+ * - appendClassName {String} - dialog theme class to be appended to defaults
+ * - disableAnimation {Boolean} - set to true to disable animation
+ * - showClose {Boolean} - show close button, default true
+ * - closeByEscape {Boolean} - default true
+ * - closeByDocument {Boolean} - default true
+ * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
+ * - onOpenCallback {String|Function} - user supplied function name/function called after opening dialog (if set)
+ * - bodyClassName {String} - class added to body at open dialog
+ * @return {Object} dialog
+ */
+ open: function (opts) {
+ var dialogID = null;
+ opts = opts || {};
+ if (openOnePerName && opts.name) {
+ dialogID = opts.name.toLowerCase().replace(/\s/g, '-') + '-dialog';
+ if (this.isOpen(dialogID)) {
+ return;
+ }
+ }
+ var options = angular.copy(defaults);
+ var localID = ++globalID;
+ dialogID = dialogID || 'ngdialog' + localID;
+ openIdStack.push(dialogID);
+
+ // Merge opts.data with predefined via setDefaults
+ if (typeof options.data !== 'undefined') {
+ if (typeof opts.data === 'undefined') {
+ opts.data = {};
+ }
+ opts.data = angular.merge(angular.copy(options.data), opts.data);
+ }
+
+ angular.extend(options, opts);
+
+ var defer;
+ defers[dialogID] = defer = $q.defer();
+
+ var scope;
+ scopes[dialogID] = scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
+
+ var $dialog, $dialogParent, $dialogContent;
+
+ var resolve = angular.extend({}, options.resolve);
+
+ angular.forEach(resolve, function (value, key) {
+ resolve[key] = angular.isString(value) ? $injector.get(value) : $injector.invoke(value, null, null, key);
+ });
+
+ $q.all({
+ template: loadTemplate(options.template || options.templateUrl),
+ locals: $q.all(resolve)
+ }).then(function (setup) {
+ var template = setup.template,
+ locals = setup.locals;
+
+ if (options.showClose) {
+ template += '<button aria-label="Dismiss" class="ngdialog-close"></button>';
+ }
+
+ var hasOverlayClass = options.overlay ? '' : ' ngdialog-no-overlay';
+ $dialog = $el('<div id="' + dialogID + '" class="ngdialog' + hasOverlayClass + '"></div>');
+ $dialog.html((options.overlay ?
+ '<div class="ngdialog-overlay"></div><div class="ngdialog-content" role="document">' + template + '</div>' :
+ '<div class="ngdialog-content" role="document">' + template + '</div>'));
+
+ $dialog.data('$ngDialogOptions', options);
+
+ scope.ngDialogId = dialogID;
+
+ if (options.data && angular.isString(options.data)) {
+ var firstLetter = options.data.replace(/^\s*/, '')[0];
+ scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : new String(options.data);
+ scope.ngDialogData.ngDialogId = dialogID;
+ } else if (options.data && angular.isObject(options.data)) {
+ scope.ngDialogData = options.data;
+ scope.ngDialogData.ngDialogId = dialogID;
+ }
+
+ if (options.className) {
+ $dialog.addClass(options.className);
+ }
+
+ if (options.appendClassName) {
+ $dialog.addClass(options.appendClassName);
+ }
+
+ if (options.width) {
+ $dialogContent = $dialog[0].querySelector('.ngdialog-content');
+ if (angular.isString(options.width)) {
+ $dialogContent.style.width = options.width;
+ } else {
+ $dialogContent.style.width = options.width + 'px';
+ }
+ }
+
+ if (options.height) {
+ $dialogContent = $dialog[0].querySelector('.ngdialog-content');
+ if (angular.isString(options.height)) {
+ $dialogContent.style.height = options.height;
+ } else {
+ $dialogContent.style.height = options.height + 'px';
+ }
+ }
+
+ if (options.disableAnimation) {
+ $dialog.addClass(disabledAnimationClass);
+ }
+
+ if (options.appendTo && angular.isString(options.appendTo)) {
+ $dialogParent = angular.element(document.querySelector(options.appendTo));
+ } else {
+ $dialogParent = $elements.body;
+ }
+
+ privateMethods.applyAriaAttributes($dialog, options);
+
+ [
+ { name: '$ngDialogPreCloseCallback', value: options.preCloseCallback },
+ { name: '$ngDialogOnOpenCallback', value: options.onOpenCallback }
+ ].forEach(function (option) {
+ if (option.value) {
+ var callback;
+
+ if (angular.isFunction(option.value)) {
+ callback = option.value;
+ } else if (angular.isString(option.value)) {
+ if (scope) {
+ if (angular.isFunction(scope[option.value])) {
+ callback = scope[option.value];
+ } else if (scope.$parent && angular.isFunction(scope.$parent[option.value])) {
+ callback = scope.$parent[option.value];
+ } else if ($rootScope && angular.isFunction($rootScope[option.value])) {
+ callback = $rootScope[option.value];
+ }
+ }
+ }
+
+ if (callback) {
+ $dialog.data(option.name, callback);
+ }
+ }
+ });
+
+ scope.closeThisDialog = function (value) {
+ privateMethods.closeDialog($dialog, value);
+ };
+
+ if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
+
+ var label;
+
+ if (options.controllerAs && angular.isString(options.controllerAs)) {
+ label = options.controllerAs;
+ }
+
+ var controllerInstance = $controller(options.controller, angular.extend(
+ locals,
+ {
+ $scope: scope,
+ $element: $dialog
+ }),
+ true,
+ label
+ );
+
+ if(options.bindToController) {
+ angular.extend(controllerInstance.instance, {ngDialogId: scope.ngDialogId, ngDialogData: scope.ngDialogData, closeThisDialog: scope.closeThisDialog, confirm: scope.confirm});
+ }
+
+ if(typeof controllerInstance === 'function'){
+ $dialog.data('$ngDialogControllerController', controllerInstance());
+ } else {
+ $dialog.data('$ngDialogControllerController', controllerInstance);
+ }
+ }
+
+ $timeout(function () {
+ var $activeDialogs = document.querySelectorAll('.ngdialog');
+ privateMethods.deactivateAll($activeDialogs);
+
+ $compile($dialog)(scope);
+ var widthDiffs = $window.innerWidth - $elements.body.prop('clientWidth');
+ $elements.html.addClass(options.bodyClassName);
+ $elements.body.addClass(options.bodyClassName);
+ activeBodyClasses.push(options.bodyClassName);
+ var scrollBarWidth = widthDiffs - ($window.innerWidth - $elements.body.prop('clientWidth'));
+ if (scrollBarWidth > 0) {
+ privateMethods.setBodyPadding(scrollBarWidth);
+ }
+ $dialogParent.append($dialog);
+
+ privateMethods.activate($dialog);
+
+ if (options.trapFocus) {
+ privateMethods.autoFocus($dialog);
+ }
+
+ if (options.name) {
+ $rootScope.$broadcast('ngDialog.opened', {dialog: $dialog, name: options.name});
+ } else {
+ $rootScope.$broadcast('ngDialog.opened', $dialog);
+ }
+ var onOpenCallback = $dialog.data('$ngDialogOnOpenCallback');
+ if (onOpenCallback && angular.isFunction(onOpenCallback)) {
+ onOpenCallback.call($dialog);
+ }
+
+ });
+
+ if (!keydownIsBound) {
+ $elements.body.bind('keydown', privateMethods.onDocumentKeydown);
+ keydownIsBound = true;
+ }
+
+ if (options.closeByNavigation) {
+ closeByNavigationDialogStack.push($dialog);
+ }
+
+ if (options.preserveFocus) {
+ $dialog.data('$ngDialogPreviousFocus', document.activeElement);
+ }
+
+ closeByDocumentHandler = function (event) {
+ var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
+ var isCloseBtn = $el(event.target).hasClass('ngdialog-close');
+
+ if (isOverlay || isCloseBtn) {
+ publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
+ }
+ };
+
+ if (typeof $window.Hammer !== 'undefined') {
+ var hammerTime = scope.hammerTime = $window.Hammer($dialog[0]);
+ hammerTime.on('tap', closeByDocumentHandler);
+ } else {
+ $dialog.bind('click', closeByDocumentHandler);
+ }
+
+ dialogsCount += 1;
+
+ return publicMethods;
+ });
+
+ return {
+ id: dialogID,
+ closePromise: defer.promise,
+ close: function (value) {
+ privateMethods.closeDialog($dialog, value);
+ }
+ };
+
+ function loadTemplateUrl (tmpl, config) {
+ var config = config || {};
+ config.headers = config.headers || {};
+
+ angular.extend(config.headers, {'Accept': 'text/html'});
+
+ $rootScope.$broadcast('ngDialog.templateLoading', tmpl);
+ return $http.get(tmpl, config).then(function(res) {
+ $rootScope.$broadcast('ngDialog.templateLoaded', tmpl);
+ return res.data || '';
+ });
+ }
+
+ function loadTemplate (tmpl) {
+ if (!tmpl) {
+ return 'Empty template';
+ }
+
+ if (angular.isString(tmpl) && options.plain) {
+ return tmpl;
+ }
+
+ if (typeof options.cache === 'boolean' && !options.cache) {
+ return loadTemplateUrl(tmpl, {cache: false});
+ }
+
+ return loadTemplateUrl(tmpl, {cache: $templateCache});
+ }
+ },
+
+ /*
+ * @param {Object} options:
+ * - template {String} - id of ng-template, url for partial, plain string (if enabled)
+ * - plain {Boolean} - enable plain string templates, default false
+ * - name {String}
+ * - scope {Object}
+ * - controller {String}
+ * - controllerAs {String}
+ * - className {String} - dialog theme class
+ * - appendClassName {String} - dialog theme class to be appended to defaults
+ * - showClose {Boolean} - show close button, default true
+ * - closeByEscape {Boolean} - default false
+ * - closeByDocument {Boolean} - default false
+ * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
+ * - bodyClassName {String} - class added to body at open dialog
+ *
+ * @return {Object} dialog
+ */
+ openConfirm: function (opts) {
+ var defer = $q.defer();
+ var options = angular.copy(defaults);
+
+ opts = opts || {};
+
+ // Merge opts.data with predefined via setDefaults
+ if (typeof options.data !== 'undefined') {
+ if (typeof opts.data === 'undefined') {
+ opts.data = {};
+ }
+ opts.data = angular.merge(angular.copy(options.data), opts.data);
+ }
+
+ angular.extend(options, opts);
+
+ options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
+ options.scope.confirm = function (value) {
+ defer.resolve(value);
+ var $dialog = $el(document.getElementById(openResult.id));
+ privateMethods.performCloseDialog($dialog, value);
+ };
+
+ var openResult = publicMethods.open(options);
+ if (openResult) {
+ openResult.closePromise.then(function (data) {
+ if (data) {
+ return defer.reject(data.value);
+ }
+ return defer.reject();
+ });
+ return defer.promise;
+ }
+ },
+
+ isOpen: function(id) {
+ var $dialog = $el(document.getElementById(id));
+ return $dialog.length > 0;
+ },
+
+ /*
+ * @param {String} id
+ * @return {Object} dialog
+ */
+ close: function (id, value) {
+ var $dialog = $el(document.getElementById(id));
+
+ if ($dialog.length) {
+ privateMethods.closeDialog($dialog, value);
+ } else {
+ if (id === '$escape') {
+ var topDialogId = openIdStack[openIdStack.length - 1];
+ $dialog = $el(document.getElementById(topDialogId));
+ if ($dialog.data('$ngDialogOptions').closeByEscape) {
+ privateMethods.closeDialog($dialog, '$escape');
+ }
+ } else {
+ publicMethods.closeAll(value);
+ }
+ }
+
+ return publicMethods;
+ },
+
+ closeAll: function (value) {
+ var $all = document.querySelectorAll('.ngdialog');
+
+ // Reverse order to ensure focus restoration works as expected
+ for (var i = $all.length - 1; i >= 0; i--) {
+ var dialog = $all[i];
+ privateMethods.closeDialog($el(dialog), value);
+ }
+ },
+
+ getOpenDialogs: function() {
+ return openIdStack;
+ },
+
+ getDefaults: function () {
+ return defaults;
+ }
+ };
+
+ angular.forEach(
+ ['html', 'body'],
+ function(elementName) {
+ $elements[elementName] = $document.find(elementName);
+ if (forceElementsReload[elementName]) {
+ var eventName = privateMethods.getRouterLocationEventName();
+ $rootScope.$on(eventName, function () {
+ $elements[elementName] = $document.find(elementName);
+ });
+ }
+ }
+ );
+
+ // Listen to navigation events to close dialog
+ var uiRouterVersion = privateMethods.detectUIRouter();
+ if (uiRouterVersion === UI_ROUTER_VERSION_ONE_PLUS) {
+ var $transitions = $injector.get('$transitions');
+ $transitions.onStart({}, function (trans) {
+ while (closeByNavigationDialogStack.length > 0) {
+ var toCloseDialog = closeByNavigationDialogStack.pop();
+ if (privateMethods.closeDialog(toCloseDialog) === false) {
+ return false;
+ }
+ }
+ });
+ }
+ else {
+ var eventName = uiRouterVersion === UI_ROUTER_VERSION_LEGACY ? '$stateChangeStart' : '$locationChangeStart';
+ $rootScope.$on(eventName, function ($event) {
+ while (closeByNavigationDialogStack.length > 0) {
+ var toCloseDialog = closeByNavigationDialogStack.pop();
+ if (privateMethods.closeDialog(toCloseDialog) === false) {
+ $event.preventDefault();
+ }
+ }
+ });
+ }
+
+ return publicMethods;
+ }];
+ });
+
+ m.directive('ngDialog', ['ngDialog', function (ngDialog) {
+ return {
+ restrict: 'A',
+ scope: {
+ ngDialogScope: '='
+ },
+ link: function (scope, elem, attrs) {
+ elem.on('click', function (e) {
+ e.preventDefault();
+
+ var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
+ angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);
+
+ var defaults = ngDialog.getDefaults();
+
+ ngDialog.open({
+ template: attrs.ngDialog,
+ className: attrs.ngDialogClass || defaults.className,
+ appendClassName: attrs.ngDialogAppendClass,
+ controller: attrs.ngDialogController,
+ controllerAs: attrs.ngDialogControllerAs,
+ bindToController: attrs.ngDialogBindToController,
+ disableAnimation: attrs.ngDialogDisableAnimation,
+ scope: ngDialogScope,
+ data: attrs.ngDialogData,
+ showClose: attrs.ngDialogShowClose === 'false' ? false : (attrs.ngDialogShowClose === 'true' ? true : defaults.showClose),
+ closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : (attrs.ngDialogCloseByDocument === 'true' ? true : defaults.closeByDocument),
+ closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : (attrs.ngDialogCloseByEscape === 'true' ? true : defaults.closeByEscape),
+ overlay: attrs.ngDialogOverlay === 'false' ? false : (attrs.ngDialogOverlay === 'true' ? true : defaults.overlay),
+ preCloseCallback: attrs.ngDialogPreCloseCallback || defaults.preCloseCallback,
+ onOpenCallback: attrs.ngDialogOnOpenCallback || defaults.onOpenCallback,
+ bodyClassName: attrs.ngDialogBodyClass || defaults.bodyClassName
+ });
+ });
+ }
+ };
+ }]);
+
+ return m;
+}));