/* * angular-ui-bootstrap * http://angular-ui.github.io/bootstrap/ * Version: 0.12.0 - 2014-11-16 * License: MIT */ angular.module("ui.bootstrap", ["ui.bootstrap.tpls","ui.bootstrap.dropdown","ui.bootstrap.tooltip","ui.bootstrap.position","ui.bootstrap.bindHtml","ui.bootstrap.modal","ui.bootstrap.transition"]); angular.module("ui.bootstrap.tpls", ["template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/modal/backdrop.html","template/modal/window.html"]); angular.module('ui.bootstrap.dropdown', []) .constant('dropdownConfig', { openClass: 'open' }) .service('dropdownService', ['$document', function($document) { var openScope = null; this.open = function( dropdownScope ) { if ( !openScope ) { $document.bind('click', closeDropdown); $document.bind('keydown', escapeKeyBind); } if ( openScope && openScope !== dropdownScope ) { openScope.isOpen = false; } openScope = dropdownScope; }; this.close = function( dropdownScope ) { if ( openScope === dropdownScope ) { openScope = null; $document.unbind('click', closeDropdown); $document.unbind('keydown', escapeKeyBind); } }; var closeDropdown = function( evt ) { // This method may still be called during the same mouse event that // unbound this event handler. So check openScope before proceeding. if (!openScope) { return; } var toggleElement = openScope.getToggleElement(); if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) { return; } openScope.$apply(function() { openScope.isOpen = false; }); }; var escapeKeyBind = function( evt ) { if ( evt.which === 27 ) { openScope.focusToggleElement(); closeDropdown(); } }; }]) .controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) { var self = this, scope = $scope.$new(), // create a child scope so we are not polluting original one openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop; this.init = function( element ) { self.$element = element; if ( $attrs.isOpen ) { getIsOpen = $parse($attrs.isOpen); setIsOpen = getIsOpen.assign; $scope.$watch(getIsOpen, function(value) { scope.isOpen = !!value; }); } }; this.toggle = function( open ) { return scope.isOpen = arguments.length ? !!open : !scope.isOpen; }; // Allow other directives to watch status this.isOpen = function() { return scope.isOpen; }; scope.getToggleElement = function() { return self.toggleElement; }; scope.focusToggleElement = function() { if ( self.toggleElement ) { self.toggleElement[0].focus(); } }; scope.$watch('isOpen', function( isOpen, wasOpen ) { $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); if ( isOpen ) { scope.focusToggleElement(); dropdownService.open( scope ); } else { dropdownService.close( scope ); } setIsOpen($scope, isOpen); if (angular.isDefined(isOpen) && isOpen !== wasOpen) { toggleInvoker($scope, { open: !!isOpen }); } }); $scope.$on('$locationChangeSuccess', function() { scope.isOpen = false; }); $scope.$on('$destroy', function() { scope.$destroy(); }); }]) .directive('dropdown', function() { return { controller: 'DropdownController', link: function(scope, element, attrs, dropdownCtrl) { dropdownCtrl.init( element ); } }; }) .directive('dropdownToggle', function() { return { require: '?^dropdown', link: function(scope, element, attrs, dropdownCtrl) { if ( !dropdownCtrl ) { return; } dropdownCtrl.toggleElement = element; var toggleDropdown = function(event) { event.preventDefault(); if ( !element.hasClass('disabled') && !attrs.disabled ) { scope.$apply(function() { dropdownCtrl.toggle(); }); } }; element.bind('click', toggleDropdown); // WAI-ARIA element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); scope.$watch(dropdownCtrl.isOpen, function( isOpen ) { element.attr('aria-expanded', !!isOpen); }); scope.$on('$destroy', function() { element.unbind('click', toggleDropdown); }); } }; }); /** * The following features are still outstanding: animation as a * function, placement as a function, inside, support for more triggers than * just mouse enter/leave, html tooltips, and selector delegation. */ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) /** * The $tooltip service creates tooltip- and popover-like directives as well as * houses global options for them. */ .provider( '$tooltip', function () { // The default options tooltip and popover. var defaultOptions = { placement: 'top', animation: true, popupDelay: 0 }; // Default hide triggers for each show trigger var triggerMap = { 'mouseenter': 'mouseleave', 'click': 'click', 'focus': 'blur' }; // The options specified to the provider globally. var globalOptions = {}; /** * `options({})` allows global configuration of all tooltips in the * application. * * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { * // place tooltips left instead of top by default * $tooltipProvider.options( { placement: 'left' } ); * }); */ this.options = function( value ) { angular.extend( globalOptions, value ); }; /** * This allows you to extend the set of trigger mappings available. E.g.: * * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); */ this.setTriggers = function setTriggers ( triggers ) { angular.extend( triggerMap, triggers ); }; /** * This is a helper function for translating camel-case to snake-case. */ function snake_case(name){ var regexp = /[A-Z]/g; var separator = '-'; return name.replace(regexp, function(letter, pos) { return (pos ? separator : '') + letter.toLowerCase(); }); } /** * Returns the actual instance of the $tooltip service. * TODO support multiple triggers */ this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) { return function $tooltip ( type, prefix, defaultTriggerShow ) { var options = angular.extend( {}, defaultOptions, globalOptions ); /** * Returns an object of show and hide triggers. * * If a trigger is supplied, * it is used to show the tooltip; otherwise, it will use the `trigger` * option passed to the `$tooltipProvider.options` method; else it will * default to the trigger supplied to this directive factory. * * The hide trigger is based on the show trigger. If the `trigger` option * was passed to the `$tooltipProvider.options` method, it will use the * mapped trigger from `triggerMap` or the passed trigger if the map is * undefined; otherwise, it uses the `triggerMap` value of the show * trigger; else it will just use the show trigger. */ function getTriggers ( trigger ) { var show = trigger || options.trigger || defaultTriggerShow; var hide = triggerMap[show] || show; return { show: show, hide: hide }; } var directiveName = snake_case( type ); var startSym = $interpolate.startSymbol(); var endSym = $interpolate.endSymbol(); var template = '
'+ '
'; return { restrict: 'EA', compile: function (tElem, tAttrs) { var tooltipLinker = $compile( template ); return function link ( scope, element, attrs ) { var tooltip; var tooltipLinkedScope; var transitionTimeout; var popupTimeout; var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; var triggers = getTriggers( undefined ); var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); var ttScope = scope.$new(true); var positionTooltip = function () { var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); ttPosition.top += 'px'; ttPosition.left += 'px'; // Now set the calculated positioning. tooltip.css( ttPosition ); }; // By default, the tooltip is not open. // TODO add ability to start tooltip opened ttScope.isOpen = false; function toggleTooltipBind () { if ( ! ttScope.isOpen ) { showTooltipBind(); } else { hideTooltipBind(); } } // Show the tooltip with delay if specified, otherwise show it immediately function showTooltipBind() { if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { return; } prepareTooltip(); if ( ttScope.popupDelay ) { // Do nothing if the tooltip was already scheduled to pop-up. // This happens if show is triggered multiple times before any hide is triggered. if (!popupTimeout) { popupTimeout = $timeout( show, ttScope.popupDelay, false ); popupTimeout.then(function(reposition){reposition();}); } } else { show()(); } } function hideTooltipBind () { scope.$apply(function () { hide(); }); } // Show the tooltip popup element. function show() { popupTimeout = null; // If there is a pending remove transition, we must cancel it, lest the // tooltip be mysteriously removed. if ( transitionTimeout ) { $timeout.cancel( transitionTimeout ); transitionTimeout = null; } // Don't show empty tooltips. if ( ! ttScope.content ) { return angular.noop; } createTooltip(); // Set the initial positioning. tooltip.css({ top: 0, left: 0, display: 'block' }); // Now we add it to the DOM because need some info about it. But it's not // visible yet anyway. if ( appendToBody ) { $document.find( 'body' ).append( tooltip ); } else { element.after( tooltip ); } positionTooltip(); // And show the tooltip. ttScope.isOpen = true; ttScope.$digest(); // digest required as $apply is not called // Return positioning function as promise callback for correct // positioning after draw. return positionTooltip; } // Hide the tooltip popup element. function hide() { // First things first: we don't show it anymore. ttScope.isOpen = false; //if tooltip is going to be shown after delay, we must cancel this $timeout.cancel( popupTimeout ); popupTimeout = null; // And now we remove it from the DOM. However, if we have animation, we // need to wait for it to expire beforehand. // FIXME: this is a placeholder for a port of the transitions library. if ( ttScope.animation ) { if (!transitionTimeout) { transitionTimeout = $timeout(removeTooltip, 500); } } else { removeTooltip(); } } function createTooltip() { // There can only be one tooltip element per directive shown at once. if (tooltip) { removeTooltip(); } tooltipLinkedScope = ttScope.$new(); tooltip = tooltipLinker(tooltipLinkedScope, angular.noop); } function removeTooltip() { transitionTimeout = null; if (tooltip) { tooltip.remove(); tooltip = null; } if (tooltipLinkedScope) { tooltipLinkedScope.$destroy(); tooltipLinkedScope = null; } } function prepareTooltip() { prepPlacement(); prepPopupDelay(); } /** * Observe the relevant attributes. */ attrs.$observe( type, function ( val ) { ttScope.content = val; if (!val && ttScope.isOpen ) { hide(); } }); attrs.$observe( prefix+'Title', function ( val ) { ttScope.title = val; }); function prepPlacement() { var val = attrs[ prefix + 'Placement' ]; ttScope.placement = angular.isDefined( val ) ? val : options.placement; } function prepPopupDelay() { var val = attrs[ prefix + 'PopupDelay' ]; var delay = parseInt( val, 10 ); ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay; } var unregisterTriggers = function () { element.unbind(triggers.show, showTooltipBind); element.unbind(triggers.hide, hideTooltipBind); }; function prepTriggers() { var val = attrs[ prefix + 'Trigger' ]; unregisterTriggers(); triggers = getTriggers( val ); if ( triggers.show === triggers.hide ) { element.bind( triggers.show, toggleTooltipBind ); } else { element.bind( triggers.show, showTooltipBind ); element.bind( triggers.hide, hideTooltipBind ); } } prepTriggers(); var animation = scope.$eval(attrs[prefix + 'Animation']); ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; // if a tooltip is attached to we need to remove it on // location change as its parent scope will probably not be destroyed // by the change. if ( appendToBody ) { scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { if ( ttScope.isOpen ) { hide(); } }); } // Make sure tooltip is destroyed and removed. scope.$on('$destroy', function onDestroyTooltip() { $timeout.cancel( transitionTimeout ); $timeout.cancel( popupTimeout ); unregisterTriggers(); removeTooltip(); ttScope = null; }); }; } }; }; }]; }) .directive( 'tooltipPopup', function () { return { restrict: 'EA', replace: true, scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, templateUrl: 'template/tooltip/tooltip-popup.html' }; }) .directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); }]) .directive( 'tooltipHtmlUnsafePopup', function () { return { restrict: 'EA', replace: true, scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' }; }) .directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); }]); angular.module('ui.bootstrap.position', []) /** * A set of utility methods that can be use to retrieve position of DOM elements. * It is meant to be used where we need to absolute-position DOM elements in * relation to other, existing elements (this is the case for tooltips, popovers, * typeahead suggestions etc.). */ .factory('$position', ['$document', '$window', function ($document, $window) { function getStyle(el, cssprop) { if (el.currentStyle) { //IE return el.currentStyle[cssprop]; } else if ($window.getComputedStyle) { return $window.getComputedStyle(el)[cssprop]; } // finally try and get inline style return el.style[cssprop]; } /** * Checks if a given element is statically positioned * @param element - raw DOM element */ function isStaticPositioned(element) { return (getStyle(element, 'position') || 'static' ) === 'static'; } /** * returns the closest, non-statically positioned parentOffset of a given element * @param element */ var parentOffsetEl = function (element) { var docDomEl = $document[0]; var offsetParent = element.offsetParent || docDomEl; while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { offsetParent = offsetParent.offsetParent; } return offsetParent || docDomEl; }; return { /** * Provides read-only equivalent of jQuery's position function: * http://api.jquery.com/position/ */ position: function (element) { var elBCR = this.offset(element); var offsetParentBCR = { top: 0, left: 0 }; var offsetParentEl = parentOffsetEl(element[0]); if (offsetParentEl != $document[0]) { offsetParentBCR = this.offset(angular.element(offsetParentEl)); offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; } var boundingClientRect = element[0].getBoundingClientRect(); return { width: boundingClientRect.width || element.prop('offsetWidth'), height: boundingClientRect.height || element.prop('offsetHeight'), top: elBCR.top - offsetParentBCR.top, left: elBCR.left - offsetParentBCR.left }; }, /** * Provides read-only equivalent of jQuery's offset function: * http://api.jquery.com/offset/ */ offset: function (element) { var boundingClientRect = element[0].getBoundingClientRect(); return { width: boundingClientRect.width || element.prop('offsetWidth'), height: boundingClientRect.height || element.prop('offsetHeight'), top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) }; }, /** * Provides coordinates for the targetEl in relation to hostEl */ positionElements: function (hostEl, targetEl, positionStr, appendToBody) { var positionStrParts = positionStr.split('-'); var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; var hostElPos, targetElWidth, targetElHeight, targetElPos; hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); targetElWidth = targetEl.prop('offsetWidth'); targetElHeight = targetEl.prop('offsetHeight'); var shiftWidth = { center: function () { return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; }, left: function () { return hostElPos.left; }, right: function () { return hostElPos.left + hostElPos.width; } }; var shiftHeight = { center: function () { return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; }, top: function () { return hostElPos.top; }, bottom: function () { return hostElPos.top + hostElPos.height; } }; switch (pos0) { case 'right': targetElPos = { top: shiftHeight[pos1](), left: shiftWidth[pos0]() }; break; case 'left': targetElPos = { top: shiftHeight[pos1](), left: hostElPos.left - targetElWidth }; break; case 'bottom': targetElPos = { top: shiftHeight[pos0](), left: shiftWidth[pos1]() }; break; default: targetElPos = { top: hostElPos.top - targetElHeight, left: shiftWidth[pos1]() }; break; } return targetElPos; } }; }]); angular.module('ui.bootstrap.bindHtml', []) .directive('bindHtmlUnsafe', function () { return function (scope, element, attr) { element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { element.html(value || ''); }); }; }); angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition']) /** * A helper, internal data structure that acts as a map but also allows getting / removing * elements in the LIFO order */ .factory('$$stackedMap', function () { return { createNew: function () { var stack = []; return { add: function (key, value) { stack.push({ key: key, value: value }); }, get: function (key) { for (var i = 0; i < stack.length; i++) { if (key == stack[i].key) { return stack[i]; } } }, keys: function() { var keys = []; for (var i = 0; i < stack.length; i++) { keys.push(stack[i].key); } return keys; }, top: function () { return stack[stack.length - 1]; }, remove: function (key) { var idx = -1; for (var i = 0; i < stack.length; i++) { if (key == stack[i].key) { idx = i; break; } } return stack.splice(idx, 1)[0]; }, removeTop: function () { return stack.splice(stack.length - 1, 1)[0]; }, length: function () { return stack.length; } }; } }; }) /** * A helper directive for the $modal service. It creates a backdrop element. */ .directive('modalBackdrop', ['$timeout', function ($timeout) { return { restrict: 'EA', replace: true, templateUrl: 'template/modal/backdrop.html', link: function (scope, element, attrs) { scope.backdropClass = attrs.backdropClass || ''; scope.animate = false; //trigger CSS transitions $timeout(function () { scope.animate = true; }); } }; }]) .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { return { restrict: 'EA', scope: { index: '@', animate: '=' }, replace: true, transclude: true, templateUrl: function(tElement, tAttrs) { return tAttrs.templateUrl || 'template/modal/window.html'; }, link: function (scope, element, attrs) { element.addClass(attrs.windowClass || ''); scope.size = attrs.size; $timeout(function () { // trigger CSS transitions scope.animate = true; /** * 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 (!element[0].querySelectorAll('[autofocus]').length) { element[0].focus(); } }); 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'); } }; } }; }]) .directive('modalTransclude', function () { return { link: function($scope, $element, $attrs, controller, $transclude) { $transclude($scope.$parent, function(clone) { $element.empty(); $element.append(clone); }); } }; }) .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) { var OPENED_MODAL_CLASS = 'modal-open'; var backdropDomEl, backdropScope; var openedWindows = $$stackedMap.createNew(); var $modalStack = {}; 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) { var body = $document.find('body').eq(0); var modalWindow = openedWindows.get(modalInstance).value; //clean up the stack openedWindows.remove(modalInstance); //remove window DOM element removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 0, function() { modalWindow.modalScope.$destroy(); body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); checkRemoveBackdrop(); }); } function checkRemoveBackdrop() { //remove backdrop if no longer needed if (backdropDomEl && backdropIndex() == -1) { var backdropScopeRef = backdropScope; removeAfterAnimate(backdropDomEl, backdropScope, 0, function () { backdropScopeRef.$destroy(); backdropScopeRef = null; }); backdropDomEl = undefined; backdropScope = undefined; } } function removeAfterAnimate(domEl, scope, emulateTime, done) { // Closing animation scope.animate = false; var transitionEndEventName = $transition.transitionEndEventName; if (transitionEndEventName) { // transition out var timeout = $timeout(afterAnimating, emulateTime); domEl.bind(transitionEndEventName, function () { $timeout.cancel(timeout); afterAnimating(); scope.$apply(); }); } else { // Ensure this call is async $timeout(afterAnimating); } function afterAnimating() { if (afterAnimating.done) { return; } afterAnimating.done = true; domEl.remove(); if (done) { done(); } } } $document.bind('keydown', function (evt) { var modal; if (evt.which === 27) { modal = openedWindows.top(); if (modal && modal.value.keyboard) { evt.preventDefault(); $rootScope.$apply(function () { $modalStack.dismiss(modal.key, 'escape key press'); }); } } }); $modalStack.open = function (modalInstance, modal) { openedWindows.add(modalInstance, { deferred: modal.deferred, modalScope: modal.scope, backdrop: modal.backdrop, keyboard: modal.keyboard }); var body = $document.find('body').eq(0), currBackdropIndex = backdropIndex(); if (currBackdropIndex >= 0 && !backdropDomEl) { backdropScope = $rootScope.$new(true); backdropScope.index = currBackdropIndex; var angularBackgroundDomEl = angular.element('
'); angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass); backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); body.append(backdropDomEl); } var angularDomEl = angular.element('
'); angularDomEl.attr({ 'template-url': modal.windowTemplateUrl, 'window-class': modal.windowClass, 'size': modal.size, 'index': openedWindows.length() - 1, 'animate': 'animate' }).html(modal.content); var modalDomEl = $compile(angularDomEl)(modal.scope); openedWindows.top().value.modalDomEl = modalDomEl; body.append(modalDomEl); body.addClass(OPENED_MODAL_CLASS); }; $modalStack.close = function (modalInstance, result) { var modalWindow = openedWindows.get(modalInstance); if (modalWindow) { modalWindow.value.deferred.resolve(result); removeModalWindow(modalInstance); } }; $modalStack.dismiss = function (modalInstance, reason) { var modalWindow = openedWindows.get(modalInstance); if (modalWindow) { modalWindow.value.deferred.reject(reason); removeModalWindow(modalInstance); } }; $modalStack.dismissAll = function (reason) { var topModal = this.getTop(); while (topModal) { this.dismiss(topModal.key, reason); topModal = this.getTop(); } }; $modalStack.getTop = function () { return openedWindows.top(); }; return $modalStack; }]) .provider('$modal', function () { var $modalProvider = { options: { backdrop: true, //can be also false or 'static' keyboard: true }, $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { var $modal = {}; function getTemplatePromise(options) { return options.template ? $q.when(options.template) : $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl, {cache: $templateCache}).then(function (result) { return result.data; }); } function getResolvePromises(resolves) { var promisesArr = []; angular.forEach(resolves, function (value) { if (angular.isFunction(value) || angular.isArray(value)) { promisesArr.push($q.when($injector.invoke(value))); } }); return promisesArr; } $modal.open = function (modalOptions) { var modalResultDeferred = $q.defer(); var modalOpenedDeferred = $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, close: function (result) { $modalStack.close(modalInstance, result); }, dismiss: function (reason) { $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))); templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { var modalScope = (modalOptions.scope || $rootScope).$new(); modalScope.$close = modalInstance.close; modalScope.$dismiss = modalInstance.dismiss; var ctrlInstance, ctrlLocals = {}; var resolveIter = 1; //controllers if (modalOptions.controller) { ctrlLocals.$scope = modalScope; ctrlLocals.$modalInstance = modalInstance; angular.forEach(modalOptions.resolve, function (value, key) { ctrlLocals[key] = tplAndVars[resolveIter++]; }); ctrlInstance = $controller(modalOptions.controller, ctrlLocals); if (modalOptions.controllerAs) { modalScope[modalOptions.controllerAs] = ctrlInstance; } } $modalStack.open(modalInstance, { scope: modalScope, deferred: modalResultDeferred, content: tplAndVars[0], backdrop: modalOptions.backdrop, keyboard: modalOptions.keyboard, backdropClass: modalOptions.backdropClass, windowClass: modalOptions.windowClass, windowTemplateUrl: modalOptions.windowTemplateUrl, size: modalOptions.size }); }, function resolveError(reason) { modalResultDeferred.reject(reason); }); templateAndResolvePromise.then(function () { modalOpenedDeferred.resolve(true); }, function () { modalOpenedDeferred.reject(false); }); return modalInstance; }; return $modal; }] }; return $modalProvider; }); angular.module('ui.bootstrap.transition', []) /** * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. * @param {DOMElement} element The DOMElement that will be animated. * @param {string|object|function} trigger The thing that will cause the transition to start: * - As a string, it represents the css class to be added to the element. * - As an object, it represents a hash of style attributes to be applied to the element. * - As a function, it represents a function to be called that will cause the transition to occur. * @return {Promise} A promise that is resolved when the transition finishes. */ .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) { var $transition = function(element, trigger, options) { options = options || {}; var deferred = $q.defer(); var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName']; var transitionEndHandler = function(event) { $rootScope.$apply(function() { element.unbind(endEventName, transitionEndHandler); deferred.resolve(element); }); }; if (endEventName) { element.bind(endEventName, transitionEndHandler); } // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur $timeout(function() { if ( angular.isString(trigger) ) { element.addClass(trigger); } else if ( angular.isFunction(trigger) ) { trigger(element); } else if ( angular.isObject(trigger) ) { element.css(trigger); } //If browser does not support transitions, instantly resolve if ( !endEventName ) { deferred.resolve(element); } }); // Add our custom cancel function to the promise that is returned // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, // i.e. it will therefore never raise a transitionEnd event for that transition deferred.promise.cancel = function() { if ( endEventName ) { element.unbind(endEventName, transitionEndHandler); } deferred.reject('Transition cancelled'); }; return deferred.promise; }; // Work out the name of the transitionEnd event var transElement = document.createElement('trans'); var transitionEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'transition': 'transitionend' }; var animationEndEventNames = { 'WebkitTransition': 'webkitAnimationEnd', 'MozTransition': 'animationend', 'OTransition': 'oAnimationEnd', 'transition': 'animationend' }; function findEndEventName(endEventNames) { for (var name in endEventNames){ if (transElement.style[name] !== undefined) { return endEventNames[name]; } } } $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); $transition.animationEndEventName = findEndEventName(animationEndEventNames); return $transition; }]); angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", "
\n" + "
\n" + "
\n" + "
\n" + ""); }]); angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/tooltip/tooltip-popup.html", "
\n" + "
\n" + "
\n" + "
\n" + ""); }]); angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/modal/backdrop.html", "
\n" + ""); }]); angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/modal/window.html", "
\n" + "
\n" + "
\n" + "
\n" + "
\n" + "
"); }]);