123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934 |
- angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
- /**
- * A helper, internal data structure that stores all references attached to key
- */
- .factory('$$multiMap', function() {
- return {
- createNew: function() {
- var map = {};
- return {
- entries: function() {
- return Object.keys(map).map(function(key) {
- return {
- key: key,
- value: map[key]
- };
- });
- },
- get: function(key) {
- return map[key];
- },
- hasKey: function(key) {
- return !!map[key];
- },
- keys: function() {
- return Object.keys(map);
- },
- put: function(key, value) {
- if (!map[key]) {
- map[key] = [];
- }
- map[key].push(value);
- },
- remove: function(key, value) {
- var values = map[key];
- if (!values) {
- return;
- }
- var idx = values.indexOf(value);
- if (idx !== -1) {
- values.splice(idx, 1);
- }
- if (!values.length) {
- delete map[key];
- }
- }
- };
- }
- };
- })
- /**
- * A helper directive for the $modal service. It creates a backdrop element.
- */
- .directive('uibModalBackdrop', [
- '$animate', '$injector', '$uibModalStack',
- function($animate , $injector, $modalStack) {
- var $animateCss = null;
- if ($injector.has('$animateCss')) {
- $animateCss = $injector.get('$animateCss');
- }
- return {
- replace: true,
- templateUrl: 'template/modal/backdrop.html',
- compile: function(tElement, tAttrs) {
- tElement.addClass(tAttrs.backdropClass);
- return linkFn;
- }
- };
- function linkFn(scope, element, attrs) {
- // Temporary fix for prefixing
- element.addClass('modal-backdrop');
- if (attrs.modalInClass) {
- if ($animateCss) {
- $animateCss(element, {
- addClass: attrs.modalInClass
- }).start();
- } else {
- $animate.addClass(element, attrs.modalInClass);
- }
- scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
- var done = setIsAsync();
- if ($animateCss) {
- $animateCss(element, {
- removeClass: attrs.modalInClass
- }).start().then(done);
- } else {
- $animate.removeClass(element, attrs.modalInClass).then(done);
- }
- });
- }
- }
- }])
- .directive('uibModalWindow', [
- '$uibModalStack', '$q', '$animate', '$injector',
- function($modalStack , $q , $animate, $injector) {
- var $animateCss = null;
- if ($injector.has('$animateCss')) {
- $animateCss = $injector.get('$animateCss');
- }
- return {
- scope: {
- index: '@'
- },
- replace: true,
- transclude: true,
- templateUrl: function(tElement, tAttrs) {
- return tAttrs.templateUrl || 'template/modal/window.html';
- },
- link: function(scope, element, attrs) {
- element.addClass(attrs.windowClass || '');
- element.addClass(attrs.windowTopClass || '');
- scope.size = attrs.size;
- scope.close = function(evt) {
- var modal = $modalStack.getTop();
- if (modal && modal.value.backdrop && modal.value.backdrop !== 'static' && (evt.target === evt.currentTarget)) {
- evt.preventDefault();
- evt.stopPropagation();
- $modalStack.dismiss(modal.key, 'backdrop click');
- }
- };
- // moved from template to fix issue #2280
- element.on('click', scope.close);
- // This property is only added to the scope for the purpose of detecting when this directive is rendered.
- // We can detect that by using this property in the template associated with this directive and then use
- // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
- scope.$isRendered = true;
- // Deferred object that will be resolved when this modal is render.
- var modalRenderDeferObj = $q.defer();
- // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
- // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
- attrs.$observe('modalRender', function(value) {
- if (value == 'true') {
- modalRenderDeferObj.resolve();
- }
- });
- modalRenderDeferObj.promise.then(function() {
- var animationPromise = null;
- if (attrs.modalInClass) {
- if ($animateCss) {
- animationPromise = $animateCss(element, {
- addClass: attrs.modalInClass
- }).start();
- } else {
- animationPromise = $animate.addClass(element, attrs.modalInClass);
- }
- scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
- var done = setIsAsync();
- if ($animateCss) {
- $animateCss(element, {
- removeClass: attrs.modalInClass
- }).start().then(done);
- } else {
- $animate.removeClass(element, attrs.modalInClass).then(done);
- }
- });
- }
- $q.when(animationPromise).then(function() {
- var inputWithAutofocus = element[0].querySelector('[autofocus]');
- /**
- * Auto-focusing of a freshly-opened modal element causes any child elements
- * with the autofocus attribute to lose focus. This is an issue on touch
- * based devices which will show and then hide the onscreen keyboard.
- * Attempts to refocus the autofocus element via JavaScript will not reopen
- * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
- * the modal element if the modal does not contain an autofocus element.
- */
- if (inputWithAutofocus) {
- inputWithAutofocus.focus();
- } else {
- element[0].focus();
- }
- });
- // Notify {@link $modalStack} that modal is rendered.
- var modal = $modalStack.getTop();
- if (modal) {
- $modalStack.modalRendered(modal.key);
- }
- });
- }
- };
- }])
- .directive('uibModalAnimationClass', function() {
- return {
- compile: function(tElement, tAttrs) {
- if (tAttrs.modalAnimation) {
- tElement.addClass(tAttrs.uibModalAnimationClass);
- }
- }
- };
- })
- .directive('uibModalTransclude', function() {
- return {
- link: function($scope, $element, $attrs, controller, $transclude) {
- $transclude($scope.$parent, function(clone) {
- $element.empty();
- $element.append(clone);
- });
- }
- };
- })
- .factory('$uibModalStack', [
- '$animate', '$timeout', '$document', '$compile', '$rootScope',
- '$q',
- '$injector',
- '$$multiMap',
- '$$stackedMap',
- function($animate , $timeout , $document , $compile , $rootScope ,
- $q,
- $injector,
- $$multiMap,
- $$stackedMap) {
- var $animateCss = null;
- if ($injector.has('$animateCss')) {
- $animateCss = $injector.get('$animateCss');
- }
- var OPENED_MODAL_CLASS = 'modal-open';
- var backdropDomEl, backdropScope;
- var openedWindows = $$stackedMap.createNew();
- var openedClasses = $$multiMap.createNew();
- var $modalStack = {
- NOW_CLOSING_EVENT: 'modal.stack.now-closing'
- };
- //Modal focus behavior
- var focusableElementList;
- var focusIndex = 0;
- var tababbleSelector = 'a[href], area[href], input:not([disabled]), ' +
- 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
- 'iframe, object, embed, *[tabindex], *[contenteditable=true]';
- function backdropIndex() {
- var topBackdropIndex = -1;
- var opened = openedWindows.keys();
- for (var i = 0; i < opened.length; i++) {
- if (openedWindows.get(opened[i]).value.backdrop) {
- topBackdropIndex = i;
- }
- }
- return topBackdropIndex;
- }
- $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
- if (backdropScope) {
- backdropScope.index = newBackdropIndex;
- }
- });
- function removeModalWindow(modalInstance, elementToReceiveFocus) {
- var body = $document.find('body').eq(0);
- var modalWindow = openedWindows.get(modalInstance).value;
- //clean up the stack
- openedWindows.remove(modalInstance);
- removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
- var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
- openedClasses.remove(modalBodyClass, modalInstance);
- body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
- toggleTopWindowClass(true);
- });
- checkRemoveBackdrop();
- //move focus to specified element if available, or else to body
- if (elementToReceiveFocus && elementToReceiveFocus.focus) {
- elementToReceiveFocus.focus();
- } else {
- body.focus();
- }
- }
- // Add or remove "windowTopClass" from the top window in the stack
- function toggleTopWindowClass(toggleSwitch) {
- var modalWindow;
- if (openedWindows.length() > 0) {
- modalWindow = openedWindows.top().value;
- modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
- }
- }
- function checkRemoveBackdrop() {
- //remove backdrop if no longer needed
- if (backdropDomEl && backdropIndex() == -1) {
- var backdropScopeRef = backdropScope;
- removeAfterAnimate(backdropDomEl, backdropScope, function() {
- backdropScopeRef = null;
- });
- backdropDomEl = undefined;
- backdropScope = undefined;
- }
- }
- function removeAfterAnimate(domEl, scope, done) {
- var asyncDeferred;
- var asyncPromise = null;
- var setIsAsync = function() {
- if (!asyncDeferred) {
- asyncDeferred = $q.defer();
- asyncPromise = asyncDeferred.promise;
- }
- return function asyncDone() {
- asyncDeferred.resolve();
- };
- };
- scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
- // Note that it's intentional that asyncPromise might be null.
- // That's when setIsAsync has not been called during the
- // NOW_CLOSING_EVENT broadcast.
- return $q.when(asyncPromise).then(afterAnimating);
- function afterAnimating() {
- if (afterAnimating.done) {
- return;
- }
- afterAnimating.done = true;
- if ($animateCss) {
- $animateCss(domEl, {
- event: 'leave'
- }).start().then(function() {
- domEl.remove();
- });
- } else {
- $animate.leave(domEl);
- }
- scope.$destroy();
- if (done) {
- done();
- }
- }
- }
- $document.bind('keydown', function(evt) {
- if (evt.isDefaultPrevented()) {
- return evt;
- }
- var modal = openedWindows.top();
- if (modal && modal.value.keyboard) {
- switch (evt.which) {
- case 27: {
- evt.preventDefault();
- $rootScope.$apply(function() {
- $modalStack.dismiss(modal.key, 'escape key press');
- });
- break;
- }
- case 9: {
- $modalStack.loadFocusElementList(modal);
- var focusChanged = false;
- if (evt.shiftKey) {
- if ($modalStack.isFocusInFirstItem(evt)) {
- focusChanged = $modalStack.focusLastFocusableElement();
- }
- } else {
- if ($modalStack.isFocusInLastItem(evt)) {
- focusChanged = $modalStack.focusFirstFocusableElement();
- }
- }
- if (focusChanged) {
- evt.preventDefault();
- evt.stopPropagation();
- }
- break;
- }
- }
- }
- });
- $modalStack.open = function(modalInstance, modal) {
- var modalOpener = $document[0].activeElement,
- modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
- toggleTopWindowClass(false);
- openedWindows.add(modalInstance, {
- deferred: modal.deferred,
- renderDeferred: modal.renderDeferred,
- modalScope: modal.scope,
- backdrop: modal.backdrop,
- keyboard: modal.keyboard,
- openedClass: modal.openedClass,
- windowTopClass: modal.windowTopClass
- });
- openedClasses.put(modalBodyClass, modalInstance);
- var body = $document.find('body').eq(0),
- currBackdropIndex = backdropIndex();
- if (currBackdropIndex >= 0 && !backdropDomEl) {
- backdropScope = $rootScope.$new(true);
- backdropScope.index = currBackdropIndex;
- var angularBackgroundDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
- angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
- if (modal.animation) {
- angularBackgroundDomEl.attr('modal-animation', 'true');
- }
- backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
- body.append(backdropDomEl);
- }
- var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
- angularDomEl.attr({
- 'template-url': modal.windowTemplateUrl,
- 'window-class': modal.windowClass,
- 'window-top-class': modal.windowTopClass,
- 'size': modal.size,
- 'index': openedWindows.length() - 1,
- 'animate': 'animate'
- }).html(modal.content);
- if (modal.animation) {
- angularDomEl.attr('modal-animation', 'true');
- }
- var modalDomEl = $compile(angularDomEl)(modal.scope);
- openedWindows.top().value.modalDomEl = modalDomEl;
- openedWindows.top().value.modalOpener = modalOpener;
- body.append(modalDomEl);
- body.addClass(modalBodyClass);
- $modalStack.clearFocusListCache();
- };
- function broadcastClosing(modalWindow, resultOrReason, closing) {
- return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
- }
- $modalStack.close = function(modalInstance, result) {
- var modalWindow = openedWindows.get(modalInstance);
- if (modalWindow && broadcastClosing(modalWindow, result, true)) {
- modalWindow.value.modalScope.$$uibDestructionScheduled = true;
- modalWindow.value.deferred.resolve(result);
- removeModalWindow(modalInstance, modalWindow.value.modalOpener);
- return true;
- }
- return !modalWindow;
- };
- $modalStack.dismiss = function(modalInstance, reason) {
- var modalWindow = openedWindows.get(modalInstance);
- if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
- modalWindow.value.modalScope.$$uibDestructionScheduled = true;
- modalWindow.value.deferred.reject(reason);
- removeModalWindow(modalInstance, modalWindow.value.modalOpener);
- return true;
- }
- return !modalWindow;
- };
- $modalStack.dismissAll = function(reason) {
- var topModal = this.getTop();
- while (topModal && this.dismiss(topModal.key, reason)) {
- topModal = this.getTop();
- }
- };
- $modalStack.getTop = function() {
- return openedWindows.top();
- };
- $modalStack.modalRendered = function(modalInstance) {
- var modalWindow = openedWindows.get(modalInstance);
- if (modalWindow) {
- modalWindow.value.renderDeferred.resolve();
- }
- };
- $modalStack.focusFirstFocusableElement = function() {
- if (focusableElementList.length > 0) {
- focusableElementList[0].focus();
- return true;
- }
- return false;
- };
- $modalStack.focusLastFocusableElement = function() {
- if (focusableElementList.length > 0) {
- focusableElementList[focusableElementList.length - 1].focus();
- return true;
- }
- return false;
- };
- $modalStack.isFocusInFirstItem = function(evt) {
- if (focusableElementList.length > 0) {
- return (evt.target || evt.srcElement) == focusableElementList[0];
- }
- return false;
- };
- $modalStack.isFocusInLastItem = function(evt) {
- if (focusableElementList.length > 0) {
- return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1];
- }
- return false;
- };
- $modalStack.clearFocusListCache = function() {
- focusableElementList = [];
- focusIndex = 0;
- };
- $modalStack.loadFocusElementList = function(modalWindow) {
- if (focusableElementList === undefined || !focusableElementList.length) {
- if (modalWindow) {
- var modalDomE1 = modalWindow.value.modalDomEl;
- if (modalDomE1 && modalDomE1.length) {
- focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector);
- }
- }
- }
- };
- return $modalStack;
- }])
- .provider('$uibModal', function() {
- var $modalProvider = {
- options: {
- animation: true,
- backdrop: true, //can also be false or 'static'
- keyboard: true
- },
- $get: ['$injector', '$rootScope', '$q', '$templateRequest', '$controller', '$uibModalStack', '$modalSuppressWarning', '$log',
- function ($injector, $rootScope, $q, $templateRequest, $controller, $modalStack, $modalSuppressWarning, $log) {
- var $modal = {};
- function getTemplatePromise(options) {
- return options.template ? $q.when(options.template) :
- $templateRequest(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl);
- }
- function getResolvePromises(resolves) {
- var promisesArr = [];
- angular.forEach(resolves, function(value) {
- if (angular.isFunction(value) || angular.isArray(value)) {
- promisesArr.push($q.when($injector.invoke(value)));
- } else if (angular.isString(value)) {
- promisesArr.push($q.when($injector.get(value)));
- } else {
- promisesArr.push($q.when(value));
- }
- });
- return promisesArr;
- }
- var promiseChain = null;
- $modal.getPromiseChain = function() {
- return promiseChain;
- };
- $modal.open = function(modalOptions) {
- var modalResultDeferred = $q.defer();
- var modalOpenedDeferred = $q.defer();
- var modalRenderDeferred = $q.defer();
- //prepare an instance of a modal to be injected into controllers and returned to a caller
- var modalInstance = {
- result: modalResultDeferred.promise,
- opened: modalOpenedDeferred.promise,
- rendered: modalRenderDeferred.promise,
- close: function (result) {
- return $modalStack.close(modalInstance, result);
- },
- dismiss: function (reason) {
- return $modalStack.dismiss(modalInstance, reason);
- }
- };
- //merge and clean up options
- modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
- modalOptions.resolve = modalOptions.resolve || {};
- //verify options
- if (!modalOptions.template && !modalOptions.templateUrl) {
- throw new Error('One of template or templateUrl options is required.');
- }
- var templateAndResolvePromise =
- $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
- function resolveWithTemplate() {
- return templateAndResolvePromise;
- }
- // Wait for the resolution of the existing promise chain.
- // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
- // Then add to $modalStack and resolve opened.
- // Finally clean up the chain variable if no subsequent modal has overwritten it.
- var samePromise;
- samePromise = promiseChain = $q.all([promiseChain])
- .then(resolveWithTemplate, resolveWithTemplate)
- .then(function resolveSuccess(tplAndVars) {
- var modalScope = (modalOptions.scope || $rootScope).$new();
- modalScope.$close = modalInstance.close;
- modalScope.$dismiss = modalInstance.dismiss;
- modalScope.$on('$destroy', function() {
- if (!modalScope.$$uibDestructionScheduled) {
- modalScope.$dismiss('$uibUnscheduledDestruction');
- }
- });
- var ctrlInstance, ctrlLocals = {};
- var resolveIter = 1;
- //controllers
- if (modalOptions.controller) {
- ctrlLocals.$scope = modalScope;
- ctrlLocals.$uibModalInstance = modalInstance;
- Object.defineProperty(ctrlLocals, '$modalInstance', {
- get: function() {
- if (!$modalSuppressWarning) {
- $log.warn('$modalInstance is now deprecated. Use $uibModalInstance instead.');
- }
- return modalInstance;
- }
- });
- angular.forEach(modalOptions.resolve, function(value, key) {
- ctrlLocals[key] = tplAndVars[resolveIter++];
- });
- ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
- if (modalOptions.controllerAs) {
- if (modalOptions.bindToController) {
- angular.extend(ctrlInstance, modalScope);
- }
- modalScope[modalOptions.controllerAs] = ctrlInstance;
- }
- }
- $modalStack.open(modalInstance, {
- scope: modalScope,
- deferred: modalResultDeferred,
- renderDeferred: modalRenderDeferred,
- content: tplAndVars[0],
- animation: modalOptions.animation,
- backdrop: modalOptions.backdrop,
- keyboard: modalOptions.keyboard,
- backdropClass: modalOptions.backdropClass,
- windowTopClass: modalOptions.windowTopClass,
- windowClass: modalOptions.windowClass,
- windowTemplateUrl: modalOptions.windowTemplateUrl,
- size: modalOptions.size,
- openedClass: modalOptions.openedClass
- });
- modalOpenedDeferred.resolve(true);
- }, function resolveError(reason) {
- modalOpenedDeferred.reject(reason);
- modalResultDeferred.reject(reason);
- })
- .finally(function() {
- if (promiseChain === samePromise) {
- promiseChain = null;
- }
- });
- return modalInstance;
- };
- return $modal;
- }
- ]
- };
- return $modalProvider;
- });
- /* deprecated modal below */
- angular.module('ui.bootstrap.modal')
- .value('$modalSuppressWarning', false)
- /**
- * A helper directive for the $modal service. It creates a backdrop element.
- */
- .directive('modalBackdrop', [
- '$animate', '$injector', '$modalStack', '$log', '$modalSuppressWarning',
- function($animate , $injector, $modalStack, $log, $modalSuppressWarning) {
- var $animateCss = null;
- if ($injector.has('$animateCss')) {
- $animateCss = $injector.get('$animateCss');
- }
- return {
- replace: true,
- templateUrl: 'template/modal/backdrop.html',
- compile: function(tElement, tAttrs) {
- tElement.addClass(tAttrs.backdropClass);
- return linkFn;
- }
- };
- function linkFn(scope, element, attrs) {
- if (!$modalSuppressWarning) {
- $log.warn('modal-backdrop is now deprecated. Use uib-modal-backdrop instead.');
- }
- element.addClass('modal-backdrop');
- if (attrs.modalInClass) {
- if ($animateCss) {
- $animateCss(element, {
- addClass: attrs.modalInClass
- }).start();
- } else {
- $animate.addClass(element, attrs.modalInClass);
- }
- scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
- var done = setIsAsync();
- if ($animateCss) {
- $animateCss(element, {
- removeClass: attrs.modalInClass
- }).start().then(done);
- } else {
- $animate.removeClass(element, attrs.modalInClass).then(done);
- }
- });
- }
- }
- }])
- .directive('modalWindow', [
- '$modalStack', '$q', '$animate', '$injector', '$log', '$modalSuppressWarning',
- function($modalStack , $q , $animate, $injector, $log, $modalSuppressWarning) {
- var $animateCss = null;
- if ($injector.has('$animateCss')) {
- $animateCss = $injector.get('$animateCss');
- }
- return {
- scope: {
- index: '@'
- },
- replace: true,
- transclude: true,
- templateUrl: function(tElement, tAttrs) {
- return tAttrs.templateUrl || 'template/modal/window.html';
- },
- link: function(scope, element, attrs) {
- if (!$modalSuppressWarning) {
- $log.warn('modal-window is now deprecated. Use uib-modal-window instead.');
- }
- element.addClass(attrs.windowClass || '');
- element.addClass(attrs.windowTopClass || '');
- scope.size = attrs.size;
- scope.close = function(evt) {
- var modal = $modalStack.getTop();
- if (modal && modal.value.backdrop && modal.value.backdrop !== 'static' && (evt.target === evt.currentTarget)) {
- evt.preventDefault();
- evt.stopPropagation();
- $modalStack.dismiss(modal.key, 'backdrop click');
- }
- };
- // moved from template to fix issue #2280
- element.on('click', scope.close);
- // This property is only added to the scope for the purpose of detecting when this directive is rendered.
- // We can detect that by using this property in the template associated with this directive and then use
- // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
- scope.$isRendered = true;
- // Deferred object that will be resolved when this modal is render.
- var modalRenderDeferObj = $q.defer();
- // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
- // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
- attrs.$observe('modalRender', function(value) {
- if (value == 'true') {
- modalRenderDeferObj.resolve();
- }
- });
- modalRenderDeferObj.promise.then(function() {
- var animationPromise = null;
- if (attrs.modalInClass) {
- if ($animateCss) {
- animationPromise = $animateCss(element, {
- addClass: attrs.modalInClass
- }).start();
- } else {
- animationPromise = $animate.addClass(element, attrs.modalInClass);
- }
- scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
- var done = setIsAsync();
- if ($animateCss) {
- $animateCss(element, {
- removeClass: attrs.modalInClass
- }).start().then(done);
- } else {
- $animate.removeClass(element, attrs.modalInClass).then(done);
- }
- });
- }
- $q.when(animationPromise).then(function() {
- var inputWithAutofocus = element[0].querySelector('[autofocus]');
- /**
- * Auto-focusing of a freshly-opened modal element causes any child elements
- * with the autofocus attribute to lose focus. This is an issue on touch
- * based devices which will show and then hide the onscreen keyboard.
- * Attempts to refocus the autofocus element via JavaScript will not reopen
- * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
- * the modal element if the modal does not contain an autofocus element.
- */
- if (inputWithAutofocus) {
- inputWithAutofocus.focus();
- } else {
- element[0].focus();
- }
- });
- // Notify {@link $modalStack} that modal is rendered.
- var modal = $modalStack.getTop();
- if (modal) {
- $modalStack.modalRendered(modal.key);
- }
- });
- }
- };
- }])
- .directive('modalAnimationClass', [
- '$log', '$modalSuppressWarning',
- function ($log, $modalSuppressWarning) {
- return {
- compile: function(tElement, tAttrs) {
- if (!$modalSuppressWarning) {
- $log.warn('modal-animation-class is now deprecated. Use uib-modal-animation-class instead.');
- }
- if (tAttrs.modalAnimation) {
- tElement.addClass(tAttrs.modalAnimationClass);
- }
- }
- };
- }])
- .directive('modalTransclude', [
- '$log', '$modalSuppressWarning',
- function ($log, $modalSuppressWarning) {
- return {
- link: function($scope, $element, $attrs, controller, $transclude) {
- if (!$modalSuppressWarning) {
- $log.warn('modal-transclude is now deprecated. Use uib-modal-transclude instead.');
- }
- $transclude($scope.$parent, function(clone) {
- $element.empty();
- $element.append(clone);
- });
- }
- };
- }])
- .service('$modalStack', [
- '$animate', '$timeout', '$document', '$compile', '$rootScope',
- '$q',
- '$injector',
- '$$multiMap',
- '$$stackedMap',
- '$uibModalStack',
- '$log',
- '$modalSuppressWarning',
- function($animate , $timeout , $document , $compile , $rootScope ,
- $q,
- $injector,
- $$multiMap,
- $$stackedMap,
- $uibModalStack,
- $log,
- $modalSuppressWarning) {
- if (!$modalSuppressWarning) {
- $log.warn('$modalStack is now deprecated. Use $uibModalStack instead.');
- }
- angular.extend(this, $uibModalStack);
- }])
- .provider('$modal', ['$uibModalProvider', function($uibModalProvider) {
- angular.extend(this, $uibModalProvider);
- this.$get = ['$injector', '$log', '$modalSuppressWarning',
- function ($injector, $log, $modalSuppressWarning) {
- if (!$modalSuppressWarning) {
- $log.warn('$modal is now deprecated. Use $uibModal instead.');
- }
- return $injector.invoke($uibModalProvider.$get);
- }];
- }]);
|