From da5e7fd075580aa459f14a3d9b7da78f5f1e4123 Mon Sep 17 00:00:00 2001 From: Olivier Louvignes Date: Tue, 7 Jan 2014 19:32:41 +0100 Subject: [PATCH] feat(release): release initial v2.0.0-beta.1 --- dist/angular-strap.js | 1540 ++++++++++++++++++++++++++++++++ dist/angular-strap.min.js | 9 + dist/angular-strap.min.map | 1 + dist/modules/affix.js | 143 +++ dist/modules/affix.min.js | 9 + dist/modules/alert.js | 109 +++ dist/modules/alert.min.js | 9 + dist/modules/aside.js | 92 ++ dist/modules/aside.min.js | 9 + dist/modules/button.js | 124 +++ dist/modules/button.min.js | 9 + dist/modules/debounce.js | 60 ++ dist/modules/debounce.min.js | 9 + dist/modules/dimensions.js | 91 ++ dist/modules/dimensions.min.js | 9 + dist/modules/dropdown.js | 114 +++ dist/modules/dropdown.min.js | 9 + dist/modules/modal.js | 219 +++++ dist/modules/modal.min.js | 9 + dist/modules/module.js | 19 + dist/modules/module.min.js | 9 + dist/modules/popover.js | 91 ++ dist/modules/popover.min.js | 9 + dist/modules/scrollspy.js | 205 +++++ dist/modules/scrollspy.min.js | 9 + dist/modules/tab.js | 65 ++ dist/modules/tab.min.js | 9 + dist/modules/tooltip.js | 301 +++++++ dist/modules/tooltip.min.js | 9 + 29 files changed, 3300 insertions(+) create mode 100644 dist/angular-strap.js create mode 100644 dist/angular-strap.min.js create mode 100644 dist/angular-strap.min.map create mode 100644 dist/modules/affix.js create mode 100644 dist/modules/affix.min.js create mode 100644 dist/modules/alert.js create mode 100644 dist/modules/alert.min.js create mode 100644 dist/modules/aside.js create mode 100644 dist/modules/aside.min.js create mode 100644 dist/modules/button.js create mode 100644 dist/modules/button.min.js create mode 100644 dist/modules/debounce.js create mode 100644 dist/modules/debounce.min.js create mode 100644 dist/modules/dimensions.js create mode 100644 dist/modules/dimensions.min.js create mode 100644 dist/modules/dropdown.js create mode 100644 dist/modules/dropdown.min.js create mode 100644 dist/modules/modal.js create mode 100644 dist/modules/modal.min.js create mode 100644 dist/modules/module.js create mode 100644 dist/modules/module.min.js create mode 100644 dist/modules/popover.js create mode 100644 dist/modules/popover.min.js create mode 100644 dist/modules/scrollspy.js create mode 100644 dist/modules/scrollspy.min.js create mode 100644 dist/modules/tab.js create mode 100644 dist/modules/tab.min.js create mode 100644 dist/modules/tooltip.js create mode 100644 dist/modules/tooltip.min.js diff --git a/dist/angular-strap.js b/dist/angular-strap.js new file mode 100644 index 000000000..4d6aed498 --- /dev/null +++ b/dist/angular-strap.js @@ -0,0 +1,1540 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +(function (window, document, $, undefined) { + 'use strict'; + angular.module('mgcrea.ngStrap', [ + 'mgcrea.ngStrap.modal', + 'mgcrea.ngStrap.aside', + 'mgcrea.ngStrap.alert', + 'mgcrea.ngStrap.button', + 'mgcrea.ngStrap.tooltip', + 'mgcrea.ngStrap.popover', + 'mgcrea.ngStrap.dropdown', + 'mgcrea.ngStrap.scrollspy', + 'mgcrea.ngStrap.affix', + 'mgcrea.ngStrap.tab' + ]); + angular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.jqlite.dimensions']).provider('$affix', function () { + var defaults = this.defaults = { offsetTop: 'auto' }; + this.$get = [ + '$window', + 'dimensions', + function ($window, dimensions) { + var windowEl = angular.element($window); + var bodyEl = angular.element($window.document.body); + function AffixFactory(element, config) { + var $affix = {}; + var options = angular.extend({}, defaults, config); + var reset = 'affix affix-top affix-bottom', initialAffixTop = 0, initialOffsetTop = 0, affixed = null, unpin = null; + var parent = element.parent(); + if (options.offsetParent) { + if (options.offsetParent.match(/^\d+$/)) { + for (var i = 0; i < options.offsetParent * 1 - 1; i++) { + parent = parent.parent(); + } + } else { + parent = angular.element(options.offsetParent); + } + } + var offsetTop = 0; + if (options.offsetTop) { + if (options.offsetTop === 'auto') { + options.offsetTop = '+0'; + } + if (options.offsetTop.match(/^[-+]\d+$/)) { + initialAffixTop -= options.offsetTop * 1; + if (options.offsetParent) { + offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1; + } else { + offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1; + } + } else { + offsetTop = options.offsetTop * 1; + } + } + var offsetBottom = 0; + if (options.offsetBottom) { + if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) { + offsetBottom = $window.document.body.scrollHeight - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1; + } else { + offsetBottom = options.offsetBottom * 1; + } + } + $affix.init = function () { + initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop; + windowEl.on('scroll', this.checkPosition); + windowEl.on('click', this.checkPositionWithEventLoop); + this.checkPosition(); + this.checkPositionWithEventLoop(); + }; + $affix.destroy = function () { + windowEl.off('scroll', this.checkPosition); + windowEl.off('click', this.checkPositionWithEventLoop); + }; + $affix.checkPositionWithEventLoop = function () { + setTimeout(this.checkPosition, 1); + }; + $affix.checkPosition = function () { + var scrollTop = $window.pageYOffset; + var position = dimensions.offset(element[0]); + var elementHeight = dimensions.height(element[0]); + var affix = getRequiredAffixClass(unpin, position, elementHeight); + if (affixed === affix) + return; + affixed = affix; + element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : '')); + if (affix === 'top') { + unpin = null; + element.css('position', options.offsetParent ? '' : 'relative'); + element.css('top', ''); + } else if (affix === 'bottom') { + if (options.offsetUnpin) { + unpin = -(options.offsetUnpin * 1); + } else { + unpin = position.top - scrollTop; + } + element.css('position', options.offsetParent ? '' : 'relative'); + element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px'); + } else { + unpin = null; + element.css('position', 'fixed'); + element.css('top', initialAffixTop + 'px'); + } + }; + function getRequiredAffixClass(unpin, position, elementHeight) { + var scrollTop = $window.pageYOffset; + var scrollHeight = $window.document.body.scrollHeight; + if (scrollTop <= offsetTop) { + return 'top'; + } else if (unpin !== null && scrollTop + unpin <= position.top) { + return 'middle'; + } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) { + return 'bottom'; + } else { + return 'middle'; + } + } + $affix.init(); + return $affix; + } + return AffixFactory; + } + ]; + }).directive('bsAffix', [ + '$affix', + 'dimensions', + function ($affix, dimensions) { + return { + restrict: 'EAC', + link: function postLink(scope, element, attr) { + var options = { + scope: scope, + offsetTop: 'auto' + }; + angular.forEach([ + 'offsetTop', + 'offsetBottom', + 'offsetParent', + 'offsetUnpin' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + var affix = $affix(element, options); + scope.$on('$destroy', function () { + options = null; + affix = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.alert', []).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '' + ' ' + '
'; + $templateCache.put('$alert', template); + } + ]).provider('$alert', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'alert', + placement: null, + template: '$alert', + container: false, + element: null, + backdrop: false, + keyboard: true, + show: true, + duration: false + }; + this.$get = [ + '$modal', + '$timeout', + function ($modal, $timeout) { + function AlertFactory(config) { + var $alert = {}; + var options = angular.extend({}, defaults, config); + $alert = $modal(options); + if (!options.scope) { + angular.forEach(['type'], function (key) { + if (options[key]) + $alert.scope[key] = options[key]; + }); + } + var show = $alert.show; + if (options.duration) { + $alert.show = function () { + show(); + $timeout(function () { + $alert.hide(); + }, options.duration * 1000); + }; + } + return $alert; + } + return AlertFactory; + } + ]; + }).directive('bsAlert', [ + '$window', + '$location', + '$sce', + '$alert', + function ($window, $location, $sce, $alert) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + angular.forEach([ + 'template', + 'placement', + 'keyboard', + 'container', + 'animation', + 'duration' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content', + 'type' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsAlert && scope.$watch(attr.bsAlert, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var alert = $alert(options); + element.on(attr.trigger || 'click', alert.toggle); + scope.$on('$destroy', function () { + alert.destroy(); + options = null; + alert = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$aside', template); + } + ]).provider('$aside', function () { + var defaults = this.defaults = { + animation: 'animation-fadeAndSlideRight', + prefixClass: 'aside', + placement: 'right', + template: '$aside', + container: false, + element: null, + backdrop: true, + keyboard: true, + show: true + }; + this.$get = [ + '$modal', + function ($modal) { + function AsideFactory(config) { + var $aside = {}; + var options = angular.extend({}, defaults, config); + $aside = $modal(options); + return $aside; + } + return AsideFactory; + } + ]; + }).directive('bsAside', [ + '$window', + '$location', + '$sce', + '$aside', + function ($window, $location, $sce, $aside) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + angular.forEach([ + 'template', + 'placement', + 'backdrop', + 'keyboard', + 'show', + 'container', + 'animation' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsAside && scope.$watch(attr.bsAside, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var aside = $aside(options); + element.on(attr.trigger || 'click', aside.toggle); + scope.$on('$destroy', function () { + aside.destroy(); + options = null; + aside = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.button', []).provider('$button', function () { + var defaults = this.defaults = { + activeClass: 'active', + toggleEvent: 'click' + }; + this.$get = function () { + return { defaults: defaults }; + }; + }).directive('bsCheckboxGroup', function () { + return { + restrict: 'A', + require: 'ngModel', + compile: function postLink(element, attr) { + element.attr('data-toggle', 'buttons'); + element.removeAttr('ng-model'); + var children = element[0].querySelectorAll('input[type="checkbox"]'); + angular.forEach(children, function (child) { + var childEl = angular.element(child); + childEl.attr('bs-checkbox', ''); + childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value')); + }); + } + }; + }).directive('bsCheckbox', [ + '$button', + function ($button) { + var defaults = $button.defaults; + var constantValueRegExp = /^(true|false|\d+)$/; + return { + restrict: 'A', + require: 'ngModel', + link: function postLink(scope, element, attr, controller) { + var options = defaults; + var isInput = element[0].nodeName === 'INPUT'; + var activeElement = isInput ? element.parent() : element; + var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true; + if (constantValueRegExp.test(attr.trueValue)) { + trueValue = scope.$eval(attr.trueValue); + } + var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false; + if (constantValueRegExp.test(attr.falseValue)) { + falseValue = scope.$eval(attr.falseValue); + } + var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean'; + if (hasExoticValues) { + controller.$parsers.push(function (viewValue) { + return viewValue ? trueValue : falseValue; + }); + scope.$watch(attr.ngModel, function (newValue, oldValue) { + controller.$render(); + }); + } + controller.$render = function () { + var isActive = angular.equals(controller.$modelValue, trueValue); + if (isInput) { + element[0].checked = isActive; + } + activeElement.toggleClass(options.activeClass, isActive); + }; + element.bind(options.toggleEvent, function () { + scope.$apply(function () { + if (!isInput) { + controller.$setViewValue(!activeElement.hasClass('active')); + } + if (!hasExoticValues) { + controller.$render(); + } + }); + }); + } + }; + } + ]).directive('bsRadioGroup', function () { + return { + restrict: 'A', + require: 'ngModel', + compile: function postLink(element, attr) { + element.attr('data-toggle', 'buttons'); + element.removeAttr('ng-model'); + var children = element[0].querySelectorAll('input[type="radio"]'); + angular.forEach(children, function (child) { + angular.element(child).attr('bs-radio', ''); + angular.element(child).attr('ng-model', attr.ngModel); + }); + } + }; + }).directive('bsRadio', [ + '$button', + function ($button) { + var defaults = $button.defaults; + var constantValueRegExp = /^(true|false|\d+)$/; + return { + restrict: 'A', + require: 'ngModel', + link: function postLink(scope, element, attr, controller) { + var options = defaults; + var isInput = element[0].nodeName === 'INPUT'; + var activeElement = isInput ? element.parent() : element; + var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value; + controller.$render = function () { + var isActive = angular.equals(controller.$modelValue, value); + if (isInput) { + element[0].checked = isActive; + } + activeElement.toggleClass(options.activeClass, isActive); + }; + element.bind(options.toggleEvent, function () { + scope.$apply(function () { + controller.$setViewValue(value); + controller.$render(); + }); + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$dropdown', template); + } + ]).provider('$dropdown', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + placement: 'bottom-left', + template: '$dropdown', + trigger: 'click', + keyboard: true, + container: false + }; + this.$get = [ + '$window', + '$tooltip', + function ($window, $tooltip) { + var bodyEl = angular.element($window.document.body); + var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector; + function DropdownFactory(element, config) { + var $dropdown = {}; + var options = angular.extend({}, defaults, config); + $dropdown = $tooltip(element, options); + $dropdown.$onKeyDown = function (evt) { + if (!/(38|40)/.test(evt.keyCode)) + return; + evt.preventDefault(); + evt.stopPropagation(); + var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a')); + if (!items.length) + return; + var index; + angular.forEach(items, function (el, i) { + if (matchesSelector && matchesSelector.call(el, ':focus')) + index = i; + }); + if (evt.keyCode === 38 && index > 0) + index--; + else if (evt.keyCode === 40 && index < items.length - 1) + index++; + else if (angular.isUndefined(index)) + index = 0; + items.eq(index)[0].focus(); + }; + var show = $dropdown.show; + $dropdown.show = function () { + show(); + setTimeout(function () { + options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown); + bodyEl.on('click', onBodyClick); + }); + }; + var hide = $dropdown.hide; + $dropdown.hide = function () { + options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown); + bodyEl.off('click', onBodyClick); + hide(); + }; + function onBodyClick(evt) { + if (evt.target === element[0]) + return; + return evt.target !== element[0] && $dropdown.hide(); + } + return $dropdown; + } + return DropdownFactory; + } + ]; + }).directive('bsDropdown', [ + '$window', + '$location', + '$sce', + '$dropdown', + function ($window, $location, $sce, $dropdown) { + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'keyboard', + 'container', + 'delay', + 'trigger', + 'animation', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) { + scope.content = newValue; + }, true); + var dropdown = $dropdown(element, options); + scope.$on('$destroy', function () { + dropdown.destroy(); + options = null; + dropdown = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.jqlite.debounce', []).constant('debounce', function (func, wait, immediate) { + var timeout, args, context, timestamp, result; + return function () { + context = this; + args = arguments; + timestamp = new Date(); + var later = function () { + var last = new Date() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) + result = func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) + result = func.apply(context, args); + return result; + }; + }).constant('throttle', function (func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function () { + previous = options.leading === false ? 0 : new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function () { + var now = new Date(); + if (!previous && options.leading === false) + previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }); + angular.module('mgcrea.ngStrap.jqlite.dimensions', []).factory('dimensions', [ + '$document', + '$window', + function ($document, $window) { + var jqLite = angular.element; + var fn = {}; + var nodeName = fn.nodeName = function (element, name) { + return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase(); + }; + fn.css = function (element, prop, extra) { + var value; + if (element.currentStyle) { + value = element.currentStyle[prop]; + } else if (window.getComputedStyle) { + value = window.getComputedStyle(element)[prop]; + } else { + value = element.style[prop]; + } + return extra === true ? parseFloat(value) || 0 : value; + }; + fn.offset = function (element) { + var boxRect = element.getBoundingClientRect(); + var docElement = element.ownerDocument; + return { + width: element.offsetWidth, + height: element.offsetHeight, + top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0), + left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0) + }; + }; + fn.position = function (element) { + var offsetParentRect = { + top: 0, + left: 0 + }, offsetParentElement, offset; + if (fn.css(element, 'position') === 'fixed') { + offset = element.getBoundingClientRect(); + } else { + offsetParentElement = offsetParent(element); + offset = fn.offset(element); + offset = fn.offset(element); + if (!nodeName(offsetParentElement, 'html')) { + offsetParentRect = fn.offset(offsetParentElement); + } + offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true); + offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true); + } + return { + width: element.offsetWidth, + height: element.offsetHeight, + top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true), + left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true) + }; + }; + var offsetParent = function offsetParentElement(element) { + var docElement = element.ownerDocument; + var offsetParent = element.offsetParent || docElement; + while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docElement.documentElement; + }; + fn.height = function (element, outer) { + var value = element.offsetHeight; + if (outer) { + value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true); + } else { + value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true); + } + return value; + }; + fn.width = function (element, outer) { + var value = element.offsetWidth; + if (outer) { + value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true); + } else { + value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true); + } + return value; + }; + return fn; + } + ]); + angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.jqlite.dimensions']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$modal', template); + } + ]).provider('$modal', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'modal', + placement: 'top', + template: '$modal', + container: false, + element: null, + backdrop: true, + keyboard: true, + show: true + }; + this.$get = [ + '$window', + '$rootScope', + '$compile', + '$q', + '$templateCache', + '$http', + '$animate', + '$timeout', + 'dimensions', + function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) { + var forEach = angular.forEach; + var jqLite = angular.element; + var trim = String.prototype.trim; + var bodyElement = jqLite($window.document.body); + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + var findElement = function (query, element) { + return jqLite((element || document).querySelectorAll(query)); + }; + function ModalFactory(config) { + var $modal = {}; + var options = angular.extend({}, defaults, config); + $modal.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template)); + var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new(); + if (!options.element && !options.container) { + options.container = 'body'; + } + if (!options.scope) { + forEach([ + 'title', + 'content' + ], function (key) { + if (options[key]) + scope[key] = options[key]; + }); + } + scope.$hide = function () { + scope.$$postDigest(function () { + $modal.hide(); + }); + }; + scope.$show = function () { + scope.$$postDigest(function () { + $modal.show(); + }); + }; + scope.$toggle = function () { + scope.$$postDigest(function () { + $modal.toggle(); + }); + }; + var modalLinker, modalElement; + var backdropElement = jqLite('
'); + $modal.$promise.then(function (template) { + if (angular.isObject(template)) + template = template.data; + template = trim.apply(template); + modalLinker = $compile(template); + $modal.init(); + }); + $modal.init = function () { + if (options.show) { + scope.$$postDigest(function () { + $modal.show(); + }); + } + }; + $modal.destroy = function () { + modalElement.remove(); + backdropElement.remove(); + scope.$destroy(); + }; + $modal.show = function () { + var parent = options.container ? findElement(options.container) : null; + var after = options.container ? null : options.element; + modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) { + }); + modalElement.css({ display: 'block' }).addClass(options.placement); + if (options.animation) { + if (options.backdrop) { + backdropElement.addClass('animation-fade'); + } + modalElement.addClass(options.animation); + } + if (options.backdrop) { + $animate.enter(backdropElement, bodyElement, null, function () { + }); + } + $animate.enter(modalElement, parent, after, function () { + }); + scope.$isShown = true; + scope.$digest(); + $modal.focus(); + bodyElement.addClass(options.prefixClass + '-open'); + if (options.backdrop) { + modalElement.on('click', hideOnBackdropClick); + } + if (options.keyboard) { + modalElement.on('keyup', $modal.$onKeyUp); + } + }; + $modal.hide = function () { + $animate.leave(modalElement, function () { + bodyElement.removeClass('modal-open'); + }); + if (options.backdrop) { + $animate.leave(backdropElement, function () { + }); + } + scope.$digest(); + scope.$isShown = false; + if (options.backdrop) { + modalElement.off('click', hideOnBackdropClick); + } + if (options.keyboard) { + modalElement.off('keyup', $modal.$onKeyUp); + } + }; + $modal.toggle = function () { + scope.$isShown ? $modal.hide() : $modal.show(); + }; + $modal.focus = function () { + modalElement[0].focus(); + }; + $modal.$onKeyUp = function (evt) { + evt.which === 27 && $modal.hide(); + }; + function hideOnBackdropClick(evt) { + if (evt.target !== evt.currentTarget) + return; + options.backdrop === 'static' ? $modal.focus() : $modal.hide(); + } + return $modal; + } + return ModalFactory; + } + ]; + }).directive('bsModal', [ + '$window', + '$location', + '$sce', + '$modal', + function ($window, $location, $sce, $modal) { + var forEach = angular.forEach; + var isDefined = angular.isDefined; + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + forEach([ + 'template', + 'placement', + 'backdrop', + 'keyboard', + 'show', + 'container', + 'animation' + ], function (key) { + if (isDefined(attr[key])) + options[key] = attr[key]; + }); + forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var modal = $modal(options); + element.on(attr.trigger || 'click', modal.toggle); + scope.$on('$destroy', function () { + modal.destroy(); + options = null; + modal = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '
' + '

' + '
' + '
'; + $templateCache.put('$popover', template); + } + ]).provider('$popover', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + placement: 'right', + template: '$popover', + trigger: 'click', + keyboard: true, + title: '', + content: '', + delay: 0, + container: false + }; + this.$get = [ + '$tooltip', + function ($tooltip) { + function PopoverFactory(element, config) { + var options = angular.extend({}, defaults, config); + return $tooltip(element, options); + } + return PopoverFactory; + } + ]; + }).directive('bsPopover', [ + '$window', + '$location', + '$sce', + '$popover', + function ($window, $location, $sce, $popover) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'keyboard', + 'container', + 'delay', + 'trigger', + 'animation', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + angular.isDefined(oldValue) && requestAnimationFrame(function () { + popover && popover.$applyPlacement(); + }); + }); + }); + attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + angular.isDefined(oldValue) && requestAnimationFrame(function () { + popover && popover.$applyPlacement(); + }); + }, true); + var popover = $popover(element, options); + scope.$on('$destroy', function () { + popover.destroy(); + options = null; + popover = null; + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.scrollspy', [ + 'mgcrea.ngStrap.jqlite.debounce', + 'mgcrea.ngStrap.jqlite.dimensions' + ]).provider('$scrollspy', function () { + var spies = this.$$spies = {}; + var defaults = this.defaults = { + debounce: 150, + throttle: 100, + offset: 100 + }; + this.$get = [ + '$window', + '$document', + '$rootScope', + 'dimensions', + 'debounce', + 'throttle', + function ($window, $document, $rootScope, dimensions, debounce, throttle) { + var windowEl = angular.element($window); + var docEl = angular.element($document.prop('documentElement')); + var bodyEl = angular.element($window.document.body); + function nodeName(element, name) { + return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase(); + } + function ScrollSpyFactory(config) { + var options = angular.extend({}, defaults, config); + if (!options.element) + options.element = bodyEl; + var isWindowSpy = nodeName(options.element, 'body'); + var scrollEl = isWindowSpy ? windowEl : options.element; + var scrollId = isWindowSpy ? 'window' : options.id; + if (spies[scrollId]) { + spies[scrollId].$$count++; + return spies[scrollId]; + } + var $scrollspy = {}; + var trackedElements = $scrollspy.$trackedElements = []; + var sortedElements = []; + var activeTarget; + var debouncedCheckPosition; + var throttledCheckPosition; + var debouncedCheckOffsets; + var viewportHeight; + var scrollTop; + $scrollspy.init = function () { + this.$$count = 1; + debouncedCheckPosition = debounce(this.checkPosition, options.debounce); + throttledCheckPosition = throttle(this.checkPosition, options.throttle); + scrollEl.on('click', this.checkPositionWithEventLoop); + windowEl.on('resize', debouncedCheckPosition); + scrollEl.on('scroll', throttledCheckPosition); + debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce); + $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets); + $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets); + debouncedCheckOffsets(); + if (scrollId) { + spies[scrollId] = $scrollspy; + } + }; + $scrollspy.destroy = function () { + this.$$count--; + if (this.$$count > 0) { + return; + } + scrollEl.off('click', this.checkPositionWithEventLoop); + windowEl.off('resize', debouncedCheckPosition); + scrollEl.off('scroll', debouncedCheckPosition); + $rootScope.$off('$viewContentLoaded', debouncedCheckOffsets); + $rootScope.$off('$includeContentLoaded', debouncedCheckOffsets); + }; + $scrollspy.checkPosition = function () { + scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0; + viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight')); + if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) { + return $scrollspy.$activateElement(sortedElements[0]); + } + for (var i = sortedElements.length; i--;) { + if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) + continue; + if (activeTarget === sortedElements[i].target) + continue; + if (scrollTop < sortedElements[i].offsetTop) + continue; + if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) + continue; + return $scrollspy.$activateElement(sortedElements[i]); + } + }; + $scrollspy.checkPositionWithEventLoop = function () { + setTimeout(this.checkPosition, 1); + }; + $scrollspy.$activateElement = function (element) { + if (activeTarget) { + var activeElement = $scrollspy.$getTrackedElement(activeTarget); + if (activeElement) { + activeElement.source.removeClass('active'); + if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) { + activeElement.source.parent().parent().removeClass('active'); + } + } + } + activeTarget = element.target; + element.source.addClass('active'); + if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) { + element.source.parent().parent().addClass('active'); + } + }; + $scrollspy.$getTrackedElement = function (target) { + return trackedElements.filter(function (obj) { + return obj.target === target; + })[0]; + }; + $scrollspy.checkOffsets = function () { + angular.forEach(trackedElements, function (trackedElement) { + var targetElement = document.querySelector(trackedElement.target); + trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null; + if (options.offset && trackedElement.offsetTop !== null) + trackedElement.offsetTop -= options.offset * 1; + }); + sortedElements = trackedElements.filter(function (el) { + return el.offsetTop !== null; + }).sort(function (a, b) { + return a.offsetTop - b.offsetTop; + }); + debouncedCheckPosition(); + }; + $scrollspy.trackElement = function (target, source) { + trackedElements.push({ + target: target, + source: source + }); + }; + $scrollspy.untrackElement = function (target, source) { + var toDelete; + for (var i = trackedElements.length; i--;) { + if (trackedElements[i].target === target && trackedElements[i].source === source) { + toDelete = i; + break; + } + } + trackedElements = trackedElements.splice(toDelete, 1); + }; + $scrollspy.activate = function (i) { + trackedElements[i].addClass('active'); + }; + $scrollspy.init(); + return $scrollspy; + } + return ScrollSpyFactory; + } + ]; + }).directive('bsScrollspy', [ + '$rootScope', + 'debounce', + 'dimensions', + '$scrollspy', + function ($rootScope, debounce, dimensions, $scrollspy) { + return { + restrict: 'EAC', + link: function postLink(scope, element, attr) { + var options = { scope: scope }; + angular.forEach([ + 'offset', + 'target' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + var scrollspy = $scrollspy(options); + scrollspy.trackElement(options.target, element); + scope.$on('$destroy', function () { + scrollspy.untrackElement(options.target, element); + scrollspy.destroy(); + options = null; + scrollspy = null; + }); + } + }; + } + ]).directive('bsScrollspyList', [ + '$rootScope', + 'debounce', + 'dimensions', + '$scrollspy', + function ($rootScope, debounce, dimensions, $scrollspy) { + return { + restrict: 'A', + compile: function postLink(element, attr) { + var children = element[0].querySelectorAll('li > a[href]'); + angular.forEach(children, function (child) { + var childEl = angular.element(child); + childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href')); + }); + } + }; + } + ]); + angular.module('mgcrea.ngStrap.tab', []).run([ + '$templateCache', + function ($templateCache) { + $templateCache.put('$pane', '{{pane.content}}'); + var template = '' + '
' + '
' + '
'; + $templateCache.put('$tabs', template); + } + ]).provider('$tab', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + template: '$tabs' + }; + this.$get = function () { + return { defaults: defaults }; + }; + }).directive('bsTabs', [ + '$window', + '$animate', + '$tab', + function ($window, $animate, $tab) { + var defaults = $tab.defaults; + return { + restrict: 'EAC', + scope: true, + require: '?ngModel', + templateUrl: function (element, attr) { + return attr.template || defaults.template; + }, + link: function postLink(scope, element, attr, controller) { + var options = defaults; + angular.forEach(['animation'], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + attr.bsTabs && scope.$watch(attr.bsTabs, function (newValue, oldValue) { + scope.panes = newValue; + }, true); + element.addClass('tabs'); + if (options.animation) { + element.addClass(options.animation); + } + scope.active = scope.activePane = 0; + scope.setActive = function (index, ev) { + scope.active = index; + if (controller) { + controller.$setViewValue(index); + } + }; + if (controller) { + controller.$render = function () { + scope.active = controller.$modelValue * 1; + }; + } + } + }; + } + ]); + angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.jqlite.dimensions']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '
' + '
' + '
'; + $templateCache.put('$tooltip', template); + } + ]).provider('$tooltip', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'tooltip', + container: false, + placement: 'top', + template: '$tooltip', + trigger: 'hover focus', + keyboard: false, + type: '', + title: '', + delay: 0 + }; + this.$get = [ + '$window', + '$rootScope', + '$compile', + '$q', + '$templateCache', + '$http', + '$animate', + '$timeout', + 'dimensions', + function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) { + var trim = String.prototype.trim; + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + var findElement = function (query, element) { + return angular.element((element || document).querySelectorAll(query)); + }; + function TooltipFactory(element, config) { + var $tooltip = {}; + var options = angular.extend({}, defaults, config); + $tooltip.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template)); + var scope = options.scope.$new() || $rootScope.$new(); + if (options.delay && angular.isString(options.delay)) { + options.delay = parseFloat(options.delay); + } + scope.$hide = function () { + scope.$$postDigest(function () { + $tooltip.hide(); + }); + }; + scope.$show = function () { + scope.$$postDigest(function () { + $tooltip.show(); + }); + }; + scope.$toggle = function () { + scope.$$postDigest(function () { + $tooltip.toggle(); + }); + }; + var timeout, hoverState, isShown; + var tipLinker, tipElement, tipTemplate; + $tooltip.$promise.then(function (template) { + if (angular.isObject(template)) + template = template.data; + template = trim.apply(template); + tipTemplate = template; + tipLinker = $compile(template); + $tooltip.init(); + }); + $tooltip.init = function () { + if (options.delay && angular.isNumber(options.delay)) { + options.delay = { + show: options.delay, + hide: options.delay + }; + } + var triggers = options.trigger.split(' '); + for (var i = triggers.length; i--;) { + var trigger = triggers[i]; + if (trigger === 'click') { + element.on('click', this.toggle); + } else if (trigger !== 'manual') { + element.on(trigger === 'hover' ? 'mouseenter' : 'focus', this.enter); + element.on(trigger === 'hover' ? 'mouseleave' : 'blur', this.leave); + } + } + }; + $tooltip.destroy = function () { + var triggers = options.trigger.split(' '); + for (var i = triggers.length; i--;) { + var trigger = triggers[i]; + if (trigger === 'click') { + element.off('click', this.toggle); + } else if (trigger !== 'manual') { + element.off(trigger === 'hover' ? 'mouseenter' : 'focus', this.enter); + element.off(trigger === 'hover' ? 'mouseleave' : 'blur', this.leave); + } + } + if (tipElement) { + tipElement.remove(); + tipElement = null; + } + scope.$destroy(); + }; + $tooltip.enter = function () { + clearTimeout(timeout); + hoverState = 'in'; + if (!options.delay || !options.delay.show) { + return $tooltip.show(); + } + timeout = setTimeout(function () { + if (hoverState === 'in') + $tooltip.show(); + }, options.delay.show); + }; + $tooltip.show = function () { + var parent = options.container ? findElement(options.container) : null; + var after = options.container ? null : element; + tipElement = $tooltip.$element = tipLinker(scope, function (clonedElement, scope) { + }); + tipElement.css({ + top: '0px', + left: '0px', + display: 'block' + }).addClass(options.placement); + if (options.animation) + tipElement.addClass(options.animation); + if (options.type) + tipElement.addClass(options.prefixClass + '-' + options.type); + $animate.enter(tipElement, parent, after, function () { + }); + isShown = true; + scope.$digest(); + requestAnimationFrame($tooltip.$applyPlacement); + if (options.keyboard) { + $tooltip.focus(); + tipElement.on('keyup', $tooltip.$onKeyUp); + } + }; + $tooltip.leave = function () { + clearTimeout(timeout); + hoverState = 'out'; + if (!options.delay || !options.delay.hide) { + return $tooltip.hide(); + } + timeout = setTimeout(function () { + if (hoverState === 'out') { + $tooltip.hide(); + } + }, options.delay.hide); + }; + $tooltip.hide = function () { + $animate.leave(tipElement, function () { + }); + scope.$digest(); + isShown = false; + if (options.keyboard) { + tipElement.off('keyup', $tooltip.$onKeyUp); + } + }; + $tooltip.toggle = function () { + isShown ? $tooltip.leave() : $tooltip.enter(); + }; + $tooltip.focus = function () { + tipElement[0].focus(); + }; + $tooltip.$applyPlacement = function () { + if (!tipElement) + return; + var elementPosition = getPosition(); + var tipWidth = tipElement.prop('offsetWidth'), tipHeight = tipElement.prop('offsetHeight'); + var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight); + tipPosition.top += 'px'; + tipPosition.left += 'px'; + tipElement.css(tipPosition); + }; + $tooltip.$onKeyUp = function (evt) { + evt.which === 27 && $tooltip.hide(); + }; + function getPosition() { + if (options.container === 'body') { + return dimensions.offset(element[0]); + } else { + return dimensions.position(element[0]); + } + } + function getCalculatedOffset(placement, position, actualWidth, actualHeight) { + var offset; + var split = placement.split('-'); + switch (split[0]) { + case 'right': + offset = { + top: position.top + position.height / 2 - actualHeight / 2, + left: position.left + position.width + }; + break; + case 'bottom': + offset = { + top: position.top + position.height, + left: position.left + position.width / 2 - actualWidth / 2 + }; + break; + case 'left': + offset = { + top: position.top + position.height / 2 - actualHeight / 2, + left: position.left - actualWidth + }; + break; + default: + offset = { + top: position.top - actualHeight, + left: position.left + position.width / 2 - actualWidth / 2 + }; + break; + } + if (!split[1]) { + return offset; + } + if (split[0] === 'top' || split[0] === 'bottom') { + switch (split[1]) { + case 'left': + offset.left = position.left; + break; + case 'right': + offset.left = position.left + position.width - actualWidth; + } + } else if (split[0] === 'left' || split[0] === 'right') { + switch (split[1]) { + case 'top': + offset.top = position.top - actualHeight; + break; + case 'bottom': + offset.top = position.top + position.height; + } + } + return offset; + } + return $tooltip; + } + return TooltipFactory; + } + ]; + }).directive('bsTooltip', [ + '$window', + '$location', + '$sce', + '$tooltip', + function ($window, $location, $sce, $tooltip) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'container', + 'delay', + 'trigger', + 'animation', + 'type', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach(['title'], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + angular.isDefined(oldValue) && requestAnimationFrame(function () { + tooltip && tooltip.$applyPlacement(); + }); + }); + }); + attr.bsTooltip && scope.$watch(attr.bsTooltip, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + angular.isDefined(oldValue) && requestAnimationFrame(function () { + tooltip && tooltip.$applyPlacement(); + }); + }, true); + var tooltip = $tooltip(element, options); + scope.$on('$destroy', function () { + tooltip.destroy(); + options = null; + tooltip = null; + }); + } + }; + } + ]); +}(window, document, window.jQuery)); \ No newline at end of file diff --git a/dist/angular-strap.min.js b/dist/angular-strap.min.js new file mode 100644 index 000000000..f434dc133 --- /dev/null +++ b/dist/angular-strap.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +!function(a,b){"use strict";angular.module("mgcrea.ngStrap",["mgcrea.ngStrap.modal","mgcrea.ngStrap.aside","mgcrea.ngStrap.alert","mgcrea.ngStrap.button","mgcrea.ngStrap.tooltip","mgcrea.ngStrap.popover","mgcrea.ngStrap.dropdown","mgcrea.ngStrap.scrollspy","mgcrea.ngStrap.affix","mgcrea.ngStrap.tab"]),angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.jqlite.dimensions"]).provider("$affix",function(){var a=this.defaults={offsetTop:"auto"};this.$get=["$window","dimensions",function(b,c){function d(d,g){function h(a,c,d){var e=b.pageYOffset,f=b.document.body.scrollHeight;return r>=e?"top":null!==a&&e+a<=c.top?"middle":null!==s&&c.top+d+l>=f-s?"bottom":"middle"}var i={},j=angular.extend({},a,g),k="affix affix-top affix-bottom",l=0,m=0,n=null,o=null,p=d.parent();if(j.offsetParent)if(j.offsetParent.match(/^\d+$/))for(var q=0;q<1*j.offsetParent-1;q++)p=p.parent();else p=angular.element(j.offsetParent);var r=0;j.offsetTop&&("auto"===j.offsetTop&&(j.offsetTop="+0"),j.offsetTop.match(/^[-+]\d+$/)?(l-=1*j.offsetTop,r=j.offsetParent?c.offset(p[0]).top+1*j.offsetTop:c.offset(d[0]).top-c.css(d[0],"marginTop",!0)+1*j.offsetTop):r=1*j.offsetTop);var s=0;return j.offsetBottom&&(s=j.offsetParent&&j.offsetBottom.match(/^[-+]\d+$/)?b.document.body.scrollHeight-(c.offset(p[0]).top+c.height(p[0]))+1*j.offsetBottom+1:1*j.offsetBottom),i.init=function(){m=c.offset(d[0]).top+l,e.on("scroll",this.checkPosition),e.on("click",this.checkPositionWithEventLoop),this.checkPosition(),this.checkPositionWithEventLoop()},i.destroy=function(){e.off("scroll",this.checkPosition),e.off("click",this.checkPositionWithEventLoop)},i.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},i.checkPosition=function(){var a=b.pageYOffset,e=c.offset(d[0]),g=c.height(d[0]),i=h(o,e,g);n!==i&&(n=i,d.removeClass(k).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(o=null,d.css("position",j.offsetParent?"":"relative"),d.css("top","")):"bottom"===i?(o=j.offsetUnpin?-(1*j.offsetUnpin):e.top-a,d.css("position",j.offsetParent?"":"relative"),d.css("top",j.offsetParent?"":f[0].offsetHeight-s-g-m+"px")):(o=null,d.css("position","fixed"),d.css("top",l+"px")))},i.init(),i}var e=angular.element(b),f=angular.element(b.document.body);return d}]}).directive("bsAffix",["$affix","dimensions",function(a){return{restrict:"EAC",link:function(b,c,d){var e={scope:b,offsetTop:"auto"};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(a){angular.isDefined(d[a])&&(e[a]=d[a])});var f=a(c,e);b.$on("$destroy",function(){e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.alert",[]).run(["$templateCache",function(a){var b='
 
';a.put("$alert",b)}]).provider("$alert",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"alert",placement:null,template:"$alert",container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1};this.$get=["$modal","$timeout",function(b,c){function d(d){var e={},f=angular.extend({},a,d);e=b(f),f.scope||angular.forEach(["type"],function(a){f[a]&&(e.scope[a]=f[a])});var g=e.show;return f.duration&&(e.show=function(){g(),c(function(){e.hide()},1e3*f.duration)}),e}return d}]}).directive("bsAlert",["$window","$location","$sce","$alert",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","placement","keyboard","container","animation","duration"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content","type"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAlert&&a.$watch(c.bsAlert,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.aside",["mgcrea.ngStrap.modal"]).run(["$templateCache",function(a){var b='';a.put("$aside",b)}]).provider("$aside",function(){var a=this.defaults={animation:"animation-fadeAndSlideRight",prefixClass:"aside",placement:"right",template:"$aside",container:!1,element:null,backdrop:!0,keyboard:!0,show:!0};this.$get=["$modal",function(b){function c(c){var d={},e=angular.extend({},a,c);return d=b(e)}return c}]}).directive("bsAside",["$window","$location","$sce","$aside",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","placement","backdrop","keyboard","show","container","animation"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAside&&a.$watch(c.bsAside,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.button",[]).provider("$button",function(){var a=this.defaults={activeClass:"active",toggleEvent:"click"};this.$get=function(){return{defaults:a}}}).directive("bsCheckboxGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="checkbox"]');angular.forEach(c,function(a){var c=angular.element(a);c.attr("bs-checkbox",""),c.attr("ng-model",b.ngModel+"."+c.attr("value"))})}}}).directive("bsCheckbox",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=angular.isDefined(e.trueValue)?e.trueValue:!0;c.test(e.trueValue)&&(j=a.$eval(e.trueValue));var k=angular.isDefined(e.falseValue)?e.falseValue:!1;c.test(e.falseValue)&&(k=a.$eval(e.falseValue));var l="boolean"!=typeof j||"boolean"!=typeof k;l&&(f.$parsers.push(function(a){return a?j:k}),a.$watch(e.ngModel,function(){f.$render()})),f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){h||f.$setViewValue(!i.hasClass("active")),l||f.$render()})})}}}]).directive("bsRadioGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="radio"]');angular.forEach(c,function(a){angular.element(a).attr("bs-radio",""),angular.element(a).attr("ng-model",b.ngModel)})}}}).directive("bsRadio",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=c.test(e.value)?a.$eval(e.value):e.value;f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){f.$setViewValue(j),f.$render()})})}}}]),angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).run(["$templateCache",function(a){var b='';a.put("$dropdown",b)}]).provider("$dropdown",function(){var a=this.defaults={animation:"animation-fade",placement:"bottom-left",template:"$dropdown",trigger:"click",keyboard:!0,container:!1};this.$get=["$window","$tooltip",function(b,c){function d(b,d){function g(a){return a.target!==b[0]?a.target!==b[0]&&h.hide():void 0}var h={},i=angular.extend({},a,d);h=c(b,i),h.$onKeyDown=function(a){if(/(38|40)/.test(a.keyCode)){a.preventDefault(),a.stopPropagation();var b=angular.element(h.$element[0].querySelectorAll("li:not(.divider) a"));if(b.length){var c;angular.forEach(b,function(a,b){f&&f.call(a,":focus")&&(c=b)}),38===a.keyCode&&c>0?c--:40===a.keyCode&&cj?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e)))},j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e)),h}}).constant("throttle",function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date,g=null,f=a.apply(d,e)};return function(){var j=new Date;h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k?(clearTimeout(g),g=null,h=j,f=a.apply(d,e)):g||c.trailing===!1||(g=setTimeout(i,k)),f}}),angular.module("mgcrea.ngStrap.jqlite.dimensions",[]).factory("dimensions",["$document","$window",function(){var b=(angular.element,{}),c=b.nodeName=function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()};b.css=function(b,c,d){var e;return e=b.currentStyle?b.currentStyle[c]:a.getComputedStyle?a.getComputedStyle(b)[c]:b.style[c],d===!0?parseFloat(e)||0:e},b.offset=function(b){var c=b.getBoundingClientRect(),d=b.ownerDocument;return{width:b.offsetWidth,height:b.offsetHeight,top:c.top+(a.pageYOffset||d.documentElement.scrollTop)-(d.documentElement.clientTop||0),left:c.left+(a.pageXOffset||d.documentElement.scrollLeft)-(d.documentElement.clientLeft||0)}},b.position=function(a){var e,f,g={top:0,left:0};return"fixed"===b.css(a,"position")?f=a.getBoundingClientRect():(e=d(a),f=b.offset(a),f=b.offset(a),c(e,"html")||(g=b.offset(e)),g.top+=b.css(e,"borderTopWidth",!0),g.left+=b.css(e,"borderLeftWidth",!0)),{width:a.offsetWidth,height:a.offsetHeight,top:f.top-g.top-b.css(a,"marginTop",!0),left:f.left-g.left-b.css(a,"marginLeft",!0)}};var d=function(a){for(var d=a.ownerDocument,e=a.offsetParent||d;e&&!c(e,"html")&&"static"===b.css(e,"position");)e=e.offsetParent;return e||d.documentElement};return b.height=function(a,c){var d=a.offsetHeight;return c?d+=b.css(a,"marginTop",!0)+b.css(a,"marginBottom",!0):d-=b.css(a,"paddingTop",!0)+b.css(a,"paddingBottom",!0)+b.css(a,"borderTopWidth",!0)+b.css(a,"borderBottomWidth",!0),d},b.width=function(a,c){var d=a.offsetWidth;return c?d+=b.css(a,"marginLeft",!0)+b.css(a,"marginRight",!0):d-=b.css(a,"paddingLeft",!0)+b.css(a,"paddingRight",!0)+b.css(a,"borderLeftWidth",!0)+b.css(a,"borderRightWidth",!0),d},b}]),angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.jqlite.dimensions"]).run(["$templateCache",function(a){var b='';a.put("$modal",b)}]).provider("$modal",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"modal",placement:"top",template:"$modal",container:!1,element:null,backdrop:!0,keyboard:!0,show:!0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","dimensions",function(c,d,e,f,g,h,i){function j(b){function c(a){a.target===a.currentTarget&&("static"===p.backdrop?j.focus():j.hide())}var j={},p=angular.extend({},a,b);j.$promise=f.when(g.get(p.template)||h.get(p.template));var q=j.$scope=p.scope&&p.scope.$new()||d.$new();p.element||p.container||(p.container="body"),p.scope||k(["title","content"],function(a){p[a]&&(q[a]=p[a])}),q.$hide=function(){q.$$postDigest(function(){j.hide()})},q.$show=function(){q.$$postDigest(function(){j.show()})},q.$toggle=function(){q.$$postDigest(function(){j.toggle()})};var r,s,t=l('
');return j.$promise.then(function(a){angular.isObject(a)&&(a=a.data),a=m.apply(a),r=e(a),j.init()}),j.init=function(){p.show&&q.$$postDigest(function(){j.show()})},j.destroy=function(){s.remove(),t.remove(),q.$destroy()},j.show=function(){var a=p.container?o(p.container):null,b=p.container?null:p.element;s=j.$element=r(q,function(){}),s.css({display:"block"}).addClass(p.placement),p.animation&&(p.backdrop&&t.addClass("animation-fade"),s.addClass(p.animation)),p.backdrop&&i.enter(t,n,null,function(){}),i.enter(s,a,b,function(){}),q.$isShown=!0,q.$digest(),j.focus(),n.addClass(p.prefixClass+"-open"),p.backdrop&&s.on("click",c),p.keyboard&&s.on("keyup",j.$onKeyUp)},j.hide=function(){i.leave(s,function(){n.removeClass("modal-open")}),p.backdrop&&i.leave(t,function(){}),q.$digest(),q.$isShown=!1,p.backdrop&&s.off("click",c),p.keyboard&&s.off("keyup",j.$onKeyUp)},j.toggle=function(){q.$isShown?j.hide():j.show()},j.focus=function(){s[0].focus()},j.$onKeyUp=function(a){27===a.which&&j.hide()},j}var k=angular.forEach,l=angular.element,m=String.prototype.trim,n=l(c.document.body),o=(c.requestAnimationFrame||c.setTimeout,function(a,c){return l((c||b).querySelectorAll(a))});return j}]}).directive("bsModal",["$window","$location","$sce","$modal",function(a,b,c,d){{var e=angular.forEach,f=angular.isDefined;a.requestAnimationFrame||a.setTimeout}return{restrict:"EAC",scope:!0,link:function(a,b,c){var g={scope:a,element:b,show:!1};e(["template","placement","backdrop","keyboard","show","container","animation"],function(a){f(c[a])&&(g[a]=c[a])}),e(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsModal&&a.$watch(c.bsModal,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var h=d(g);b.on(c.trigger||"click",h.toggle),a.$on("$destroy",function(){h.destroy(),g=null,h=null})}}}]),angular.module("mgcrea.ngStrap.popover",["mgcrea.ngStrap.tooltip"]).run(["$templateCache",function(a){var b='

';a.put("$popover",b)}]).provider("$popover",function(){var a=this.defaults={animation:"animation-fade",placement:"right",template:"$popover",trigger:"click",keyboard:!0,title:"",content:"",delay:0,container:!1};this.$get=["$tooltip",function(b){function c(c,d){var e=angular.extend({},a,d);return b(c,e)}return c}]}).directive("bsPopover",["$window","$location","$sce","$popover",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["placement","keyboard","container","delay","trigger","animation","template"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsPopover&&a.$watch(c.bsPopover,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}]),angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.jqlite.debounce","mgcrea.ngStrap.jqlite.dimensions"]).provider("$scrollspy",function(){var a=this.$$spies={},c=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(d,e,f,g,h,i){function j(a,b){return a[0].nodeName&&a[0].nodeName.toLowerCase()===b.toLowerCase()}function k(e){var k=angular.extend({},c,e);k.element||(k.element=n);var o=j(k.element,"body"),p=o?l:k.element,q=o?"window":k.id;if(a[q])return a[q].$$count++,a[q];var r,s,t,u,v,w,x={},y=x.$trackedElements=[],z=[];return x.init=function(){this.$$count=1,s=h(this.checkPosition,k.debounce),t=i(this.checkPosition,k.throttle),p.on("click",this.checkPositionWithEventLoop),l.on("resize",s),p.on("scroll",t),u=h(this.checkOffsets,k.debounce),f.$on("$viewContentLoaded",u),f.$on("$includeContentLoaded",u),u(),q&&(a[q]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(p.off("click",this.checkPositionWithEventLoop),l.off("resize",s),p.off("scroll",s),f.$off("$viewContentLoaded",u),f.$off("$includeContentLoaded",u))},x.checkPosition=function(){if(w=(o?d.pageYOffset:p.prop("scrollTop"))||0,v=Math.max(d.innerHeight,m.prop("clientHeight")),wz[a+1].offsetTop))return x.$activateElement(z[a])},x.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},x.$activateElement=function(a){if(r){var b=x.$getTrackedElement(r);b&&(b.source.removeClass("active"),j(b.source,"li")&&j(b.source.parent().parent(),"li")&&b.source.parent().parent().removeClass("active"))}r=a.target,a.source.addClass("active"),j(a.source,"li")&&j(a.source.parent().parent(),"li")&&a.source.parent().parent().addClass("active")},x.$getTrackedElement=function(a){return y.filter(function(b){return b.target===a})[0]},x.checkOffsets=function(){angular.forEach(y,function(a){var c=b.querySelector(a.target);a.offsetTop=c?g.offset(c).top:null,k.offset&&null!==a.offsetTop&&(a.offsetTop-=1*k.offset)}),z=y.filter(function(a){return null!==a.offsetTop}).sort(function(a,b){return a.offsetTop-b.offsetTop}),s()},x.trackElement=function(a,b){y.push({target:a,source:b})},x.untrackElement=function(a,b){for(var c,d=y.length;d--;)if(y[d].target===a&&y[d].source===b){c=d;break}y=y.splice(c,1)},x.activate=function(a){y[a].addClass("active")},x.init(),x}var l=angular.element(d),m=angular.element(e.prop("documentElement")),n=angular.element(d.document.body);return k}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(a,b,c,d){return{restrict:"EAC",link:function(a,b,c){var e={scope:a};angular.forEach(["offset","target"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])});var f=d(e);f.trackElement(e.target,b),a.$on("$destroy",function(){f.untrackElement(e.target,b),f.destroy(),e=null,f=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(a){var b=a[0].querySelectorAll("li > a[href]");angular.forEach(b,function(a){var b=angular.element(a);b.parent().attr("bs-scrollspy","").attr("data-target",b.attr("href"))})}}}]),angular.module("mgcrea.ngStrap.tab",[]).run(["$templateCache",function(a){a.put("$pane","{{pane.content}}");var b='
';a.put("$tabs",b)}]).provider("$tab",function(){var a=this.defaults={animation:"animation-fade",template:"$tabs"};this.$get=function(){return{defaults:a}}}).directive("bsTabs",["$window","$animate","$tab",function(a,b,c){var d=c.defaults;return{restrict:"EAC",scope:!0,require:"?ngModel",templateUrl:function(a,b){return b.template||d.template},link:function(a,b,c,e){var f=d;angular.forEach(["animation"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),c.bsTabs&&a.$watch(c.bsTabs,function(b){a.panes=b},!0),b.addClass("tabs"),f.animation&&b.addClass(f.animation),a.active=a.activePane=0,a.setActive=function(b){a.active=b,e&&e.$setViewValue(b)},e&&(e.$render=function(){a.active=1*e.$modelValue})}}}]),angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.jqlite.dimensions"]).run(["$templateCache",function(a){var b='
';a.put("$tooltip",b)}]).provider("$tooltip",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"tooltip",container:!1,placement:"top",template:"$tooltip",trigger:"hover focus",keyboard:!1,type:"",title:"",delay:0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","dimensions",function(c,d,e,f,g,h,i,j,k){function l(b,c){function j(){return"body"===q.container?k.offset(b[0]):k.position(b[0])}function l(a,b,c,d){var e,f=a.split("-");switch(f[0]){case"right":e={top:b.top+b.height/2-d/2,left:b.left+b.width};break;case"bottom":e={top:b.top+b.height,left:b.left+b.width/2-c/2};break;case"left":e={top:b.top+b.height/2-d/2,left:b.left-c};break;default:e={top:b.top-d,left:b.left+b.width/2-c/2}}if(!f[1])return e;if("top"===f[0]||"bottom"===f[0])switch(f[1]){case"left":e.left=b.left;break;case"right":e.left=b.left+b.width-c}else if("left"===f[0]||"right"===f[0])switch(f[1]){case"top":e.top=b.top-d;break;case"bottom":e.top=b.top+b.height}return e}var p={},q=angular.extend({},a,c);p.$promise=f.when(g.get(q.template)||h.get(q.template));var r=q.scope.$new()||d.$new();q.delay&&angular.isString(q.delay)&&(q.delay=parseFloat(q.delay)),r.$hide=function(){r.$$postDigest(function(){p.hide()})},r.$show=function(){r.$$postDigest(function(){p.show()})},r.$toggle=function(){r.$$postDigest(function(){p.toggle()})};var s,t,u,v,w,x;return p.$promise.then(function(a){angular.isObject(a)&&(a=a.data),a=m.apply(a),x=a,v=e(a),p.init()}),p.init=function(){q.delay&&angular.isNumber(q.delay)&&(q.delay={show:q.delay,hide:q.delay});for(var a=q.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.on("click",this.toggle):"manual"!==d&&(b.on("hover"===d?"mouseenter":"focus",this.enter),b.on("hover"===d?"mouseleave":"blur",this.leave))}},p.destroy=function(){for(var a=q.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.off("click",this.toggle):"manual"!==d&&(b.off("hover"===d?"mouseenter":"focus",this.enter),b.off("hover"===d?"mouseleave":"blur",this.leave))}w&&(w.remove(),w=null),r.$destroy()},p.enter=function(){return clearTimeout(s),t="in",q.delay&&q.delay.show?(s=setTimeout(function(){"in"===t&&p.show()},q.delay.show),void 0):p.show()},p.show=function(){var a=q.container?o(q.container):null,c=q.container?null:b;w=p.$element=v(r,function(){}),w.css({top:"0px",left:"0px",display:"block"}).addClass(q.placement),q.animation&&w.addClass(q.animation),q.type&&w.addClass(q.prefixClass+"-"+q.type),i.enter(w,a,c,function(){}),u=!0,r.$digest(),n(p.$applyPlacement),q.keyboard&&(p.focus(),w.on("keyup",p.$onKeyUp))},p.leave=function(){return clearTimeout(s),t="out",q.delay&&q.delay.hide?(s=setTimeout(function(){"out"===t&&p.hide()},q.delay.hide),void 0):p.hide()},p.hide=function(){i.leave(w,function(){}),r.$digest(),u=!1,q.keyboard&&w.off("keyup",p.$onKeyUp)},p.toggle=function(){u?p.leave():p.enter()},p.focus=function(){w[0].focus()},p.$applyPlacement=function(){if(w){var a=j(),b=w.prop("offsetWidth"),c=w.prop("offsetHeight"),d=l(q.placement,a,b,c);d.top+="px",d.left+="px",w.css(d)}},p.$onKeyUp=function(a){27===a.which&&p.hide()},p}var m=String.prototype.trim,n=c.requestAnimationFrame||c.setTimeout,o=function(a,c){return angular.element((c||b).querySelectorAll(a))};return l}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["placement","container","delay","trigger","animation","type","template"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsTooltip&&a.$watch(c.bsTooltip,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}])}(window,document,window.jQuery); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/angular-strap.min.map b/dist/angular-strap.min.map new file mode 100644 index 000000000..03a36299d --- /dev/null +++ b/dist/angular-strap.min.map @@ -0,0 +1 @@ +{"version":3,"file":"dist/modules/tooltip.min.js","sources":["dist/modules/tooltip.js"],"names":["angular","module","run","$templateCache","template","put","provider","defaults","this","animation","prefixClass","container","placement","trigger","keyboard","type","title","delay","$get","$window","$rootScope","$compile","$q","$http","$animate","$timeout","dimensions","TooltipFactory","element","config","getPosition","options","offset","position","getCalculatedOffset","actualWidth","actualHeight","split","top","height","left","width","$tooltip","extend","$promise","when","get","scope","$new","isString","parseFloat","$hide","$$postDigest","hide","$show","show","$toggle","toggle","timeout","hoverState","isShown","tipLinker","tipElement","tipTemplate","then","isObject","data","trim","apply","init","isNumber","triggers","i","length","on","enter","leave","destroy","off","remove","$destroy","clearTimeout","setTimeout","parent","findElement","after","$element","css","display","addClass","$digest","requestAnimationFrame","$applyPlacement","focus","$onKeyUp","elementPosition","tipWidth","prop","tipHeight","tipPosition","evt","which","String","prototype","query","document","querySelectorAll","directive","$location","$sce","restrict","link","attr","forEach","key","isDefined","$observe","newValue","oldValue","tooltip","bsTooltip","$watch","content","$on"],"mappings":"AAAA,YACAA,SAAQC,OAAO,0BAA2B,qCAAqCC,KAC7E,iBACA,SAAUC,GACR,GAAIC,GAAW,oIACfD,GAAeE,IAAI,WAAYD,MAEhCE,SAAS,WAAY,WACtB,GAAIC,GAAWC,KAAKD,UAChBE,UAAW,iBACXC,YAAa,UACbC,WAAW,EACXC,UAAW,MACXR,SAAU,WACVS,QAAS,cACTC,UAAU,EACVC,KAAM,GACNC,MAAO,GACPC,MAAO,EAEXT,MAAKU,MACH,UACA,aACA,WACA,KACA,iBACA,QACA,WACA,WACA,aACA,SAAUC,EAASC,EAAYC,EAAUC,EAAInB,EAAgBoB,EAAOC,EAAUC,EAAUC,GAMtF,QAASC,GAAeC,EAASC,GA+I/B,QAASC,KACP,MAA0B,SAAtBC,EAAQpB,UACHe,EAAWM,OAAOJ,EAAQ,IAE1BF,EAAWO,SAASL,EAAQ,IAGvC,QAASM,GAAoBtB,EAAWqB,EAAUE,EAAaC,GAC7D,GAAIJ,GACAK,EAAQzB,EAAUyB,MAAM,IAC5B,QAAQA,EAAM,IACd,IAAK,QACHL,GACEM,IAAKL,EAASK,IAAML,EAASM,OAAS,EAAIH,EAAe,EACzDI,KAAMP,EAASO,KAAOP,EAASQ,MAEjC,MACF,KAAK,SACHT,GACEM,IAAKL,EAASK,IAAML,EAASM,OAC7BC,KAAMP,EAASO,KAAOP,EAASQ,MAAQ,EAAIN,EAAc,EAE3D,MACF,KAAK,OACHH,GACEM,IAAKL,EAASK,IAAML,EAASM,OAAS,EAAIH,EAAe,EACzDI,KAAMP,EAASO,KAAOL,EAExB,MACF,SACEH,GACEM,IAAKL,EAASK,IAAMF,EACpBI,KAAMP,EAASO,KAAOP,EAASQ,MAAQ,EAAIN,EAAc,GAI7D,IAAKE,EAAM,GACT,MAAOL,EAET,IAAiB,QAAbK,EAAM,IAA6B,WAAbA,EAAM,GAC9B,OAAQA,EAAM,IACd,IAAK,OACHL,EAAOQ,KAAOP,EAASO,IACvB,MACF,KAAK,QACHR,EAAOQ,KAAOP,EAASO,KAAOP,EAASQ,MAAQN,MAE5C,IAAiB,SAAbE,EAAM,IAA8B,UAAbA,EAAM,GACtC,OAAQA,EAAM,IACd,IAAK,MACHL,EAAOM,IAAML,EAASK,IAAMF,CAC5B,MACF,KAAK,SACHJ,EAAOM,IAAML,EAASK,IAAML,EAASM,OAGzC,MAAOP,GAtMT,GAAIU,MACAX,EAAU/B,QAAQ2C,UAAWpC,EAAUsB,EAC3Ca,GAASE,SAAWtB,EAAGuB,KAAK1C,EAAe2C,IAAIf,EAAQ3B,WAAamB,EAAMuB,IAAIf,EAAQ3B,UACtF,IAAI2C,GAAQhB,EAAQgB,MAAMC,QAAU5B,EAAW4B,MAC3CjB,GAAQd,OAASjB,QAAQiD,SAASlB,EAAQd,SAC5Cc,EAAQd,MAAQiC,WAAWnB,EAAQd,QAErC8B,EAAMI,MAAQ,WACZJ,EAAMK,aAAa,WACjBV,EAASW,UAGbN,EAAMO,MAAQ,WACZP,EAAMK,aAAa,WACjBV,EAASa,UAGbR,EAAMS,QAAU,WACdT,EAAMK,aAAa,WACjBV,EAASe,WAGb,IAAIC,GAASC,EAAYC,EACrBC,EAAWC,EAAYC,CAiL3B,OAhLArB,GAASE,SAASoB,KAAK,SAAU5D,GAC3BJ,QAAQiE,SAAS7D,KACnBA,EAAWA,EAAS8D,MACtB9D,EAAW+D,EAAKC,MAAMhE,GACtB2D,EAAc3D,EACdyD,EAAYxC,EAASjB,GACrBsC,EAAS2B,SAEX3B,EAAS2B,KAAO,WACVtC,EAAQd,OAASjB,QAAQsE,SAASvC,EAAQd,SAC5Cc,EAAQd,OACNsC,KAAMxB,EAAQd,MACdoC,KAAMtB,EAAQd,OAIlB,KAAK,GADDsD,GAAWxC,EAAQlB,QAAQwB,MAAM,KAC5BmC,EAAID,EAASE,OAAQD,KAAM,CAClC,GAAI3D,GAAU0D,EAASC,EACP,WAAZ3D,EACFe,EAAQ8C,GAAG,QAASlE,KAAKiD,QACJ,WAAZ5C,IACTe,EAAQ8C,GAAe,UAAZ7D,EAAsB,aAAe,QAASL,KAAKmE,OAC9D/C,EAAQ8C,GAAe,UAAZ7D,EAAsB,aAAe,OAAQL,KAAKoE,UAInElC,EAASmC,QAAU,WAEjB,IAAK,GADDN,GAAWxC,EAAQlB,QAAQwB,MAAM,KAC5BmC,EAAID,EAASE,OAAQD,KAAM,CAClC,GAAI3D,GAAU0D,EAASC,EACP,WAAZ3D,EACFe,EAAQkD,IAAI,QAAStE,KAAKiD,QACL,WAAZ5C,IACTe,EAAQkD,IAAgB,UAAZjE,EAAsB,aAAe,QAASL,KAAKmE,OAC/D/C,EAAQkD,IAAgB,UAAZjE,EAAsB,aAAe,OAAQL,KAAKoE,QAG9Dd,IACFA,EAAWiB,SACXjB,EAAa,MAEff,EAAMiC,YAERtC,EAASiC,MAAQ,WAGf,MAFAM,cAAavB,GACbC,EAAa,KACR5B,EAAQd,OAAUc,EAAQd,MAAMsC,MAGrCG,EAAUwB,WAAW,WACA,OAAfvB,GACFjB,EAASa,QACVxB,EAAQd,MAAMsC,MAHjBG,QAFShB,EAASa,QAOpBb,EAASa,KAAO,WACd,GAAI4B,GAASpD,EAAQpB,UAAYyE,EAAYrD,EAAQpB,WAAa,KAC9D0E,EAAQtD,EAAQpB,UAAY,KAAOiB,CACvCkC,GAAapB,EAAS4C,SAAWzB,EAAUd,EAAO,cAElDe,EAAWyB,KACTjD,IAAK,MACLE,KAAM,MACNgD,QAAS,UACRC,SAAS1D,EAAQnB,WAChBmB,EAAQtB,WACVqD,EAAW2B,SAAS1D,EAAQtB,WAC1BsB,EAAQhB,MACV+C,EAAW2B,SAAS1D,EAAQrB,YAAc,IAAMqB,EAAQhB,MAC1DS,EAASmD,MAAMb,EAAYqB,EAAQE,EAAO,cAE1CzB,GAAU,EACVb,EAAM2C,UACNC,EAAsBjD,EAASkD,iBAC3B7D,EAAQjB,WACV4B,EAASmD,QACT/B,EAAWY,GAAG,QAAShC,EAASoD,YAGpCpD,EAASkC,MAAQ,WAGf,MAFAK,cAAavB,GACbC,EAAa,MACR5B,EAAQd,OAAUc,EAAQd,MAAMoC,MAGrCK,EAAUwB,WAAW,WACA,QAAfvB,GACFjB,EAASW,QAEVtB,EAAQd,MAAMoC,MAJjBK,QAFShB,EAASW,QAQpBX,EAASW,KAAO,WACd7B,EAASoD,MAAMd,EAAY,cAE3Bf,EAAM2C,UACN9B,GAAU,EACN7B,EAAQjB,UACVgD,EAAWgB,IAAI,QAASpC,EAASoD,WAGrCpD,EAASe,OAAS,WAChBG,EAAUlB,EAASkC,QAAUlC,EAASiC,SAExCjC,EAASmD,MAAQ,WACf/B,EAAW,GAAG+B,SAEhBnD,EAASkD,gBAAkB,WACzB,GAAK9B,EAAL,CAEA,GAAIiC,GAAkBjE,IAClBkE,EAAWlC,EAAWmC,KAAK,eAAgBC,EAAYpC,EAAWmC,KAAK,gBACvEE,EAAcjE,EAAoBH,EAAQnB,UAAWmF,EAAiBC,EAAUE,EACpFC,GAAY7D,KAAO,KACnB6D,EAAY3D,MAAQ,KACpBsB,EAAWyB,IAAIY,KAEjBzD,EAASoD,SAAW,SAAUM,GACd,KAAdA,EAAIC,OAAgB3D,EAASW,QA4DxBX,EA9MT,GAAIyB,GAAOmC,OAAOC,UAAUpC,KACxBwB,EAAwBxE,EAAQwE,uBAAyBxE,EAAQ+D,WACjEE,EAAc,SAAUoB,EAAO5E,GACjC,MAAO5B,SAAQ4B,SAASA,GAAW6E,UAAUC,iBAAiBF,IA6MhE,OAAO7E,OAGVgF,UAAU,aACX,UACA,YACA,OACA,WACA,SAAUxF,EAASyF,EAAWC,EAAMnE,GAClC,GAAIiD,GAAwBxE,EAAQwE,uBAAyBxE,EAAQ+D,UACrE,QACE4B,SAAU,MACV/D,OAAO,EACPgE,KAAM,SAAkBhE,EAAOnB,EAASoF,GACtC,GAAIjF,IAAYgB,MAAOA,EACvB/C,SAAQiH,SACN,YACA,YACA,QACA,UACA,YACA,OACA,YACC,SAAUC,GACPlH,QAAQmH,UAAUH,EAAKE,MACzBnF,EAAQmF,GAAOF,EAAKE,MAExBlH,QAAQiH,SAAS,SAAU,SAAUC,GACnCF,EAAKE,IAAQF,EAAKI,SAASF,EAAK,SAAUG,EAAUC,GAClDvE,EAAMmE,GAAOG,EACbrH,QAAQmH,UAAUG,IAAa3B,EAAsB,WACnD4B,GAAWA,EAAQ3B,wBAIzBoB,EAAKQ,WAAazE,EAAM0E,OAAOT,EAAKQ,UAAW,SAAUH,EAAUC,GAC7DtH,QAAQiE,SAASoD,GACnBrH,QAAQ2C,OAAOI,EAAOsE,GAEtBtE,EAAM2E,QAAUL,EAElBrH,QAAQmH,UAAUG,IAAa3B,EAAsB,WACnD4B,GAAWA,EAAQ3B,sBAEpB,EACH,IAAI2B,GAAU7E,EAASd,EAASG,EAChCgB,GAAM4E,IAAI,WAAY,WACpBJ,EAAQ1C,UACR9C,EAAU,KACVwF,EAAU"} \ No newline at end of file diff --git a/dist/modules/affix.js b/dist/modules/affix.js new file mode 100644 index 000000000..40c9da15b --- /dev/null +++ b/dist/modules/affix.js @@ -0,0 +1,143 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.jqlite.dimensions']).provider('$affix', function () { + var defaults = this.defaults = { offsetTop: 'auto' }; + this.$get = [ + '$window', + 'dimensions', + function ($window, dimensions) { + var windowEl = angular.element($window); + var bodyEl = angular.element($window.document.body); + function AffixFactory(element, config) { + var $affix = {}; + var options = angular.extend({}, defaults, config); + var reset = 'affix affix-top affix-bottom', initialAffixTop = 0, initialOffsetTop = 0, affixed = null, unpin = null; + var parent = element.parent(); + if (options.offsetParent) { + if (options.offsetParent.match(/^\d+$/)) { + for (var i = 0; i < options.offsetParent * 1 - 1; i++) { + parent = parent.parent(); + } + } else { + parent = angular.element(options.offsetParent); + } + } + var offsetTop = 0; + if (options.offsetTop) { + if (options.offsetTop === 'auto') { + options.offsetTop = '+0'; + } + if (options.offsetTop.match(/^[-+]\d+$/)) { + initialAffixTop -= options.offsetTop * 1; + if (options.offsetParent) { + offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1; + } else { + offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1; + } + } else { + offsetTop = options.offsetTop * 1; + } + } + var offsetBottom = 0; + if (options.offsetBottom) { + if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) { + offsetBottom = $window.document.body.scrollHeight - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1; + } else { + offsetBottom = options.offsetBottom * 1; + } + } + $affix.init = function () { + initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop; + windowEl.on('scroll', this.checkPosition); + windowEl.on('click', this.checkPositionWithEventLoop); + this.checkPosition(); + this.checkPositionWithEventLoop(); + }; + $affix.destroy = function () { + windowEl.off('scroll', this.checkPosition); + windowEl.off('click', this.checkPositionWithEventLoop); + }; + $affix.checkPositionWithEventLoop = function () { + setTimeout(this.checkPosition, 1); + }; + $affix.checkPosition = function () { + var scrollTop = $window.pageYOffset; + var position = dimensions.offset(element[0]); + var elementHeight = dimensions.height(element[0]); + var affix = getRequiredAffixClass(unpin, position, elementHeight); + if (affixed === affix) + return; + affixed = affix; + element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : '')); + if (affix === 'top') { + unpin = null; + element.css('position', options.offsetParent ? '' : 'relative'); + element.css('top', ''); + } else if (affix === 'bottom') { + if (options.offsetUnpin) { + unpin = -(options.offsetUnpin * 1); + } else { + unpin = position.top - scrollTop; + } + element.css('position', options.offsetParent ? '' : 'relative'); + element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px'); + } else { + unpin = null; + element.css('position', 'fixed'); + element.css('top', initialAffixTop + 'px'); + } + }; + function getRequiredAffixClass(unpin, position, elementHeight) { + var scrollTop = $window.pageYOffset; + var scrollHeight = $window.document.body.scrollHeight; + if (scrollTop <= offsetTop) { + return 'top'; + } else if (unpin !== null && scrollTop + unpin <= position.top) { + return 'middle'; + } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) { + return 'bottom'; + } else { + return 'middle'; + } + } + $affix.init(); + return $affix; + } + return AffixFactory; + } + ]; +}).directive('bsAffix', [ + '$affix', + 'dimensions', + function ($affix, dimensions) { + return { + restrict: 'EAC', + link: function postLink(scope, element, attr) { + var options = { + scope: scope, + offsetTop: 'auto' + }; + angular.forEach([ + 'offsetTop', + 'offsetBottom', + 'offsetParent', + 'offsetUnpin' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + var affix = $affix(element, options); + scope.$on('$destroy', function () { + options = null; + affix = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/affix.min.js b/dist/modules/affix.min.js new file mode 100644 index 000000000..1ec7b6b91 --- /dev/null +++ b/dist/modules/affix.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.jqlite.dimensions"]).provider("$affix",function(){var a=this.defaults={offsetTop:"auto"};this.$get=["$window","dimensions",function(b,c){function d(d,g){function h(a,c,d){var e=b.pageYOffset,f=b.document.body.scrollHeight;return r>=e?"top":null!==a&&e+a<=c.top?"middle":null!==s&&c.top+d+l>=f-s?"bottom":"middle"}var i={},j=angular.extend({},a,g),k="affix affix-top affix-bottom",l=0,m=0,n=null,o=null,p=d.parent();if(j.offsetParent)if(j.offsetParent.match(/^\d+$/))for(var q=0;q<1*j.offsetParent-1;q++)p=p.parent();else p=angular.element(j.offsetParent);var r=0;j.offsetTop&&("auto"===j.offsetTop&&(j.offsetTop="+0"),j.offsetTop.match(/^[-+]\d+$/)?(l-=1*j.offsetTop,r=j.offsetParent?c.offset(p[0]).top+1*j.offsetTop:c.offset(d[0]).top-c.css(d[0],"marginTop",!0)+1*j.offsetTop):r=1*j.offsetTop);var s=0;return j.offsetBottom&&(s=j.offsetParent&&j.offsetBottom.match(/^[-+]\d+$/)?b.document.body.scrollHeight-(c.offset(p[0]).top+c.height(p[0]))+1*j.offsetBottom+1:1*j.offsetBottom),i.init=function(){m=c.offset(d[0]).top+l,e.on("scroll",this.checkPosition),e.on("click",this.checkPositionWithEventLoop),this.checkPosition(),this.checkPositionWithEventLoop()},i.destroy=function(){e.off("scroll",this.checkPosition),e.off("click",this.checkPositionWithEventLoop)},i.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},i.checkPosition=function(){var a=b.pageYOffset,e=c.offset(d[0]),g=c.height(d[0]),i=h(o,e,g);n!==i&&(n=i,d.removeClass(k).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(o=null,d.css("position",j.offsetParent?"":"relative"),d.css("top","")):"bottom"===i?(o=j.offsetUnpin?-(1*j.offsetUnpin):e.top-a,d.css("position",j.offsetParent?"":"relative"),d.css("top",j.offsetParent?"":f[0].offsetHeight-s-g-m+"px")):(o=null,d.css("position","fixed"),d.css("top",l+"px")))},i.init(),i}var e=angular.element(b),f=angular.element(b.document.body);return d}]}).directive("bsAffix",["$affix","dimensions",function(a){return{restrict:"EAC",link:function(b,c,d){var e={scope:b,offsetTop:"auto"};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(a){angular.isDefined(d[a])&&(e[a]=d[a])});var f=a(c,e);b.$on("$destroy",function(){e=null,f=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/alert.js b/dist/modules/alert.js new file mode 100644 index 000000000..eaca81e91 --- /dev/null +++ b/dist/modules/alert.js @@ -0,0 +1,109 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.alert', []).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '' + ' ' + '
'; + $templateCache.put('$alert', template); + } +]).provider('$alert', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'alert', + placement: null, + template: '$alert', + container: false, + element: null, + backdrop: false, + keyboard: true, + show: true, + duration: false + }; + this.$get = [ + '$modal', + '$timeout', + function ($modal, $timeout) { + function AlertFactory(config) { + var $alert = {}; + var options = angular.extend({}, defaults, config); + $alert = $modal(options); + if (!options.scope) { + angular.forEach(['type'], function (key) { + if (options[key]) + $alert.scope[key] = options[key]; + }); + } + var show = $alert.show; + if (options.duration) { + $alert.show = function () { + show(); + $timeout(function () { + $alert.hide(); + }, options.duration * 1000); + }; + } + return $alert; + } + return AlertFactory; + } + ]; +}).directive('bsAlert', [ + '$window', + '$location', + '$sce', + '$alert', + function ($window, $location, $sce, $alert) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + angular.forEach([ + 'template', + 'placement', + 'keyboard', + 'container', + 'animation', + 'duration' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content', + 'type' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsAlert && scope.$watch(attr.bsAlert, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var alert = $alert(options); + element.on(attr.trigger || 'click', alert.toggle); + scope.$on('$destroy', function () { + alert.destroy(); + options = null; + alert = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/alert.min.js b/dist/modules/alert.min.js new file mode 100644 index 000000000..772abdefc --- /dev/null +++ b/dist/modules/alert.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.alert",[]).run(["$templateCache",function(a){var b='
 
';a.put("$alert",b)}]).provider("$alert",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"alert",placement:null,template:"$alert",container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1};this.$get=["$modal","$timeout",function(b,c){function d(d){var e={},f=angular.extend({},a,d);e=b(f),f.scope||angular.forEach(["type"],function(a){f[a]&&(e.scope[a]=f[a])});var g=e.show;return f.duration&&(e.show=function(){g(),c(function(){e.hide()},1e3*f.duration)}),e}return d}]}).directive("bsAlert",["$window","$location","$sce","$alert",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","placement","keyboard","container","animation","duration"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content","type"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAlert&&a.$watch(c.bsAlert,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/aside.js b/dist/modules/aside.js new file mode 100644 index 000000000..cb80d1f74 --- /dev/null +++ b/dist/modules/aside.js @@ -0,0 +1,92 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$aside', template); + } +]).provider('$aside', function () { + var defaults = this.defaults = { + animation: 'animation-fadeAndSlideRight', + prefixClass: 'aside', + placement: 'right', + template: '$aside', + container: false, + element: null, + backdrop: true, + keyboard: true, + show: true + }; + this.$get = [ + '$modal', + function ($modal) { + function AsideFactory(config) { + var $aside = {}; + var options = angular.extend({}, defaults, config); + $aside = $modal(options); + return $aside; + } + return AsideFactory; + } + ]; +}).directive('bsAside', [ + '$window', + '$location', + '$sce', + '$aside', + function ($window, $location, $sce, $aside) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + angular.forEach([ + 'template', + 'placement', + 'backdrop', + 'keyboard', + 'show', + 'container', + 'animation' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsAside && scope.$watch(attr.bsAside, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var aside = $aside(options); + element.on(attr.trigger || 'click', aside.toggle); + scope.$on('$destroy', function () { + aside.destroy(); + options = null; + aside = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/aside.min.js b/dist/modules/aside.min.js new file mode 100644 index 000000000..3465d16af --- /dev/null +++ b/dist/modules/aside.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.aside",["mgcrea.ngStrap.modal"]).run(["$templateCache",function(a){var b='';a.put("$aside",b)}]).provider("$aside",function(){var a=this.defaults={animation:"animation-fadeAndSlideRight",prefixClass:"aside",placement:"right",template:"$aside",container:!1,element:null,backdrop:!0,keyboard:!0,show:!0};this.$get=["$modal",function(b){function c(c){var d={},e=angular.extend({},a,c);return d=b(e)}return c}]}).directive("bsAside",["$window","$location","$sce","$aside",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","placement","backdrop","keyboard","show","container","animation"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAside&&a.$watch(c.bsAside,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/button.js b/dist/modules/button.js new file mode 100644 index 000000000..006af9453 --- /dev/null +++ b/dist/modules/button.js @@ -0,0 +1,124 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.button', []).provider('$button', function () { + var defaults = this.defaults = { + activeClass: 'active', + toggleEvent: 'click' + }; + this.$get = function () { + return { defaults: defaults }; + }; +}).directive('bsCheckboxGroup', function () { + return { + restrict: 'A', + require: 'ngModel', + compile: function postLink(element, attr) { + element.attr('data-toggle', 'buttons'); + element.removeAttr('ng-model'); + var children = element[0].querySelectorAll('input[type="checkbox"]'); + angular.forEach(children, function (child) { + var childEl = angular.element(child); + childEl.attr('bs-checkbox', ''); + childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value')); + }); + } + }; +}).directive('bsCheckbox', [ + '$button', + function ($button) { + var defaults = $button.defaults; + var constantValueRegExp = /^(true|false|\d+)$/; + return { + restrict: 'A', + require: 'ngModel', + link: function postLink(scope, element, attr, controller) { + var options = defaults; + var isInput = element[0].nodeName === 'INPUT'; + var activeElement = isInput ? element.parent() : element; + var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true; + if (constantValueRegExp.test(attr.trueValue)) { + trueValue = scope.$eval(attr.trueValue); + } + var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false; + if (constantValueRegExp.test(attr.falseValue)) { + falseValue = scope.$eval(attr.falseValue); + } + var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean'; + if (hasExoticValues) { + controller.$parsers.push(function (viewValue) { + return viewValue ? trueValue : falseValue; + }); + scope.$watch(attr.ngModel, function (newValue, oldValue) { + controller.$render(); + }); + } + controller.$render = function () { + var isActive = angular.equals(controller.$modelValue, trueValue); + if (isInput) { + element[0].checked = isActive; + } + activeElement.toggleClass(options.activeClass, isActive); + }; + element.bind(options.toggleEvent, function () { + scope.$apply(function () { + if (!isInput) { + controller.$setViewValue(!activeElement.hasClass('active')); + } + if (!hasExoticValues) { + controller.$render(); + } + }); + }); + } + }; + } +]).directive('bsRadioGroup', function () { + return { + restrict: 'A', + require: 'ngModel', + compile: function postLink(element, attr) { + element.attr('data-toggle', 'buttons'); + element.removeAttr('ng-model'); + var children = element[0].querySelectorAll('input[type="radio"]'); + angular.forEach(children, function (child) { + angular.element(child).attr('bs-radio', ''); + angular.element(child).attr('ng-model', attr.ngModel); + }); + } + }; +}).directive('bsRadio', [ + '$button', + function ($button) { + var defaults = $button.defaults; + var constantValueRegExp = /^(true|false|\d+)$/; + return { + restrict: 'A', + require: 'ngModel', + link: function postLink(scope, element, attr, controller) { + var options = defaults; + var isInput = element[0].nodeName === 'INPUT'; + var activeElement = isInput ? element.parent() : element; + var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value; + controller.$render = function () { + var isActive = angular.equals(controller.$modelValue, value); + if (isInput) { + element[0].checked = isActive; + } + activeElement.toggleClass(options.activeClass, isActive); + }; + element.bind(options.toggleEvent, function () { + scope.$apply(function () { + controller.$setViewValue(value); + controller.$render(); + }); + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/button.min.js b/dist/modules/button.min.js new file mode 100644 index 000000000..ba5a59fbf --- /dev/null +++ b/dist/modules/button.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.button",[]).provider("$button",function(){var a=this.defaults={activeClass:"active",toggleEvent:"click"};this.$get=function(){return{defaults:a}}}).directive("bsCheckboxGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="checkbox"]');angular.forEach(c,function(a){var c=angular.element(a);c.attr("bs-checkbox",""),c.attr("ng-model",b.ngModel+"."+c.attr("value"))})}}}).directive("bsCheckbox",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=angular.isDefined(e.trueValue)?e.trueValue:!0;c.test(e.trueValue)&&(j=a.$eval(e.trueValue));var k=angular.isDefined(e.falseValue)?e.falseValue:!1;c.test(e.falseValue)&&(k=a.$eval(e.falseValue));var l="boolean"!=typeof j||"boolean"!=typeof k;l&&(f.$parsers.push(function(a){return a?j:k}),a.$watch(e.ngModel,function(){f.$render()})),f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){h||f.$setViewValue(!i.hasClass("active")),l||f.$render()})})}}}]).directive("bsRadioGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="radio"]');angular.forEach(c,function(a){angular.element(a).attr("bs-radio",""),angular.element(a).attr("ng-model",b.ngModel)})}}}).directive("bsRadio",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=c.test(e.value)?a.$eval(e.value):e.value;f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){f.$setViewValue(j),f.$render()})})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/debounce.js b/dist/modules/debounce.js new file mode 100644 index 000000000..9b40bd275 --- /dev/null +++ b/dist/modules/debounce.js @@ -0,0 +1,60 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.jqlite.debounce', []).constant('debounce', function (func, wait, immediate) { + var timeout, args, context, timestamp, result; + return function () { + context = this; + args = arguments; + timestamp = new Date(); + var later = function () { + var last = new Date() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) + result = func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) + result = func.apply(context, args); + return result; + }; +}).constant('throttle', function (func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function () { + previous = options.leading === false ? 0 : new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function () { + var now = new Date(); + if (!previous && options.leading === false) + previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; +}); \ No newline at end of file diff --git a/dist/modules/debounce.min.js b/dist/modules/debounce.min.js new file mode 100644 index 000000000..d22a8a460 --- /dev/null +++ b/dist/modules/debounce.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.jqlite.debounce",[]).constant("debounce",function(a,b,c){var d,e,f,g,h;return function(){f=this,e=arguments,g=new Date;var i=function(){var j=new Date-g;b>j?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e)))},j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e)),h}}).constant("throttle",function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date,g=null,f=a.apply(d,e)};return function(){var j=new Date;h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k?(clearTimeout(g),g=null,h=j,f=a.apply(d,e)):g||c.trailing===!1||(g=setTimeout(i,k)),f}}); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/dimensions.js b/dist/modules/dimensions.js new file mode 100644 index 000000000..115288404 --- /dev/null +++ b/dist/modules/dimensions.js @@ -0,0 +1,91 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.jqlite.dimensions', []).factory('dimensions', [ + '$document', + '$window', + function ($document, $window) { + var jqLite = angular.element; + var fn = {}; + var nodeName = fn.nodeName = function (element, name) { + return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase(); + }; + fn.css = function (element, prop, extra) { + var value; + if (element.currentStyle) { + value = element.currentStyle[prop]; + } else if (window.getComputedStyle) { + value = window.getComputedStyle(element)[prop]; + } else { + value = element.style[prop]; + } + return extra === true ? parseFloat(value) || 0 : value; + }; + fn.offset = function (element) { + var boxRect = element.getBoundingClientRect(); + var docElement = element.ownerDocument; + return { + width: element.offsetWidth, + height: element.offsetHeight, + top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0), + left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0) + }; + }; + fn.position = function (element) { + var offsetParentRect = { + top: 0, + left: 0 + }, offsetParentElement, offset; + if (fn.css(element, 'position') === 'fixed') { + offset = element.getBoundingClientRect(); + } else { + offsetParentElement = offsetParent(element); + offset = fn.offset(element); + offset = fn.offset(element); + if (!nodeName(offsetParentElement, 'html')) { + offsetParentRect = fn.offset(offsetParentElement); + } + offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true); + offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true); + } + return { + width: element.offsetWidth, + height: element.offsetHeight, + top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true), + left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true) + }; + }; + var offsetParent = function offsetParentElement(element) { + var docElement = element.ownerDocument; + var offsetParent = element.offsetParent || docElement; + while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docElement.documentElement; + }; + fn.height = function (element, outer) { + var value = element.offsetHeight; + if (outer) { + value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true); + } else { + value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true); + } + return value; + }; + fn.width = function (element, outer) { + var value = element.offsetWidth; + if (outer) { + value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true); + } else { + value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true); + } + return value; + }; + return fn; + } +]); \ No newline at end of file diff --git a/dist/modules/dimensions.min.js b/dist/modules/dimensions.min.js new file mode 100644 index 000000000..d9c881c47 --- /dev/null +++ b/dist/modules/dimensions.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.jqlite.dimensions",[]).factory("dimensions",["$document","$window",function(){var a=(angular.element,{}),b=a.nodeName=function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()};a.css=function(a,b,c){var d;return d=a.currentStyle?a.currentStyle[b]:window.getComputedStyle?window.getComputedStyle(a)[b]:a.style[b],c===!0?parseFloat(d)||0:d},a.offset=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument;return{width:a.offsetWidth,height:a.offsetHeight,top:b.top+(window.pageYOffset||c.documentElement.scrollTop)-(c.documentElement.clientTop||0),left:b.left+(window.pageXOffset||c.documentElement.scrollLeft)-(c.documentElement.clientLeft||0)}},a.position=function(d){var e,f,g={top:0,left:0};return"fixed"===a.css(d,"position")?f=d.getBoundingClientRect():(e=c(d),f=a.offset(d),f=a.offset(d),b(e,"html")||(g=a.offset(e)),g.top+=a.css(e,"borderTopWidth",!0),g.left+=a.css(e,"borderLeftWidth",!0)),{width:d.offsetWidth,height:d.offsetHeight,top:f.top-g.top-a.css(d,"marginTop",!0),left:f.left-g.left-a.css(d,"marginLeft",!0)}};var c=function(c){for(var d=c.ownerDocument,e=c.offsetParent||d;e&&!b(e,"html")&&"static"===a.css(e,"position");)e=e.offsetParent;return e||d.documentElement};return a.height=function(b,c){var d=b.offsetHeight;return c?d+=a.css(b,"marginTop",!0)+a.css(b,"marginBottom",!0):d-=a.css(b,"paddingTop",!0)+a.css(b,"paddingBottom",!0)+a.css(b,"borderTopWidth",!0)+a.css(b,"borderBottomWidth",!0),d},a.width=function(b,c){var d=b.offsetWidth;return c?d+=a.css(b,"marginLeft",!0)+a.css(b,"marginRight",!0):d-=a.css(b,"paddingLeft",!0)+a.css(b,"paddingRight",!0)+a.css(b,"borderLeftWidth",!0)+a.css(b,"borderRightWidth",!0),d},a}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/dropdown.js b/dist/modules/dropdown.js new file mode 100644 index 000000000..5e5648553 --- /dev/null +++ b/dist/modules/dropdown.js @@ -0,0 +1,114 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$dropdown', template); + } +]).provider('$dropdown', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + placement: 'bottom-left', + template: '$dropdown', + trigger: 'click', + keyboard: true, + container: false + }; + this.$get = [ + '$window', + '$tooltip', + function ($window, $tooltip) { + var bodyEl = angular.element($window.document.body); + var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector; + function DropdownFactory(element, config) { + var $dropdown = {}; + var options = angular.extend({}, defaults, config); + $dropdown = $tooltip(element, options); + $dropdown.$onKeyDown = function (evt) { + if (!/(38|40)/.test(evt.keyCode)) + return; + evt.preventDefault(); + evt.stopPropagation(); + var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a')); + if (!items.length) + return; + var index; + angular.forEach(items, function (el, i) { + if (matchesSelector && matchesSelector.call(el, ':focus')) + index = i; + }); + if (evt.keyCode === 38 && index > 0) + index--; + else if (evt.keyCode === 40 && index < items.length - 1) + index++; + else if (angular.isUndefined(index)) + index = 0; + items.eq(index)[0].focus(); + }; + var show = $dropdown.show; + $dropdown.show = function () { + show(); + setTimeout(function () { + options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown); + bodyEl.on('click', onBodyClick); + }); + }; + var hide = $dropdown.hide; + $dropdown.hide = function () { + options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown); + bodyEl.off('click', onBodyClick); + hide(); + }; + function onBodyClick(evt) { + if (evt.target === element[0]) + return; + return evt.target !== element[0] && $dropdown.hide(); + } + return $dropdown; + } + return DropdownFactory; + } + ]; +}).directive('bsDropdown', [ + '$window', + '$location', + '$sce', + '$dropdown', + function ($window, $location, $sce, $dropdown) { + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'keyboard', + 'container', + 'delay', + 'trigger', + 'animation', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) { + scope.content = newValue; + }, true); + var dropdown = $dropdown(element, options); + scope.$on('$destroy', function () { + dropdown.destroy(); + options = null; + dropdown = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/dropdown.min.js b/dist/modules/dropdown.min.js new file mode 100644 index 000000000..162b2611e --- /dev/null +++ b/dist/modules/dropdown.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).run(["$templateCache",function(a){var b='';a.put("$dropdown",b)}]).provider("$dropdown",function(){var a=this.defaults={animation:"animation-fade",placement:"bottom-left",template:"$dropdown",trigger:"click",keyboard:!0,container:!1};this.$get=["$window","$tooltip",function(b,c){function d(b,d){function g(a){return a.target!==b[0]?a.target!==b[0]&&h.hide():void 0}var h={},i=angular.extend({},a,d);h=c(b,i),h.$onKeyDown=function(a){if(/(38|40)/.test(a.keyCode)){a.preventDefault(),a.stopPropagation();var b=angular.element(h.$element[0].querySelectorAll("li:not(.divider) a"));if(b.length){var c;angular.forEach(b,function(a,b){f&&f.call(a,":focus")&&(c=b)}),38===a.keyCode&&c>0?c--:40===a.keyCode&&c + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.jqlite.dimensions']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + ''; + $templateCache.put('$modal', template); + } +]).provider('$modal', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'modal', + placement: 'top', + template: '$modal', + container: false, + element: null, + backdrop: true, + keyboard: true, + show: true + }; + this.$get = [ + '$window', + '$rootScope', + '$compile', + '$q', + '$templateCache', + '$http', + '$animate', + '$timeout', + 'dimensions', + function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) { + var forEach = angular.forEach; + var jqLite = angular.element; + var trim = String.prototype.trim; + var bodyElement = jqLite($window.document.body); + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + var findElement = function (query, element) { + return jqLite((element || document).querySelectorAll(query)); + }; + function ModalFactory(config) { + var $modal = {}; + var options = angular.extend({}, defaults, config); + $modal.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template)); + var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new(); + if (!options.element && !options.container) { + options.container = 'body'; + } + if (!options.scope) { + forEach([ + 'title', + 'content' + ], function (key) { + if (options[key]) + scope[key] = options[key]; + }); + } + scope.$hide = function () { + scope.$$postDigest(function () { + $modal.hide(); + }); + }; + scope.$show = function () { + scope.$$postDigest(function () { + $modal.show(); + }); + }; + scope.$toggle = function () { + scope.$$postDigest(function () { + $modal.toggle(); + }); + }; + var modalLinker, modalElement; + var backdropElement = jqLite('
'); + $modal.$promise.then(function (template) { + if (angular.isObject(template)) + template = template.data; + template = trim.apply(template); + modalLinker = $compile(template); + $modal.init(); + }); + $modal.init = function () { + if (options.show) { + scope.$$postDigest(function () { + $modal.show(); + }); + } + }; + $modal.destroy = function () { + modalElement.remove(); + backdropElement.remove(); + scope.$destroy(); + }; + $modal.show = function () { + var parent = options.container ? findElement(options.container) : null; + var after = options.container ? null : options.element; + modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) { + }); + modalElement.css({ display: 'block' }).addClass(options.placement); + if (options.animation) { + if (options.backdrop) { + backdropElement.addClass('animation-fade'); + } + modalElement.addClass(options.animation); + } + if (options.backdrop) { + $animate.enter(backdropElement, bodyElement, null, function () { + }); + } + $animate.enter(modalElement, parent, after, function () { + }); + scope.$isShown = true; + scope.$digest(); + $modal.focus(); + bodyElement.addClass(options.prefixClass + '-open'); + if (options.backdrop) { + modalElement.on('click', hideOnBackdropClick); + } + if (options.keyboard) { + modalElement.on('keyup', $modal.$onKeyUp); + } + }; + $modal.hide = function () { + $animate.leave(modalElement, function () { + bodyElement.removeClass('modal-open'); + }); + if (options.backdrop) { + $animate.leave(backdropElement, function () { + }); + } + scope.$digest(); + scope.$isShown = false; + if (options.backdrop) { + modalElement.off('click', hideOnBackdropClick); + } + if (options.keyboard) { + modalElement.off('keyup', $modal.$onKeyUp); + } + }; + $modal.toggle = function () { + scope.$isShown ? $modal.hide() : $modal.show(); + }; + $modal.focus = function () { + modalElement[0].focus(); + }; + $modal.$onKeyUp = function (evt) { + evt.which === 27 && $modal.hide(); + }; + function hideOnBackdropClick(evt) { + if (evt.target !== evt.currentTarget) + return; + options.backdrop === 'static' ? $modal.focus() : $modal.hide(); + } + return $modal; + } + return ModalFactory; + } + ]; +}).directive('bsModal', [ + '$window', + '$location', + '$sce', + '$modal', + function ($window, $location, $sce, $modal) { + var forEach = angular.forEach; + var isDefined = angular.isDefined; + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { + scope: scope, + element: element, + show: false + }; + forEach([ + 'template', + 'placement', + 'backdrop', + 'keyboard', + 'show', + 'container', + 'animation' + ], function (key) { + if (isDefined(attr[key])) + options[key] = attr[key]; + }); + forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + }); + }); + attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + }, true); + var modal = $modal(options); + element.on(attr.trigger || 'click', modal.toggle); + scope.$on('$destroy', function () { + modal.destroy(); + options = null; + modal = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/modal.min.js b/dist/modules/modal.min.js new file mode 100644 index 000000000..4c72d5500 --- /dev/null +++ b/dist/modules/modal.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.jqlite.dimensions"]).run(["$templateCache",function(a){var b='';a.put("$modal",b)}]).provider("$modal",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"modal",placement:"top",template:"$modal",container:!1,element:null,backdrop:!0,keyboard:!0,show:!0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","dimensions",function(b,c,d,e,f,g,h){function i(b){function i(a){a.target===a.currentTarget&&("static"===p.backdrop?o.focus():o.hide())}var o={},p=angular.extend({},a,b);o.$promise=e.when(f.get(p.template)||g.get(p.template));var q=o.$scope=p.scope&&p.scope.$new()||c.$new();p.element||p.container||(p.container="body"),p.scope||j(["title","content"],function(a){p[a]&&(q[a]=p[a])}),q.$hide=function(){q.$$postDigest(function(){o.hide()})},q.$show=function(){q.$$postDigest(function(){o.show()})},q.$toggle=function(){q.$$postDigest(function(){o.toggle()})};var r,s,t=k('
');return o.$promise.then(function(a){angular.isObject(a)&&(a=a.data),a=l.apply(a),r=d(a),o.init()}),o.init=function(){p.show&&q.$$postDigest(function(){o.show()})},o.destroy=function(){s.remove(),t.remove(),q.$destroy()},o.show=function(){var a=p.container?n(p.container):null,b=p.container?null:p.element;s=o.$element=r(q,function(){}),s.css({display:"block"}).addClass(p.placement),p.animation&&(p.backdrop&&t.addClass("animation-fade"),s.addClass(p.animation)),p.backdrop&&h.enter(t,m,null,function(){}),h.enter(s,a,b,function(){}),q.$isShown=!0,q.$digest(),o.focus(),m.addClass(p.prefixClass+"-open"),p.backdrop&&s.on("click",i),p.keyboard&&s.on("keyup",o.$onKeyUp)},o.hide=function(){h.leave(s,function(){m.removeClass("modal-open")}),p.backdrop&&h.leave(t,function(){}),q.$digest(),q.$isShown=!1,p.backdrop&&s.off("click",i),p.keyboard&&s.off("keyup",o.$onKeyUp)},o.toggle=function(){q.$isShown?o.hide():o.show()},o.focus=function(){s[0].focus()},o.$onKeyUp=function(a){27===a.which&&o.hide()},o}var j=angular.forEach,k=angular.element,l=String.prototype.trim,m=k(b.document.body),n=(b.requestAnimationFrame||b.setTimeout,function(a,b){return k((b||document).querySelectorAll(a))});return i}]}).directive("bsModal",["$window","$location","$sce","$modal",function(a,b,c,d){{var e=angular.forEach,f=angular.isDefined;a.requestAnimationFrame||a.setTimeout}return{restrict:"EAC",scope:!0,link:function(a,b,c){var g={scope:a,element:b,show:!1};e(["template","placement","backdrop","keyboard","show","container","animation"],function(a){f(c[a])&&(g[a]=c[a])}),e(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsModal&&a.$watch(c.bsModal,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var h=d(g);b.on(c.trigger||"click",h.toggle),a.$on("$destroy",function(){h.destroy(),g=null,h=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/module.js b/dist/modules/module.js new file mode 100644 index 000000000..2ab8b27c5 --- /dev/null +++ b/dist/modules/module.js @@ -0,0 +1,19 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +angular.module('mgcrea.ngStrap', [ + 'mgcrea.ngStrap.modal', + 'mgcrea.ngStrap.aside', + 'mgcrea.ngStrap.alert', + 'mgcrea.ngStrap.button', + 'mgcrea.ngStrap.tooltip', + 'mgcrea.ngStrap.popover', + 'mgcrea.ngStrap.dropdown', + 'mgcrea.ngStrap.scrollspy', + 'mgcrea.ngStrap.affix', + 'mgcrea.ngStrap.tab' +]); \ No newline at end of file diff --git a/dist/modules/module.min.js b/dist/modules/module.min.js new file mode 100644 index 000000000..6cbb782c9 --- /dev/null +++ b/dist/modules/module.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +angular.module("mgcrea.ngStrap",["mgcrea.ngStrap.modal","mgcrea.ngStrap.aside","mgcrea.ngStrap.alert","mgcrea.ngStrap.button","mgcrea.ngStrap.tooltip","mgcrea.ngStrap.popover","mgcrea.ngStrap.dropdown","mgcrea.ngStrap.scrollspy","mgcrea.ngStrap.affix","mgcrea.ngStrap.tab"]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/popover.js b/dist/modules/popover.js new file mode 100644 index 000000000..5708d91f9 --- /dev/null +++ b/dist/modules/popover.js @@ -0,0 +1,91 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '
' + '

' + '
' + '
'; + $templateCache.put('$popover', template); + } +]).provider('$popover', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + placement: 'right', + template: '$popover', + trigger: 'click', + keyboard: true, + title: '', + content: '', + delay: 0, + container: false + }; + this.$get = [ + '$tooltip', + function ($tooltip) { + function PopoverFactory(element, config) { + var options = angular.extend({}, defaults, config); + return $tooltip(element, options); + } + return PopoverFactory; + } + ]; +}).directive('bsPopover', [ + '$window', + '$location', + '$sce', + '$popover', + function ($window, $location, $sce, $popover) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'keyboard', + 'container', + 'delay', + 'trigger', + 'animation', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach([ + 'title', + 'content' + ], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + angular.isDefined(oldValue) && requestAnimationFrame(function () { + popover && popover.$applyPlacement(); + }); + }); + }); + attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + angular.isDefined(oldValue) && requestAnimationFrame(function () { + popover && popover.$applyPlacement(); + }); + }, true); + var popover = $popover(element, options); + scope.$on('$destroy', function () { + popover.destroy(); + options = null; + popover = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/popover.min.js b/dist/modules/popover.min.js new file mode 100644 index 000000000..56b071ed5 --- /dev/null +++ b/dist/modules/popover.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.popover",["mgcrea.ngStrap.tooltip"]).run(["$templateCache",function(a){var b='

';a.put("$popover",b)}]).provider("$popover",function(){var a=this.defaults={animation:"animation-fade",placement:"right",template:"$popover",trigger:"click",keyboard:!0,title:"",content:"",delay:0,container:!1};this.$get=["$tooltip",function(b){function c(c,d){var e=angular.extend({},a,d);return b(c,e)}return c}]}).directive("bsPopover",["$window","$location","$sce","$popover",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["placement","keyboard","container","delay","trigger","animation","template"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsPopover&&a.$watch(c.bsPopover,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/scrollspy.js b/dist/modules/scrollspy.js new file mode 100644 index 000000000..1397530e7 --- /dev/null +++ b/dist/modules/scrollspy.js @@ -0,0 +1,205 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.scrollspy', [ + 'mgcrea.ngStrap.jqlite.debounce', + 'mgcrea.ngStrap.jqlite.dimensions' +]).provider('$scrollspy', function () { + var spies = this.$$spies = {}; + var defaults = this.defaults = { + debounce: 150, + throttle: 100, + offset: 100 + }; + this.$get = [ + '$window', + '$document', + '$rootScope', + 'dimensions', + 'debounce', + 'throttle', + function ($window, $document, $rootScope, dimensions, debounce, throttle) { + var windowEl = angular.element($window); + var docEl = angular.element($document.prop('documentElement')); + var bodyEl = angular.element($window.document.body); + function nodeName(element, name) { + return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase(); + } + function ScrollSpyFactory(config) { + var options = angular.extend({}, defaults, config); + if (!options.element) + options.element = bodyEl; + var isWindowSpy = nodeName(options.element, 'body'); + var scrollEl = isWindowSpy ? windowEl : options.element; + var scrollId = isWindowSpy ? 'window' : options.id; + if (spies[scrollId]) { + spies[scrollId].$$count++; + return spies[scrollId]; + } + var $scrollspy = {}; + var trackedElements = $scrollspy.$trackedElements = []; + var sortedElements = []; + var activeTarget; + var debouncedCheckPosition; + var throttledCheckPosition; + var debouncedCheckOffsets; + var viewportHeight; + var scrollTop; + $scrollspy.init = function () { + this.$$count = 1; + debouncedCheckPosition = debounce(this.checkPosition, options.debounce); + throttledCheckPosition = throttle(this.checkPosition, options.throttle); + scrollEl.on('click', this.checkPositionWithEventLoop); + windowEl.on('resize', debouncedCheckPosition); + scrollEl.on('scroll', throttledCheckPosition); + debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce); + $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets); + $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets); + debouncedCheckOffsets(); + if (scrollId) { + spies[scrollId] = $scrollspy; + } + }; + $scrollspy.destroy = function () { + this.$$count--; + if (this.$$count > 0) { + return; + } + scrollEl.off('click', this.checkPositionWithEventLoop); + windowEl.off('resize', debouncedCheckPosition); + scrollEl.off('scroll', debouncedCheckPosition); + $rootScope.$off('$viewContentLoaded', debouncedCheckOffsets); + $rootScope.$off('$includeContentLoaded', debouncedCheckOffsets); + }; + $scrollspy.checkPosition = function () { + scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0; + viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight')); + if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) { + return $scrollspy.$activateElement(sortedElements[0]); + } + for (var i = sortedElements.length; i--;) { + if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) + continue; + if (activeTarget === sortedElements[i].target) + continue; + if (scrollTop < sortedElements[i].offsetTop) + continue; + if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) + continue; + return $scrollspy.$activateElement(sortedElements[i]); + } + }; + $scrollspy.checkPositionWithEventLoop = function () { + setTimeout(this.checkPosition, 1); + }; + $scrollspy.$activateElement = function (element) { + if (activeTarget) { + var activeElement = $scrollspy.$getTrackedElement(activeTarget); + if (activeElement) { + activeElement.source.removeClass('active'); + if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) { + activeElement.source.parent().parent().removeClass('active'); + } + } + } + activeTarget = element.target; + element.source.addClass('active'); + if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) { + element.source.parent().parent().addClass('active'); + } + }; + $scrollspy.$getTrackedElement = function (target) { + return trackedElements.filter(function (obj) { + return obj.target === target; + })[0]; + }; + $scrollspy.checkOffsets = function () { + angular.forEach(trackedElements, function (trackedElement) { + var targetElement = document.querySelector(trackedElement.target); + trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null; + if (options.offset && trackedElement.offsetTop !== null) + trackedElement.offsetTop -= options.offset * 1; + }); + sortedElements = trackedElements.filter(function (el) { + return el.offsetTop !== null; + }).sort(function (a, b) { + return a.offsetTop - b.offsetTop; + }); + debouncedCheckPosition(); + }; + $scrollspy.trackElement = function (target, source) { + trackedElements.push({ + target: target, + source: source + }); + }; + $scrollspy.untrackElement = function (target, source) { + var toDelete; + for (var i = trackedElements.length; i--;) { + if (trackedElements[i].target === target && trackedElements[i].source === source) { + toDelete = i; + break; + } + } + trackedElements = trackedElements.splice(toDelete, 1); + }; + $scrollspy.activate = function (i) { + trackedElements[i].addClass('active'); + }; + $scrollspy.init(); + return $scrollspy; + } + return ScrollSpyFactory; + } + ]; +}).directive('bsScrollspy', [ + '$rootScope', + 'debounce', + 'dimensions', + '$scrollspy', + function ($rootScope, debounce, dimensions, $scrollspy) { + return { + restrict: 'EAC', + link: function postLink(scope, element, attr) { + var options = { scope: scope }; + angular.forEach([ + 'offset', + 'target' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + var scrollspy = $scrollspy(options); + scrollspy.trackElement(options.target, element); + scope.$on('$destroy', function () { + scrollspy.untrackElement(options.target, element); + scrollspy.destroy(); + options = null; + scrollspy = null; + }); + } + }; + } +]).directive('bsScrollspyList', [ + '$rootScope', + 'debounce', + 'dimensions', + '$scrollspy', + function ($rootScope, debounce, dimensions, $scrollspy) { + return { + restrict: 'A', + compile: function postLink(element, attr) { + var children = element[0].querySelectorAll('li > a[href]'); + angular.forEach(children, function (child) { + var childEl = angular.element(child); + childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href')); + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/scrollspy.min.js b/dist/modules/scrollspy.min.js new file mode 100644 index 000000000..8be8c1702 --- /dev/null +++ b/dist/modules/scrollspy.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.jqlite.debounce","mgcrea.ngStrap.jqlite.dimensions"]).provider("$scrollspy",function(){var a=this.$$spies={},b=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(c,d,e,f,g,h){function i(a,b){return a[0].nodeName&&a[0].nodeName.toLowerCase()===b.toLowerCase()}function j(d){var j=angular.extend({},b,d);j.element||(j.element=m);var n=i(j.element,"body"),o=n?k:j.element,p=n?"window":j.id;if(a[p])return a[p].$$count++,a[p];var q,r,s,t,u,v,w={},x=w.$trackedElements=[],y=[];return w.init=function(){this.$$count=1,r=g(this.checkPosition,j.debounce),s=h(this.checkPosition,j.throttle),o.on("click",this.checkPositionWithEventLoop),k.on("resize",r),o.on("scroll",s),t=g(this.checkOffsets,j.debounce),e.$on("$viewContentLoaded",t),e.$on("$includeContentLoaded",t),t(),p&&(a[p]=w)},w.destroy=function(){this.$$count--,this.$$count>0||(o.off("click",this.checkPositionWithEventLoop),k.off("resize",r),o.off("scroll",r),e.$off("$viewContentLoaded",t),e.$off("$includeContentLoaded",t))},w.checkPosition=function(){if(v=(n?c.pageYOffset:o.prop("scrollTop"))||0,u=Math.max(c.innerHeight,l.prop("clientHeight")),vy[a+1].offsetTop))return w.$activateElement(y[a])},w.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},w.$activateElement=function(a){if(q){var b=w.$getTrackedElement(q);b&&(b.source.removeClass("active"),i(b.source,"li")&&i(b.source.parent().parent(),"li")&&b.source.parent().parent().removeClass("active"))}q=a.target,a.source.addClass("active"),i(a.source,"li")&&i(a.source.parent().parent(),"li")&&a.source.parent().parent().addClass("active")},w.$getTrackedElement=function(a){return x.filter(function(b){return b.target===a})[0]},w.checkOffsets=function(){angular.forEach(x,function(a){var b=document.querySelector(a.target);a.offsetTop=b?f.offset(b).top:null,j.offset&&null!==a.offsetTop&&(a.offsetTop-=1*j.offset)}),y=x.filter(function(a){return null!==a.offsetTop}).sort(function(a,b){return a.offsetTop-b.offsetTop}),r()},w.trackElement=function(a,b){x.push({target:a,source:b})},w.untrackElement=function(a,b){for(var c,d=x.length;d--;)if(x[d].target===a&&x[d].source===b){c=d;break}x=x.splice(c,1)},w.activate=function(a){x[a].addClass("active")},w.init(),w}var k=angular.element(c),l=angular.element(d.prop("documentElement")),m=angular.element(c.document.body);return j}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(a,b,c,d){return{restrict:"EAC",link:function(a,b,c){var e={scope:a};angular.forEach(["offset","target"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])});var f=d(e);f.trackElement(e.target,b),a.$on("$destroy",function(){f.untrackElement(e.target,b),f.destroy(),e=null,f=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(a){var b=a[0].querySelectorAll("li > a[href]");angular.forEach(b,function(a){var b=angular.element(a);b.parent().attr("bs-scrollspy","").attr("data-target",b.attr("href"))})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/tab.js b/dist/modules/tab.js new file mode 100644 index 000000000..104baee13 --- /dev/null +++ b/dist/modules/tab.js @@ -0,0 +1,65 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.tab', []).run([ + '$templateCache', + function ($templateCache) { + $templateCache.put('$pane', '{{pane.content}}'); + var template = '' + '
' + '
' + '
'; + $templateCache.put('$tabs', template); + } +]).provider('$tab', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + template: '$tabs' + }; + this.$get = function () { + return { defaults: defaults }; + }; +}).directive('bsTabs', [ + '$window', + '$animate', + '$tab', + function ($window, $animate, $tab) { + var defaults = $tab.defaults; + return { + restrict: 'EAC', + scope: true, + require: '?ngModel', + templateUrl: function (element, attr) { + return attr.template || defaults.template; + }, + link: function postLink(scope, element, attr, controller) { + var options = defaults; + angular.forEach(['animation'], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + attr.bsTabs && scope.$watch(attr.bsTabs, function (newValue, oldValue) { + scope.panes = newValue; + }, true); + element.addClass('tabs'); + if (options.animation) { + element.addClass(options.animation); + } + scope.active = scope.activePane = 0; + scope.setActive = function (index, ev) { + scope.active = index; + if (controller) { + controller.$setViewValue(index); + } + }; + if (controller) { + controller.$render = function () { + scope.active = controller.$modelValue * 1; + }; + } + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/tab.min.js b/dist/modules/tab.min.js new file mode 100644 index 000000000..8475fcc3b --- /dev/null +++ b/dist/modules/tab.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.tab",[]).run(["$templateCache",function(a){a.put("$pane","{{pane.content}}");var b='
';a.put("$tabs",b)}]).provider("$tab",function(){var a=this.defaults={animation:"animation-fade",template:"$tabs"};this.$get=function(){return{defaults:a}}}).directive("bsTabs",["$window","$animate","$tab",function(a,b,c){var d=c.defaults;return{restrict:"EAC",scope:!0,require:"?ngModel",templateUrl:function(a,b){return b.template||d.template},link:function(a,b,c,e){var f=d;angular.forEach(["animation"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),c.bsTabs&&a.$watch(c.bsTabs,function(b){a.panes=b},!0),b.addClass("tabs"),f.animation&&b.addClass(f.animation),a.active=a.activePane=0,a.setActive=function(b){a.active=b,e&&e.$setViewValue(b)},e&&(e.$render=function(){a.active=1*e.$modelValue})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file diff --git a/dist/modules/tooltip.js b/dist/modules/tooltip.js new file mode 100644 index 000000000..cf7fb1532 --- /dev/null +++ b/dist/modules/tooltip.js @@ -0,0 +1,301 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +'use strict'; +angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.jqlite.dimensions']).run([ + '$templateCache', + function ($templateCache) { + var template = '' + '
' + '
' + '
' + '
'; + $templateCache.put('$tooltip', template); + } +]).provider('$tooltip', function () { + var defaults = this.defaults = { + animation: 'animation-fade', + prefixClass: 'tooltip', + container: false, + placement: 'top', + template: '$tooltip', + trigger: 'hover focus', + keyboard: false, + type: '', + title: '', + delay: 0 + }; + this.$get = [ + '$window', + '$rootScope', + '$compile', + '$q', + '$templateCache', + '$http', + '$animate', + '$timeout', + 'dimensions', + function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) { + var trim = String.prototype.trim; + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + var findElement = function (query, element) { + return angular.element((element || document).querySelectorAll(query)); + }; + function TooltipFactory(element, config) { + var $tooltip = {}; + var options = angular.extend({}, defaults, config); + $tooltip.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template)); + var scope = options.scope.$new() || $rootScope.$new(); + if (options.delay && angular.isString(options.delay)) { + options.delay = parseFloat(options.delay); + } + scope.$hide = function () { + scope.$$postDigest(function () { + $tooltip.hide(); + }); + }; + scope.$show = function () { + scope.$$postDigest(function () { + $tooltip.show(); + }); + }; + scope.$toggle = function () { + scope.$$postDigest(function () { + $tooltip.toggle(); + }); + }; + var timeout, hoverState, isShown; + var tipLinker, tipElement, tipTemplate; + $tooltip.$promise.then(function (template) { + if (angular.isObject(template)) + template = template.data; + template = trim.apply(template); + tipTemplate = template; + tipLinker = $compile(template); + $tooltip.init(); + }); + $tooltip.init = function () { + if (options.delay && angular.isNumber(options.delay)) { + options.delay = { + show: options.delay, + hide: options.delay + }; + } + var triggers = options.trigger.split(' '); + for (var i = triggers.length; i--;) { + var trigger = triggers[i]; + if (trigger === 'click') { + element.on('click', this.toggle); + } else if (trigger !== 'manual') { + element.on(trigger === 'hover' ? 'mouseenter' : 'focus', this.enter); + element.on(trigger === 'hover' ? 'mouseleave' : 'blur', this.leave); + } + } + }; + $tooltip.destroy = function () { + var triggers = options.trigger.split(' '); + for (var i = triggers.length; i--;) { + var trigger = triggers[i]; + if (trigger === 'click') { + element.off('click', this.toggle); + } else if (trigger !== 'manual') { + element.off(trigger === 'hover' ? 'mouseenter' : 'focus', this.enter); + element.off(trigger === 'hover' ? 'mouseleave' : 'blur', this.leave); + } + } + if (tipElement) { + tipElement.remove(); + tipElement = null; + } + scope.$destroy(); + }; + $tooltip.enter = function () { + clearTimeout(timeout); + hoverState = 'in'; + if (!options.delay || !options.delay.show) { + return $tooltip.show(); + } + timeout = setTimeout(function () { + if (hoverState === 'in') + $tooltip.show(); + }, options.delay.show); + }; + $tooltip.show = function () { + var parent = options.container ? findElement(options.container) : null; + var after = options.container ? null : element; + tipElement = $tooltip.$element = tipLinker(scope, function (clonedElement, scope) { + }); + tipElement.css({ + top: '0px', + left: '0px', + display: 'block' + }).addClass(options.placement); + if (options.animation) + tipElement.addClass(options.animation); + if (options.type) + tipElement.addClass(options.prefixClass + '-' + options.type); + $animate.enter(tipElement, parent, after, function () { + }); + isShown = true; + scope.$digest(); + requestAnimationFrame($tooltip.$applyPlacement); + if (options.keyboard) { + $tooltip.focus(); + tipElement.on('keyup', $tooltip.$onKeyUp); + } + }; + $tooltip.leave = function () { + clearTimeout(timeout); + hoverState = 'out'; + if (!options.delay || !options.delay.hide) { + return $tooltip.hide(); + } + timeout = setTimeout(function () { + if (hoverState === 'out') { + $tooltip.hide(); + } + }, options.delay.hide); + }; + $tooltip.hide = function () { + $animate.leave(tipElement, function () { + }); + scope.$digest(); + isShown = false; + if (options.keyboard) { + tipElement.off('keyup', $tooltip.$onKeyUp); + } + }; + $tooltip.toggle = function () { + isShown ? $tooltip.leave() : $tooltip.enter(); + }; + $tooltip.focus = function () { + tipElement[0].focus(); + }; + $tooltip.$applyPlacement = function () { + if (!tipElement) + return; + var elementPosition = getPosition(); + var tipWidth = tipElement.prop('offsetWidth'), tipHeight = tipElement.prop('offsetHeight'); + var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight); + tipPosition.top += 'px'; + tipPosition.left += 'px'; + tipElement.css(tipPosition); + }; + $tooltip.$onKeyUp = function (evt) { + evt.which === 27 && $tooltip.hide(); + }; + function getPosition() { + if (options.container === 'body') { + return dimensions.offset(element[0]); + } else { + return dimensions.position(element[0]); + } + } + function getCalculatedOffset(placement, position, actualWidth, actualHeight) { + var offset; + var split = placement.split('-'); + switch (split[0]) { + case 'right': + offset = { + top: position.top + position.height / 2 - actualHeight / 2, + left: position.left + position.width + }; + break; + case 'bottom': + offset = { + top: position.top + position.height, + left: position.left + position.width / 2 - actualWidth / 2 + }; + break; + case 'left': + offset = { + top: position.top + position.height / 2 - actualHeight / 2, + left: position.left - actualWidth + }; + break; + default: + offset = { + top: position.top - actualHeight, + left: position.left + position.width / 2 - actualWidth / 2 + }; + break; + } + if (!split[1]) { + return offset; + } + if (split[0] === 'top' || split[0] === 'bottom') { + switch (split[1]) { + case 'left': + offset.left = position.left; + break; + case 'right': + offset.left = position.left + position.width - actualWidth; + } + } else if (split[0] === 'left' || split[0] === 'right') { + switch (split[1]) { + case 'top': + offset.top = position.top - actualHeight; + break; + case 'bottom': + offset.top = position.top + position.height; + } + } + return offset; + } + return $tooltip; + } + return TooltipFactory; + } + ]; +}).directive('bsTooltip', [ + '$window', + '$location', + '$sce', + '$tooltip', + function ($window, $location, $sce, $tooltip) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; + return { + restrict: 'EAC', + scope: true, + link: function postLink(scope, element, attr, transclusion) { + var options = { scope: scope }; + angular.forEach([ + 'placement', + 'container', + 'delay', + 'trigger', + 'animation', + 'type', + 'template' + ], function (key) { + if (angular.isDefined(attr[key])) + options[key] = attr[key]; + }); + angular.forEach(['title'], function (key) { + attr[key] && attr.$observe(key, function (newValue, oldValue) { + scope[key] = newValue; + angular.isDefined(oldValue) && requestAnimationFrame(function () { + tooltip && tooltip.$applyPlacement(); + }); + }); + }); + attr.bsTooltip && scope.$watch(attr.bsTooltip, function (newValue, oldValue) { + if (angular.isObject(newValue)) { + angular.extend(scope, newValue); + } else { + scope.content = newValue; + } + angular.isDefined(oldValue) && requestAnimationFrame(function () { + tooltip && tooltip.$applyPlacement(); + }); + }, true); + var tooltip = $tooltip(element, options); + scope.$on('$destroy', function () { + tooltip.destroy(); + options = null; + tooltip = null; + }); + } + }; + } +]); \ No newline at end of file diff --git a/dist/modules/tooltip.min.js b/dist/modules/tooltip.min.js new file mode 100644 index 000000000..8077b06b4 --- /dev/null +++ b/dist/modules/tooltip.min.js @@ -0,0 +1,9 @@ +/** + * angular-strap + * @version v2.0.0-beta.1 - 2014-01-07 + * @link http://mgcrea.github.io/angular-strap + * @author Olivier Louvignes + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"use strict";angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.jqlite.dimensions"]).run(["$templateCache",function(a){var b='
';a.put("$tooltip",b)}]).provider("$tooltip",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"tooltip",container:!1,placement:"top",template:"$tooltip",trigger:"hover focus",keyboard:!1,type:"",title:"",delay:0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","dimensions",function(b,c,d,e,f,g,h,i,j){function k(b,i){function k(){return"body"===q.container?j.offset(b[0]):j.position(b[0])}function o(a,b,c,d){var e,f=a.split("-");switch(f[0]){case"right":e={top:b.top+b.height/2-d/2,left:b.left+b.width};break;case"bottom":e={top:b.top+b.height,left:b.left+b.width/2-c/2};break;case"left":e={top:b.top+b.height/2-d/2,left:b.left-c};break;default:e={top:b.top-d,left:b.left+b.width/2-c/2}}if(!f[1])return e;if("top"===f[0]||"bottom"===f[0])switch(f[1]){case"left":e.left=b.left;break;case"right":e.left=b.left+b.width-c}else if("left"===f[0]||"right"===f[0])switch(f[1]){case"top":e.top=b.top-d;break;case"bottom":e.top=b.top+b.height}return e}var p={},q=angular.extend({},a,i);p.$promise=e.when(f.get(q.template)||g.get(q.template));var r=q.scope.$new()||c.$new();q.delay&&angular.isString(q.delay)&&(q.delay=parseFloat(q.delay)),r.$hide=function(){r.$$postDigest(function(){p.hide()})},r.$show=function(){r.$$postDigest(function(){p.show()})},r.$toggle=function(){r.$$postDigest(function(){p.toggle()})};var s,t,u,v,w,x;return p.$promise.then(function(a){angular.isObject(a)&&(a=a.data),a=l.apply(a),x=a,v=d(a),p.init()}),p.init=function(){q.delay&&angular.isNumber(q.delay)&&(q.delay={show:q.delay,hide:q.delay});for(var a=q.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.on("click",this.toggle):"manual"!==d&&(b.on("hover"===d?"mouseenter":"focus",this.enter),b.on("hover"===d?"mouseleave":"blur",this.leave))}},p.destroy=function(){for(var a=q.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.off("click",this.toggle):"manual"!==d&&(b.off("hover"===d?"mouseenter":"focus",this.enter),b.off("hover"===d?"mouseleave":"blur",this.leave))}w&&(w.remove(),w=null),r.$destroy()},p.enter=function(){return clearTimeout(s),t="in",q.delay&&q.delay.show?(s=setTimeout(function(){"in"===t&&p.show()},q.delay.show),void 0):p.show()},p.show=function(){var a=q.container?n(q.container):null,c=q.container?null:b;w=p.$element=v(r,function(){}),w.css({top:"0px",left:"0px",display:"block"}).addClass(q.placement),q.animation&&w.addClass(q.animation),q.type&&w.addClass(q.prefixClass+"-"+q.type),h.enter(w,a,c,function(){}),u=!0,r.$digest(),m(p.$applyPlacement),q.keyboard&&(p.focus(),w.on("keyup",p.$onKeyUp))},p.leave=function(){return clearTimeout(s),t="out",q.delay&&q.delay.hide?(s=setTimeout(function(){"out"===t&&p.hide()},q.delay.hide),void 0):p.hide()},p.hide=function(){h.leave(w,function(){}),r.$digest(),u=!1,q.keyboard&&w.off("keyup",p.$onKeyUp)},p.toggle=function(){u?p.leave():p.enter()},p.focus=function(){w[0].focus()},p.$applyPlacement=function(){if(w){var a=k(),b=w.prop("offsetWidth"),c=w.prop("offsetHeight"),d=o(q.placement,a,b,c);d.top+="px",d.left+="px",w.css(d)}},p.$onKeyUp=function(a){27===a.which&&p.hide()},p}var l=String.prototype.trim,m=b.requestAnimationFrame||b.setTimeout,n=function(a,b){return angular.element((b||document).querySelectorAll(a))};return k}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["placement","container","delay","trigger","animation","type","template"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsTooltip&&a.$watch(c.bsTooltip,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}]); +//# sourceMappingURL=angular-strap.min.map \ No newline at end of file