From ea357b54ab2b9c10520c906a952bf7343a2864eb Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 16 Jul 2014 11:19:16 +1000 Subject: [PATCH 1/3] Adding some map searching capabilities --- .../darkswarm/directives/map_search.js.coffee | 31 +++++++++++++++++++ app/assets/stylesheets/darkswarm/map.css.sass | 4 +++ app/views/layouts/darkswarm.html.haml | 2 +- app/views/map/index.html.haml | 1 + spec/models/product_distribution_spec.rb | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/darkswarm/directives/map_search.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee new file mode 100644 index 0000000000..ff204d5acc --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -0,0 +1,31 @@ +Darkswarm.directive 'mapSearch', ($timeout)-> + # Install a basic search field in a map + restrict: 'E' + require: '^googleMap' + replace: true + template: '' + link: (scope, elem, attrs, ctrl)-> + $timeout => + map = ctrl.getMap() + input = (document.getElementById("pac-input")) + map.controls[google.maps.ControlPosition.TOP_LEFT].push input + searchBox = new google.maps.places.SearchBox((input)) + + google.maps.event.addListener searchBox, "places_changed", -> + places = searchBox.getPlaces() + return if places.length is 0 + # For each place, get the icon, place name, and location. + markers = [] + bounds = new google.maps.LatLngBounds() + for place in places + bounds.extend place.geometry.location + #map.setCenter place.geometry.location + map.panToBounds place.geometry.viewport + #map.fitBounds bounds + + # Bias the SearchBox results towards places that are within the bounds of the + # current map's viewport. + google.maps.event.addListener map, "bounds_changed", -> + bounds = map.getBounds() + searchBox.setBounds bounds + diff --git a/app/assets/stylesheets/darkswarm/map.css.sass b/app/assets/stylesheets/darkswarm/map.css.sass index a8028c24d1..2050cf5063 100644 --- a/app/assets/stylesheets/darkswarm/map.css.sass +++ b/app/assets/stylesheets/darkswarm/map.css.sass @@ -10,3 +10,7 @@ img // https://github.com/zurb/foundation/issues/112 max-width: none height: auto + + #pac-input + padding: 4px + font-size: 2em diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index f831d93d17..595704709c 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -11,7 +11,7 @@ %link{href: "https://fonts.googleapis.com/css?family=Open+Sans:400,700", rel: "stylesheet", type: "text/css"}/ = yield :scripts - %script{src: "//maps.googleapis.com/maps/api/js?sensor=false"} + %script{src: "//maps.googleapis.com/maps/api/js?libraries=places&sensor=false"} = stylesheet_link_tag "darkswarm/all" = javascript_include_tag "darkswarm/all" diff --git a/app/views/map/index.html.haml b/app/views/map/index.html.haml index e7f6006ae4..ce4052be57 100644 --- a/app/views/map/index.html.haml +++ b/app/views/map/index.html.haml @@ -3,5 +3,6 @@ .map-container{"fill-vertical" => true} %map{"ng-controller" => "MapCtrl"} %google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"} + %map-search %markers{models: "OfnMap.enterprises", fit: "true", coords: "'self'", icon: "'icon'", click: "'reveal'"} diff --git a/spec/models/product_distribution_spec.rb b/spec/models/product_distribution_spec.rb index a2fbf23873..44ebb3cfd3 100644 --- a/spec/models/product_distribution_spec.rb +++ b/spec/models/product_distribution_spec.rb @@ -56,6 +56,7 @@ describe ProductDistribution do adjustment.label.should == "Product distribution by #{distributor.name} for Pear" adjustment.amount.should == 1.23 + # TODO ROB this has an intermittent failure # And it should have some associated metadata md = adjustment.metadata md.enterprise.should == distributor From 10fcf80be157f3cdba72b6b45144738e908a0455 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 29 Jul 2014 15:34:14 +1000 Subject: [PATCH 2/3] Switching back to proper bounds fitting --- .../javascripts/darkswarm/directives/map_search.js.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index ff204d5acc..4942032580 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -18,9 +18,8 @@ Darkswarm.directive 'mapSearch', ($timeout)-> markers = [] bounds = new google.maps.LatLngBounds() for place in places - bounds.extend place.geometry.location #map.setCenter place.geometry.location - map.panToBounds place.geometry.viewport + map.fitBounds place.geometry.viewport #map.fitBounds bounds # Bias the SearchBox results towards places that are within the bounds of the From 88c3f7f9b386e794b8a3e6f6051a99fb8c598ce7 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 30 Jul 2014 13:45:37 +1000 Subject: [PATCH 3/3] Removing a couple of pointless files --- .../darkswarm/services/order.js.coffee | 4 - .../mm-foundation-tpls-0.2.0-SNAPSHOT.js | 2626 ----------------- 2 files changed, 2630 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/services/order.js.coffee delete mode 100644 app/assets/javascripts/shared/mm-foundation-tpls-0.2.0-SNAPSHOT.js diff --git a/app/assets/javascripts/darkswarm/services/order.js.coffee b/app/assets/javascripts/darkswarm/services/order.js.coffee deleted file mode 100644 index 17933b6a4c..0000000000 --- a/app/assets/javascripts/darkswarm/services/order.js.coffee +++ /dev/null @@ -1,4 +0,0 @@ -Darkswarm.factory 'Order', (order)-> - new class Order - order: order - diff --git a/app/assets/javascripts/shared/mm-foundation-tpls-0.2.0-SNAPSHOT.js b/app/assets/javascripts/shared/mm-foundation-tpls-0.2.0-SNAPSHOT.js deleted file mode 100644 index 972b74247f..0000000000 --- a/app/assets/javascripts/shared/mm-foundation-tpls-0.2.0-SNAPSHOT.js +++ /dev/null @@ -1,2626 +0,0 @@ -/* - * angular-mm-foundation - * http://madmimi.github.io/angular-foundation/ - - * Version: 0.2.0-SNAPSHOT - 2014-03-26 - * License: MIT - */ -angular.module("mm.foundation", ["mm.foundation.tpls", "mm.foundation.accordion","mm.foundation.alert","mm.foundation.bindHtml","mm.foundation.buttons","mm.foundation.position","mm.foundation.dropdownToggle","mm.foundation.transition","mm.foundation.modal","mm.foundation.pagination","mm.foundation.tooltip","mm.foundation.popover","mm.foundation.progressbar","mm.foundation.rating","mm.foundation.tabs","mm.foundation.tour","mm.foundation.typeahead"]); -angular.module("mm.foundation.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/tour/tour.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); -angular.module('mm.foundation.accordion', []) - -.constant('accordionConfig', { - closeOthers: true -}) - -.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { - - // This array keeps track of the accordion groups - this.groups = []; - - // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to - this.closeOthers = function(openGroup) { - var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; - if ( closeOthers ) { - angular.forEach(this.groups, function (group) { - if ( group !== openGroup ) { - group.isOpen = false; - } - }); - } - }; - - // This is called from the accordion-group directive to add itself to the accordion - this.addGroup = function(groupScope) { - var that = this; - this.groups.push(groupScope); - - groupScope.$on('$destroy', function (event) { - that.removeGroup(groupScope); - }); - }; - - // This is called from the accordion-group directive when to remove itself - this.removeGroup = function(group) { - var index = this.groups.indexOf(group); - if ( index !== -1 ) { - this.groups.splice(this.groups.indexOf(group), 1); - } - }; - -}]) - -// The accordion directive simply sets up the directive controller -// and adds an accordion CSS class to itself element. -.directive('accordion', function () { - return { - restrict:'EA', - controller:'AccordionController', - transclude: true, - replace: false, - templateUrl: 'template/accordion/accordion.html' - }; -}) - -// The accordion-group directive indicates a block of html that will expand and collapse in an accordion -.directive('accordionGroup', ['$parse', function($parse) { - return { - require:'^accordion', // We need this directive to be inside an accordion - restrict:'EA', - transclude:true, // It transcludes the contents of the directive into the template - replace: true, // The element containing the directive will be replaced with the template - templateUrl:'template/accordion/accordion-group.html', - scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope - controller: function() { - this.setHeading = function(element) { - this.heading = element; - }; - }, - link: function(scope, element, attrs, accordionCtrl) { - var getIsOpen, setIsOpen; - - accordionCtrl.addGroup(scope); - - scope.isOpen = false; - - if ( attrs.isOpen ) { - getIsOpen = $parse(attrs.isOpen); - setIsOpen = getIsOpen.assign; - - scope.$parent.$watch(getIsOpen, function(value) { - scope.isOpen = !!value; - }); - } - - scope.$watch('isOpen', function(value) { - if ( value ) { - accordionCtrl.closeOthers(scope); - } - if ( setIsOpen ) { - setIsOpen(scope.$parent, value); - } - }); - } - }; -}]) - -// Use accordion-heading below an accordion-group to provide a heading containing HTML -// -// Heading containing HTML - -// -.directive('accordionHeading', function() { - return { - restrict: 'EA', - transclude: true, // Grab the contents to be used as the heading - template: '', // In effect remove this element! - replace: true, - require: '^accordionGroup', - compile: function(element, attr, transclude) { - return function link(scope, element, attr, accordionGroupCtrl) { - // Pass the heading to the accordion-group controller - // so that it can be transcluded into the right place in the template - // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] - accordionGroupCtrl.setHeading(transclude(scope, function() {})); - }; - } - }; -}) - -// Use in the accordion-group template to indicate where you want the heading to be transcluded -// You must provide the property on the accordion-group controller that will hold the transcluded element -//
-// -// ... -//
-.directive('accordionTransclude', function() { - return { - require: '^accordionGroup', - link: function(scope, element, attr, controller) { - scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { - if ( heading ) { - element.html(''); - element.append(heading); - } - }); - } - }; -}); - -angular.module("mm.foundation.alert", []) - -.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { - $scope.closeable = 'close' in $attrs; -}]) - -.directive('alert', function () { - return { - restrict:'EA', - controller:'AlertController', - templateUrl:'template/alert/alert.html', - transclude:true, - replace:true, - scope: { - type: '=', - close: '&' - } - }; -}); - -angular.module('mm.foundation.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('mm.foundation.buttons', []) - -.constant('buttonConfig', { - activeClass: 'active', - toggleEvent: 'click' -}) - -.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { - this.activeClass = buttonConfig.activeClass; - this.toggleEvent = buttonConfig.toggleEvent; -}]) - -.directive('btnRadio', function () { - return { - require: ['btnRadio', 'ngModel'], - controller: 'ButtonsController', - link: function (scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - - //model -> UI - ngModelCtrl.$render = function () { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); - }; - - //ui->model - element.bind(buttonsCtrl.toggleEvent, function () { - if (!element.hasClass(buttonsCtrl.activeClass)) { - scope.$apply(function () { - ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio)); - ngModelCtrl.$render(); - }); - } - }); - } - }; -}) - -.directive('btnCheckbox', function () { - return { - require: ['btnCheckbox', 'ngModel'], - controller: 'ButtonsController', - link: function (scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - - function getTrueValue() { - return getCheckboxValue(attrs.btnCheckboxTrue, true); - } - - function getFalseValue() { - return getCheckboxValue(attrs.btnCheckboxFalse, false); - } - - function getCheckboxValue(attributeValue, defaultValue) { - var val = scope.$eval(attributeValue); - return angular.isDefined(val) ? val : defaultValue; - } - - //model -> UI - ngModelCtrl.$render = function () { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); - }; - - //ui->model - element.bind(buttonsCtrl.toggleEvent, function () { - scope.$apply(function () { - ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); - ngModelCtrl.$render(); - }); - }); - } - }; -}); - -angular.module('mm.foundation.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].body.scrollTop || $document[0].documentElement.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) - }; - } - }; - }]); - -/* - * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js - * @restrict class or attribute - * @example: - - */ -angular.module('mm.foundation.dropdownToggle', [ 'mm.foundation.position' ]) - -.directive('dropdownToggle', ['$document', '$location', '$position', function ($document, $location, $position) { - var openElement = null, - closeMenu = angular.noop; - return { - restrict: 'CA', - scope: { - dropdownToggle: '@' - }, - link: function(scope, element, attrs) { - var dropdown = angular.element($document[0].querySelector(scope.dropdownToggle)); - - scope.$watch('$location.path', function() { closeMenu(); }); - dropdown.css('display', 'none').bind('click', function() { closeMenu(); }); - element.bind('click', function (event) { - - var elementWasOpen = (element === openElement); - - event.preventDefault(); - event.stopPropagation(); - - if (!!openElement) { - closeMenu(); - } - - if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) { - dropdown.css('display', 'block'); - - var offset = $position.offset(element); - var parentOffset = $position.offset(angular.element(dropdown[0].offsetParent)); - - dropdown.css({ - left: offset.left - parentOffset.left + 'px', - top: offset.top - parentOffset.top + offset.height + 'px' - }); - - openElement = element; - closeMenu = function (event) { - if (event) { - event.preventDefault(); - event.stopPropagation(); - } - $document.unbind('click', closeMenu); - dropdown.css('display', 'none'); - closeMenu = angular.noop; - openElement = null; - }; - $document.bind('click', closeMenu); - } - }); - } - }; -}]); - -angular.module('mm.foundation.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('mm.foundation.modal', ['mm.foundation.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', ['$modalStack', '$timeout', function ($modalStack, $timeout) { - return { - restrict: 'EA', - replace: true, - templateUrl: 'template/modal/backdrop.html', - link: function (scope) { - - scope.animate = false; - - //trigger CSS transitions - $timeout(function () { - scope.animate = true; - }); - - 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('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { - return { - restrict: 'EA', - scope: { - index: '@', - animate: '=' - }, - replace: true, - transclude: true, - templateUrl: 'template/modal/window.html', - link: function (scope, element, attrs) { - scope.windowClass = attrs.windowClass || ''; - - $timeout(function () { - // trigger CSS transitions - scope.animate = true; - // focus a freshly-opened modal - element[0].focus(); - }); - } - }; - }]) - - .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, 300, checkRemoveBackdrop); - body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); - } - - function checkRemoveBackdrop() { - //remove backdrop if no longer needed - if (backdropDomEl && backdropIndex() == -1) { - var backdropScopeRef = backdropScope; - removeAfterAnimate(backdropDomEl, backdropScope, 150, 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, 0); - } - - 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) { - $rootScope.$apply(function () { - $modalStack.dismiss(modal.key); - }); - } - } - }); - - $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; - backdropDomEl = $compile('
')(backdropScope); - body.append(backdropDomEl); - } - - var angularDomEl = angular.element('
'); - angularDomEl.attr('window-class', modal.windowClass); - angularDomEl.attr('index', openedWindows.length() - 1); - angularDomEl.attr('animate', 'animate'); - angularDomEl.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).value; - if (modalWindow) { - modalWindow.deferred.resolve(result); - removeModalWindow(modalInstance); - } - }; - - $modalStack.dismiss = function (modalInstance, reason) { - var modalWindow = openedWindows.get(modalInstance).value; - if (modalWindow) { - modalWindow.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(options.templateUrl, {cache: $templateCache}).then(function (result) { - return result.data; - }); - } - - function getResolvePromises(resolves) { - var promisesArr = []; - angular.forEach(resolves, function (value, key) { - 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); - } - - $modalStack.open(modalInstance, { - scope: modalScope, - deferred: modalResultDeferred, - content: tplAndVars[0], - backdrop: modalOptions.backdrop, - keyboard: modalOptions.keyboard, - windowClass: modalOptions.windowClass - }); - - }, function resolveError(reason) { - modalResultDeferred.reject(reason); - }); - - templateAndResolvePromise.then(function () { - modalOpenedDeferred.resolve(true); - }, function () { - modalOpenedDeferred.reject(false); - }); - - return modalInstance; - }; - - return $modal; - }] - }; - - return $modalProvider; - }); - -angular.module('mm.foundation.pagination', []) - -.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) { - var self = this, - setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; - - this.init = function(defaultItemsPerPage) { - if ($attrs.itemsPerPage) { - $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { - self.itemsPerPage = parseInt(value, 10); - $scope.totalPages = self.calculateTotalPages(); - }); - } else { - this.itemsPerPage = defaultItemsPerPage; - } - }; - - this.noPrevious = function() { - return this.page === 1; - }; - this.noNext = function() { - return this.page === $scope.totalPages; - }; - - this.isActive = function(page) { - return this.page === page; - }; - - this.calculateTotalPages = function() { - var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); - return Math.max(totalPages || 0, 1); - }; - - this.getAttributeValue = function(attribute, defaultValue, interpolate) { - return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; - }; - - this.render = function() { - this.page = parseInt($scope.page, 10) || 1; - if (this.page > 0 && this.page <= $scope.totalPages) { - $scope.pages = this.getPages(this.page, $scope.totalPages); - } - }; - - $scope.selectPage = function(page) { - if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) { - $scope.page = page; - $scope.onSelectPage({ page: page }); - } - }; - - $scope.$watch('page', function() { - self.render(); - }); - - $scope.$watch('totalItems', function() { - $scope.totalPages = self.calculateTotalPages(); - }); - - $scope.$watch('totalPages', function(value) { - setNumPages($scope.$parent, value); // Readonly variable - - if ( self.page > value ) { - $scope.selectPage(value); - } else { - self.render(); - } - }); -}]) - -.constant('paginationConfig', { - itemsPerPage: 10, - boundaryLinks: false, - directionLinks: true, - firstText: 'First', - previousText: 'Previous', - nextText: 'Next', - lastText: 'Last', - rotate: true -}) - -.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) { - return { - restrict: 'EA', - scope: { - page: '=', - totalItems: '=', - onSelectPage:' &' - }, - controller: 'PaginationController', - templateUrl: 'template/pagination/pagination.html', - replace: true, - link: function(scope, element, attrs, paginationCtrl) { - - // Setup configuration parameters - var maxSize, - boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), - directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), - firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), - previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), - nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), - lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), - rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); - - paginationCtrl.init(config.itemsPerPage); - - if (attrs.maxSize) { - scope.$parent.$watch($parse(attrs.maxSize), function(value) { - maxSize = parseInt(value, 10); - paginationCtrl.render(); - }); - } - - // Create page object used in template - function makePage(number, text, isActive, isDisabled) { - return { - number: number, - text: text, - active: isActive, - disabled: isDisabled - }; - } - - paginationCtrl.getPages = function(currentPage, totalPages) { - var pages = []; - - // Default page limits - var startPage = 1, endPage = totalPages; - var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); - - // recompute if maxSize - if ( isMaxSized ) { - if ( rotate ) { - // Current page is displayed in the middle of the visible ones - startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); - endPage = startPage + maxSize - 1; - - // Adjust if limit is exceeded - if (endPage > totalPages) { - endPage = totalPages; - startPage = endPage - maxSize + 1; - } - } else { - // Visible pages are paginated with maxSize - startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; - - // Adjust last page if limit is exceeded - endPage = Math.min(startPage + maxSize - 1, totalPages); - } - } - - // Add page number links - for (var number = startPage; number <= endPage; number++) { - var page = makePage(number, number, paginationCtrl.isActive(number), false); - pages.push(page); - } - - // Add links to move between page sets - if ( isMaxSized && ! rotate ) { - if ( startPage > 1 ) { - var previousPageSet = makePage(startPage - 1, '...', false, false); - pages.unshift(previousPageSet); - } - - if ( endPage < totalPages ) { - var nextPageSet = makePage(endPage + 1, '...', false, false); - pages.push(nextPageSet); - } - } - - // Add previous & next links - if (directionLinks) { - var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious()); - pages.unshift(previousPage); - - var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext()); - pages.push(nextPage); - } - - // Add first & last links - if (boundaryLinks) { - var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious()); - pages.unshift(firstPage); - - var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext()); - pages.push(lastPage); - } - - return pages; - }; - } - }; -}]) - -.constant('pagerConfig', { - itemsPerPage: 10, - previousText: '« Previous', - nextText: 'Next »', - align: true -}) - -.directive('pager', ['pagerConfig', function(config) { - return { - restrict: 'EA', - scope: { - page: '=', - totalItems: '=', - onSelectPage:' &' - }, - controller: 'PaginationController', - templateUrl: 'template/pagination/pager.html', - replace: true, - link: function(scope, element, attrs, paginationCtrl) { - - // Setup configuration parameters - var previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), - nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), - align = paginationCtrl.getAttributeValue(attrs.align, config.align); - - paginationCtrl.init(config.itemsPerPage); - - // Create page object used in template - function makePage(number, text, isDisabled, isPrevious, isNext) { - return { - number: number, - text: text, - disabled: isDisabled, - previous: ( align && isPrevious ), - next: ( align && isNext ) - }; - } - - paginationCtrl.getPages = function(currentPage) { - return [ - makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false), - makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true) - ]; - }; - } - }; -}]); - -/** - * 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( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundation.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', ['mm.foundation.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', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $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', - scope: true, - compile: function (tElem, tAttrs) { - var tooltipLinker = $compile( template ); - - return function link ( scope, element, attrs ) { - var tooltip; - var transitionTimeout; - var popupTimeout; - var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; - var triggers = getTriggers( undefined ); - var hasRegisteredTriggers = false; - var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); - - var positionTooltip = function (){ - var position, - ttWidth, - ttHeight, - ttPosition; - // Get the position of the directive element. - position = appendToBody ? $position.offset( element ) : $position.position( element ); - - // Get the height and width of the tooltip so we can center it. - ttWidth = tooltip.prop( 'offsetWidth' ); - ttHeight = tooltip.prop( 'offsetHeight' ); - - // Calculate the tooltip's top and left coordinates to center it with - // this directive. - switch ( scope.tt_placement ) { - case 'right': - ttPosition = { - top: position.top + position.height / 2 - ttHeight / 2, - left: position.left + position.width + 10 - }; - break; - case 'bottom': - ttPosition = { - top: position.top + position.height + 10, - left: position.left - }; - break; - case 'left': - ttPosition = { - top: position.top + position.height / 2 - ttHeight / 2, - left: position.left - ttWidth - 10 - }; - break; - default: - ttPosition = { - top: position.top - ttHeight - 10, - left: position.left - }; - break; - } - - 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 - scope.tt_isOpen = false; - - function toggleTooltipBind () { - if ( ! scope.tt_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; - } - if ( scope.tt_popupDelay ) { - popupTimeout = $timeout( show, scope.tt_popupDelay, false ); - popupTimeout.then(function(reposition){reposition();}); - } else { - show()(); - } - } - - function hideTooltipBind () { - scope.$apply(function () { - hide(); - }); - } - - // Show the tooltip popup element. - function show() { - - - // Don't show empty tooltips. - if ( ! scope.tt_content ) { - return angular.noop; - } - - createTooltip(); - - // If there is a pending remove transition, we must cancel it, lest the - // tooltip be mysteriously removed. - if ( transitionTimeout ) { - $timeout.cancel( transitionTimeout ); - } - - // 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. - scope.tt_isOpen = true; - scope.$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. - scope.tt_isOpen = false; - - //if tooltip is going to be shown after delay, we must cancel this - $timeout.cancel( popupTimeout ); - - // 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 ( scope.tt_animation ) { - transitionTimeout = $timeout(removeTooltip, 500); - } else { - removeTooltip(); - } - } - - function createTooltip() { - // There can only be one tooltip element per directive shown at once. - if (tooltip) { - removeTooltip(); - } - tooltip = tooltipLinker(scope, function () {}); - - // Get contents rendered into the tooltip - scope.$digest(); - } - - function removeTooltip() { - if (tooltip) { - tooltip.remove(); - tooltip = null; - } - } - - /** - * Observe the relevant attributes. - */ - attrs.$observe( type, function ( val ) { - scope.tt_content = val; - - if (!val && scope.tt_isOpen ) { - hide(); - } - }); - - attrs.$observe( prefix+'Title', function ( val ) { - scope.tt_title = val; - }); - - attrs.$observe( prefix+'Placement', function ( val ) { - scope.tt_placement = angular.isDefined( val ) ? val : options.placement; - }); - - attrs.$observe( prefix+'PopupDelay', function ( val ) { - var delay = parseInt( val, 10 ); - scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay; - }); - - var unregisterTriggers = function() { - if (hasRegisteredTriggers) { - element.unbind( triggers.show, showTooltipBind ); - element.unbind( triggers.hide, hideTooltipBind ); - } - }; - - var unregisterTriggerFunction = function () {}; - - attrs.$observe( prefix+'Trigger', function ( val ) { - unregisterTriggers(); - unregisterTriggerFunction(); - - triggers = getTriggers( val ); - - if ( angular.isFunction( triggers.show ) ) { - unregisterTriggerFunction = scope.$watch( function () { - return triggers.show( scope, element, attrs ); - }, function ( val ) { - return val ? $timeout( show ) : $timeout( hide ); - }); - } else { - if ( triggers.show === triggers.hide ) { - element.bind( triggers.show, toggleTooltipBind ); - } else { - element.bind( triggers.show, showTooltipBind ); - element.bind( triggers.hide, hideTooltipBind ); - } - } - - hasRegisteredTriggers = true; - }); - - var animation = scope.$eval(attrs[prefix + 'Animation']); - scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation; - - attrs.$observe( prefix+'AppendToBody', function ( val ) { - appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : 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 ( scope.tt_isOpen ) { - hide(); - } - }); - } - - // Make sure tooltip is destroyed and removed. - scope.$on('$destroy', function onDestroyTooltip() { - $timeout.cancel( transitionTimeout ); - $timeout.cancel( popupTimeout ); - unregisterTriggers(); - unregisterTriggerFunction(); - removeTooltip(); - }); - }; - } - }; - }; - }]; -}) - -.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' ); -}]); - -/** - * The following features are still outstanding: popup delay, animation as a - * function, placement as a function, inside, support for more triggers than - * just mouse enter/leave, html popovers, and selector delegatation. - */ -angular.module( 'mm.foundation.popover', [ 'mm.foundation.tooltip' ] ) - -.directive( 'popoverPopup', function () { - return { - restrict: 'EA', - replace: true, - scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/popover/popover.html' - }; -}) - -.directive( 'popover', [ '$tooltip', function ( $tooltip ) { - return $tooltip( 'popover', 'popover', 'click' ); -}]); - -angular.module('mm.foundation.progressbar', ['mm.foundation.transition']) - -.constant('progressConfig', { - animate: true, - max: 100 -}) - -.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) { - var self = this, - bars = [], - max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max, - animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; - - this.addBar = function(bar, element) { - var oldValue = 0, index = bar.$parent.$index; - if ( angular.isDefined(index) && bars[index] ) { - oldValue = bars[index].value; - } - bars.push(bar); - - this.update(element, bar.value, oldValue); - - bar.$watch('value', function(value, oldValue) { - if (value !== oldValue) { - self.update(element, value, oldValue); - } - }); - - bar.$on('$destroy', function() { - self.removeBar(bar); - }); - }; - - // Update bar element width - this.update = function(element, newValue, oldValue) { - var percent = this.getPercentage(newValue); - - if (animate) { - element.css('width', this.getPercentage(oldValue) + '%'); - $transition(element, {width: percent + '%'}); - } else { - element.css({'transition': 'none', 'width': percent + '%'}); - } - }; - - this.removeBar = function(bar) { - bars.splice(bars.indexOf(bar), 1); - }; - - this.getPercentage = function(value) { - return Math.round(100 * value / max); - }; -}]) - -.directive('progress', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - controller: 'ProgressController', - require: 'progress', - scope: {}, - template: '
' - //templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2 - }; -}) - -.directive('bar', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - require: '^progress', - scope: { - value: '=', - type: '@' - }, - templateUrl: 'template/progressbar/bar.html', - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, element); - } - }; -}) - -.directive('progressbar', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - controller: 'ProgressController', - scope: { - value: '=', - type: '@' - }, - templateUrl: 'template/progressbar/progressbar.html', - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, angular.element(element.children()[0])); - } - }; -}); - -angular.module('mm.foundation.rating', []) - -.constant('ratingConfig', { - max: 5, - stateOn: null, - stateOff: null -}) - -.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { - - this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; - this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; - this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; - - this.createRateObjects = function(states) { - var defaultOptions = { - stateOn: this.stateOn, - stateOff: this.stateOff - }; - - for (var i = 0, n = states.length; i < n; i++) { - states[i] = angular.extend({ index: i }, defaultOptions, states[i]); - } - return states; - }; - - // Get objects used in template - $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange)); - - $scope.rate = function(value) { - if ( $scope.value !== value && !$scope.readonly ) { - $scope.value = value; - } - }; - - $scope.enter = function(value) { - if ( ! $scope.readonly ) { - $scope.val = value; - } - $scope.onHover({value: value}); - }; - - $scope.reset = function() { - $scope.val = angular.copy($scope.value); - $scope.onLeave(); - }; - - $scope.$watch('value', function(value) { - $scope.val = value; - }); - - $scope.readonly = false; - if ($attrs.readonly) { - $scope.$parent.$watch($parse($attrs.readonly), function(value) { - $scope.readonly = !!value; - }); - } -}]) - -.directive('rating', function() { - return { - restrict: 'EA', - scope: { - value: '=', - onHover: '&', - onLeave: '&' - }, - controller: 'RatingController', - templateUrl: 'template/rating/rating.html', - replace: true - }; -}); - - -/** - * @ngdoc overview - * @name mm.foundation.tabs - * - * @description - * AngularJS version of the tabs directive. - */ - -angular.module('mm.foundation.tabs', []) - -.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { - var ctrl = this, - tabs = ctrl.tabs = $scope.tabs = []; - - // We simplified this method: now it simply executes the provided selectExpression - ctrl.select = function(tab) { - tab.selectExpression(tab.$parent); - }; - - // This method used to default the first to active - // Now tab.active is maintained through the provided activeExpression - // So we never actually set it internal to this plugin - ctrl.addTab = function addTab(tab) { - tabs.push(tab); - }; - - ctrl.removeTab = function removeTab(tab) { - var index = tabs.indexOf(tab); - //Select a new tab if the tab to be removed is selected - if (tab.active && tabs.length > 1) { - //If this is the last tab, select the previous tab. else, the next tab. - var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; - ctrl.select(tabs[newActiveIndex]); - } - tabs.splice(index, 1); - }; -}]) - -/** - * @ngdoc directive - * @name mm.foundation.tabs.directive:tabset - * @restrict EA - * - * @description - * Tabset is the outer container for the tabs directive - * - * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. - * @param {boolean=} justified Whether or not to use justified styling for the tabs. - * - * @example - - - - First Content! - Second Content! - -
- - First Vertical Content! - Second Vertical Content! - - - First Justified Content! - Second Justified Content! - -
-
- */ -.directive('tabset', function() { - return { - restrict: 'EA', - transclude: true, - replace: true, - scope: {}, - controller: 'TabsetController', - templateUrl: 'template/tabs/tabset.html', - link: function(scope, element, attrs) { - scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; - scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; - scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs'; - } - }; -}) - -/** - * @ngdoc directive - * @name mm.foundation.tabs.directive:tab - * @restrict EA - * - * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link mm.foundation.tabs.directive:tabHeading tabHeading}. - * @param {string=} select An expression to evaluate when the tab is selected. - * @param {boolean=} active A binding, telling whether or not this tab is selected. - * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. - * - * @description - * Creates a tab with a heading and content. Must be placed within a {@link mm.foundation.tabs.directive:tabset tabset}. - * - * @example - - -
- - -
- - First Tab - - Alert me! - Second Tab, with alert callback and html heading! - - - {{item.content}} - - -
-
- - function TabsDemoCtrl($scope) { - $scope.items = [ - { title:"Dynamic Title 1", content:"Dynamic Item 0" }, - { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } - ]; - - $scope.alertMe = function() { - setTimeout(function() { - alert("You've selected the alert tab!"); - }); - }; - }; - -
- */ - -/** - * @ngdoc directive - * @name mm.foundation.tabs.directive:tabHeading - * @restrict EA - * - * @description - * Creates an HTML heading for a {@link mm.foundation.tabs.directive:tab tab}. Must be placed as a child of a tab element. - * - * @example - - - - - HTML in my titles?! - And some content, too! - - - Icon heading?!? - That's right. - - - - - */ - -.directive('tab', ['$parse', function($parse) { - return { - require: '^tabset', - restrict: 'EA', - replace: true, - templateUrl: 'template/tabs/tab.html', - transclude: true, - scope: { - heading: '@', - // TODO: is this broken now? - onSelect: '&select', //This callback is called in contentHeadingTransclude - //once it inserts the tab's content into the dom - onDeselect: '&deselect' - }, - controller: function() { - //Empty controller so other directives can require being 'under' a tab - }, - compile: function(elm, attrs, transclude) { - return function postLink(scope, elm, attrs, tabsetCtrl) { - var getActive, setActive; - - // Here we parse the provided selectExpression - // This expression is executed when the tab is clicked/selected - // It is responsible for making appropriate state changes, such that getActive now returns appropriate values - // Fill in your logic here! - if (attrs.select) { - scope.selectExpression = $parse(attrs.select); - } - - // This expression is now the only thing controlling whether a tab is selected - // We no longer set scope.active/tab.active, except in response to changes to the result of this expression - if (attrs.active) { - getActive = $parse(attrs.active); - setActive = getActive.assign; - scope.$parent.$watch(getActive, function updateActive(value, oldVal) { - // Avoid re-initializing scope.active as it is already initialized - // below. (watcher is called async during init with value === - // oldVal) - if (value !== oldVal) { - scope.active = !!value; - } - }); - scope.active = getActive(scope.$parent); - } else { - setActive = getActive = angular.noop; - } - - // Commented out because: - // 1: two-way binding is limited to variables - // 2: We no longer toggle scope.active internal to this directive/plugin, so don't need to trigger responses - // 3: I'm now executing the callbacks inside scope.select() - - //scope.$watch('active', function(active) { - //// Note this watcher also initializes and assigns scope.active to the - //// attrs.active expression. - ////setActive(scope.$parent, active); - //}); - - scope.disabled = false; - if ( attrs.disabled ) { - scope.$parent.$watch($parse(attrs.disabled), function(value) { - scope.disabled = !! value; - }); - } - - scope.select = function() { - if ( ! scope.disabled ) { - scope.selectExpression(scope.$parent); - } - }; - - tabsetCtrl.addTab(scope); - scope.$on('$destroy', function() { - tabsetCtrl.removeTab(scope); - }); - - - //We need to transclude later, once the content container is ready. - //when this link happens, we're inside a tab heading. - scope.$transcludeFn = transclude; - }; - } - }; -}]) - -.directive('tabHeadingTransclude', [function() { - return { - restrict: 'A', - require: '^tab', - link: function(scope, elm, attrs, tabCtrl) { - scope.$watch('headingElement', function updateHeadingElement(heading) { - if (heading) { - elm.html(''); - elm.append(heading); - } - }); - } - }; -}]) - -.directive('tabContentTransclude', function() { - return { - restrict: 'A', - require: '^tabset', - link: function(scope, elm, attrs) { - var tab = scope.$eval(attrs.tabContentTransclude); - - //Now our tab is ready to be transcluded: both the tab heading area - //and the tab content area are loaded. Transclude 'em both. - tab.$transcludeFn(tab.$parent, function(contents) { - angular.forEach(contents, function(node) { - if (isTabHeading(node)) { - //Let tabHeadingTransclude know. - tab.headingElement = node; - } else { - elm.append(node); - } - }); - }); - } - }; - function isTabHeading(node) { - return node.tagName && ( - node.hasAttribute('tab-heading') || - node.hasAttribute('data-tab-heading') || - node.tagName.toLowerCase() === 'tab-heading' || - node.tagName.toLowerCase() === 'data-tab-heading' - ); - } -}) - -; - -angular.module( 'mm.foundation.tour', [ 'mm.foundation.position', 'mm.foundation.tooltip' ] ) - -.service( '$tour', [ '$window', function ( $window ) { - var currentIndex = getCurrentStep(); - var ended = false; - var steps = {}; - - function getCurrentStep() { - return parseInt( $window.localStorage.getItem( 'mm.tour.step' ), 10 ); - } - - function setCurrentStep(step) { - currentIndex = step; - $window.localStorage.setItem( 'mm.tour.step', step ); - } - - this.add = function ( index, attrs ) { - steps[ index ] = attrs; - }; - - this.has = function ( index ) { - return !!steps[ index ]; - }; - - this.isActive = function () { - return currentIndex > 0; - }; - - this.current = function ( index ) { - if ( index ) { - setCurrentStep( currentIndex ); - } else { - return currentIndex; - } - }; - - this.start = function () { - setCurrentStep( 1 ); - }; - - this.next = function () { - setCurrentStep( currentIndex + 1 ); - }; - - this.end = function () { - setCurrentStep( 0 ); - }; -}]) - -.directive( 'stepPopup', ['$tour', function ( $tour ) { - return { - restrict: 'EA', - replace: true, - scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/tour/tour.html', - link: function (scope, element) { - scope.isLastStep = function () { - return !$tour.has( $tour.current() + 1 ); - }; - - scope.endTour = function () { - element.remove(); - $tour.end(); - }; - - scope.nextStep = function () { - element.remove(); - $tour.next(); - }; - } - }; -}]) - -.directive( 'step', [ '$position', '$tooltip', '$tour', '$window', function ( $position, $tooltip, $tour, $window ) { - function isElementInViewport( element ) { - var rect = element[0].getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= ($window.innerHeight - 80) && - rect.right <= $window.innerWidth - ); - } - - function show( scope, element, attrs ) { - var index = parseInt( attrs.stepIndex, 10); - - if ( $tour.isActive() && index ) { - $tour.add( index, attrs ); - - if ( index === $tour.current() ) { - if ( !isElementInViewport( element ) ) { - var offset = $position.offset( element ); - $window.scrollTo( 0, offset.top - $window.innerHeight / 2 ); - } - - return true; - } - } - - return false; - } - - return $tooltip( 'step', 'step', show ); -}]); - - -angular.module('mm.foundation.typeahead', ['mm.foundation.position', 'mm.foundation.bindHtml']) - -/** - * A helper service that can parse typeahead's syntax (string provided by users) - * Extracted to a separate service for ease of unit testing - */ - .factory('typeaheadParser', ['$parse', function ($parse) { - - // 00000111000000000000022200000000000000003333333333333330000000000044000 - var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/; - - return { - parse:function (input) { - - var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source; - if (!match) { - throw new Error( - "Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" + - " but got '" + input + "'."); - } - - return { - itemName:match[3], - source:$parse(match[4]), - viewMapper:$parse(match[2] || match[1]), - modelMapper:$parse(match[1]) - }; - } - }; -}]) - - .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', - function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { - - var HOT_KEYS = [9, 13, 27, 38, 40]; - - return { - require:'ngModel', - link:function (originalScope, element, attrs, modelCtrl) { - - //SUPPORTED ATTRIBUTES (OPTIONS) - - //minimal no of characters that needs to be entered before typeahead kicks-in - var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; - - //minimal wait time after last character typed before typehead kicks-in - var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; - - //should it restrict model values to the ones selected from the popup only? - var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; - - //binding to a variable that indicates if matches are being retrieved asynchronously - var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; - - //a callback executed when a match is selected - var onSelectCallback = $parse(attrs.typeaheadOnSelect); - - var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; - - var appendToBody = attrs.typeaheadAppendToBody ? $parse(attrs.typeaheadAppendToBody) : false; - - //INTERNAL VARIABLES - - //model setter executed upon match selection - var $setModelValue = $parse(attrs.ngModel).assign; - - //expressions used by typeahead - var parserResult = typeaheadParser.parse(attrs.typeahead); - - var hasFocus; - - //pop-up element used to display matches - var popUpEl = angular.element('
'); - popUpEl.attr({ - matches: 'matches', - active: 'activeIdx', - select: 'select(activeIdx)', - query: 'query', - position: 'position' - }); - //custom item template - if (angular.isDefined(attrs.typeaheadTemplateUrl)) { - popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); - } - - //create a child scope for the typeahead directive so we are not polluting original scope - //with typeahead-specific data (matches, query etc.) - var scope = originalScope.$new(); - originalScope.$on('$destroy', function(){ - scope.$destroy(); - }); - - var resetMatches = function() { - scope.matches = []; - scope.activeIdx = -1; - }; - - var getMatchesAsync = function(inputValue) { - - var locals = {$viewValue: inputValue}; - isLoadingSetter(originalScope, true); - $q.when(parserResult.source(originalScope, locals)).then(function(matches) { - - //it might happen that several async queries were in progress if a user were typing fast - //but we are interested only in responses that correspond to the current view value - if (inputValue === modelCtrl.$viewValue && hasFocus) { - if (matches.length > 0) { - - scope.activeIdx = 0; - scope.matches.length = 0; - - //transform labels - for(var i=0; i= minSearch) { - if (waitTime > 0) { - if (timeoutPromise) { - $timeout.cancel(timeoutPromise);//cancel previous timeout - } - timeoutPromise = $timeout(function () { - getMatchesAsync(inputValue); - }, waitTime); - } else { - getMatchesAsync(inputValue); - } - } else { - isLoadingSetter(originalScope, false); - resetMatches(); - } - - if (isEditable) { - return inputValue; - } else { - if (!inputValue) { - // Reset in case user had typed something previously. - modelCtrl.$setValidity('editable', true); - return inputValue; - } else { - modelCtrl.$setValidity('editable', false); - return undefined; - } - } - }); - - modelCtrl.$formatters.push(function (modelValue) { - - var candidateViewValue, emptyViewValue; - var locals = {}; - - if (inputFormatter) { - - locals['$model'] = modelValue; - return inputFormatter(originalScope, locals); - - } else { - - //it might happen that we don't have enough info to properly render input value - //we need to check for this situation and simply return model value if we can't apply custom formatting - locals[parserResult.itemName] = modelValue; - candidateViewValue = parserResult.viewMapper(originalScope, locals); - locals[parserResult.itemName] = undefined; - emptyViewValue = parserResult.viewMapper(originalScope, locals); - - return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; - } - }); - - scope.select = function (activeIdx) { - //called from within the $digest() cycle - var locals = {}; - var model, item; - - locals[parserResult.itemName] = item = scope.matches[activeIdx].model; - model = parserResult.modelMapper(originalScope, locals); - $setModelValue(originalScope, model); - modelCtrl.$setValidity('editable', true); - - onSelectCallback(originalScope, { - $item: item, - $model: model, - $label: parserResult.viewMapper(originalScope, locals) - }); - - resetMatches(); - - //return focus to the input element if a mach was selected via a mouse click event - element[0].focus(); - }; - - //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) - element.bind('keydown', function (evt) { - - //typeahead is open and an "interesting" key was pressed - if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { - return; - } - - evt.preventDefault(); - - if (evt.which === 40) { - scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; - scope.$digest(); - - } else if (evt.which === 38) { - scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1; - scope.$digest(); - - } else if (evt.which === 13 || evt.which === 9) { - scope.$apply(function () { - scope.select(scope.activeIdx); - }); - - } else if (evt.which === 27) { - evt.stopPropagation(); - - resetMatches(); - scope.$digest(); - } - }); - - element.bind('blur', function (evt) { - hasFocus = false; - }); - - // Keep reference to click handler to unbind it. - var dismissClickHandler = function (evt) { - if (element[0] !== evt.target) { - resetMatches(); - scope.$digest(); - } - }; - - $document.bind('click', dismissClickHandler); - - originalScope.$on('$destroy', function(){ - $document.unbind('click', dismissClickHandler); - }); - - var $popup = $compile(popUpEl)(scope); - if ( appendToBody ) { - $document.find('body').append($popup); - } else { - element.after($popup); - } - } - }; - -}]) - - .directive('typeaheadPopup', function () { - return { - restrict:'EA', - scope:{ - matches:'=', - query:'=', - active:'=', - position:'=', - select:'&' - }, - replace:true, - templateUrl:'template/typeahead/typeahead-popup.html', - link:function (scope, element, attrs) { - - scope.templateUrl = attrs.templateUrl; - - scope.isOpen = function () { - return scope.matches.length > 0; - }; - - scope.isActive = function (matchIdx) { - return scope.active == matchIdx; - }; - - scope.selectActive = function (matchIdx) { - scope.active = matchIdx; - }; - - scope.selectMatch = function (activeIdx) { - scope.select({activeIdx:activeIdx}); - }; - } - }; - }) - - .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { - return { - restrict:'EA', - scope:{ - index:'=', - match:'=', - query:'=' - }, - link:function (scope, element, attrs) { - var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; - $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){ - element.replaceWith($compile(tplContent.trim())(scope)); - }); - } - }; - }]) - - .filter('typeaheadHighlight', function() { - - function escapeRegexp(queryToEscape) { - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - } - - return function(matchItem, query) { - return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; - }; - }); - -angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion-group.html", - "
\n" + - " {{heading}}\n" + - "
\n" + - "
\n" + - ""); -}]); - -angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion.html", - "
\n" + - ""); -}]); - -angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/alert/alert.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" + - ""); -}]); - -angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pager.html", - "\n" + - ""); -}]); - -angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pagination.html", - "\n" + - ""); -}]); - -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/popover/popover.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover.html", - "
\n" + - " \n" + - "
\n" + - "

\n" + - "

\n" + - "
\n" + - "
\n" + - ""); -}]); - -angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/bar.html", - "\n" + - ""); -}]); - -angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progress.html", - "
\n" + - ""); -}]); - -angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progressbar.html", - "
\n" + - " \n" + - "
\n" + - ""); -}]); - -angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/rating/rating.html", - "\n" + - " \n" + - "\n" + - ""); -}]); - -angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tab.html", - "
\n" + - " {{heading}}\n" + - "
\n" + - ""); -}]); - -angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tabset.html", - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - ""); -}]); - -angular.module("template/tour/tour.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/tour/tour.html", - "
\n" + - " \n" + - "
\n" + - "

\n" + - "

\n" + - " Next\n" + - //" Close\n" + - " ×\n" + - "
\n" + - "
\n" + - ""); -}]); - -angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-match.html", - ""); -}]); - -angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-popup.html", - "
    \n" + - "
  • \n" + - "
    \n" + - "
  • \n" + - "
\n" + - ""); -}]);