PageSourceSearch

https://s-textile.ru/vendors/ui-bootstrap-custom/ui-bootstrap-custom-1.3.3.js

js s-textile.ru collected 2026-10-08 11:37:32 UTC 56,720 bytes, 1,405 lines download raw bytes

vendor: 30,555 bytes, lines 1-882
1/*
2 * angular-ui-bootstrap
3 * http://angular-ui.github.io/bootstrap/
4
5 * Version: 1.3.3 - 2016-05-22
6 * License: MIT
7 */angular.module("ui.bootstrap", ["ui.bootstrap.popover","ui.bootstrap.tooltip","ui.bootstrap.position","ui.bootstrap.stackedMap"]);
8/**
9 * The following features are still outstanding: popup delay, animation as a
10 * function, placement as a function, inside, support for more triggers than
11 * just mouse enter/leave, and selector delegatation.
12 */
13angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
14
15.directive('uibPopoverTemplatePopup', function() {
16  return {
17    replace: true,
18    scope: { uibTitle: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
19      originScope: '&' },
20    templateUrl: 'uib/template/popover/popover-template.html'
21  };
22})
23
24.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {
25  return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
26    useContentExp: true
27  });
28}])
29
30.directive('uibPopoverHtmlPopup', function() {
31  return {
32    replace: true,
33    scope: { contentExp: '&', uibTitle: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
34    templateUrl: 'uib/template/popover/popover-html.html'
35  };
36})
37
38.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {
39  return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
40    useContentExp: true
41  });
42}])
43
44.directive('uibPopoverPopup', function() {
45  return {
46    replace: true,
47    scope: { uibTitle: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
48    templateUrl: 'uib/template/popover/popover.html'
49  };
50})
51
52.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {
53  return $uibTooltip('uibPopover', 'popover', 'click');
54}]);
55
56/**
57 * The following features are still outstanding: animation as a
58 * function, placement as a function, inside, support for more triggers than
59 * just mouse enter/leave, html tooltips, and selector delegation.
60 */
61angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
62
63/**
64 * The $tooltip service creates tooltip- and popover-like directives as well as
65 * houses global options for them.
66 */
67.provider('$uibTooltip', function() {
68  // The default options tooltip and popover.
69  var defaultOptions = {
70    placement: 'top',
71    placementClassPrefix: '',
72    animation: true,
73    popupDelay: 0,
74    popupCloseDelay: 0,
75    useContentExp: false
76  };
77
78  // Default hide triggers for each show trigger
79  var triggerMap = {
80    'mouseenter': 'mouseleave',
81    'click': 'click',
82    'outsideClick': 'outsideClick',
83    'focus': 'blur',
84    'none': ''
85  };
86
87  // The options specified to the provider globally.
88  var globalOptions = {};
89
90  /**
91   * `options({})` allows global configuration of all tooltips in the
92   * application.
93   *
94   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
95   *     // place tooltips left instead of top by default
96   *     $tooltipProvider.options( { placement: 'left' } );
97   *   });
98   */
99	this.options = function(value) {
100		angular.extend(globalOptions, value);
101	};
102
103  /**
104   * This allows you to extend the set of trigger mappings available. E.g.:
105   *
106   *   $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
107   */
108  this.setTriggers = function setTriggers(triggers) {
109    angular.extend(triggerMap, triggers);
110  };
111
112  /**
113   * This is a helper function for translating camel-case to snake_case.
114   */
115  function snake_case(name) {
116    var regexp = /[A-Z]/g;
117    var separator = '-';
118    return name.replace(regexp, function(letter, pos) {
119      return (pos ? separator : '') + letter.toLowerCase();
120    });
121  }
122
123  /**
124   * Returns the actual instance of the $tooltip service.
125   * TODO support multiple triggers
126   */
127  this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
128    var openedTooltips = $$stackedMap.createNew();
129    $document.on('keypress', keypressListener);
130
131    $rootScope.$on('$destroy', function() {
132      $document.off('keypress', keypressListener);
133    });
134
135    function keypressListener(e) {
136      if (e.which === 27) {
137        var last = openedTooltips.top();
138        if (last) {
139          last.value.close();
140          openedTooltips.removeTop();
141          last = null;
142        }
143      }
144    }
145
146    return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
147      options = angular.extend({}, defaultOptions, globalOptions, options);
148
149      /**
150       * Returns an object of show and hide triggers.
151       *
152       * If a trigger is supplied,
153       * it is used to show the tooltip; otherwise, it will use the `trigger`
154       * option passed to the `$tooltipProvider.options` method; else it will
155       * default to the trigger supplied to this directive factory.
156       *
157       * The hide trigger is based on the show trigger. If the `trigger` option
158       * was passed to the `$tooltipProvider.options` method, it will use the
159       * mapped trigger from `triggerMap` or the passed trigger if the map is
160       * undefined; otherwise, it uses the `triggerMap` value of the show
161       * trigger; else it will just use the show trigger.
162       */
163      function getTriggers(trigger) {
164        var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
165        var hide = show.map(function(trigger) {
166          return triggerMap[trigger] || trigger;
167        });
168        return {
169          show: show,
170          hide: hide
171        };
172      }
173
174      var directiveName = snake_case(ttType);
175
176      var startSym = $interpolate.startSymbol();
177      var endSym = $interpolate.endSymbol();
178      var template =
179        '<div '+ directiveName + '-popup ' +
180          'uib-title="' + startSym + 'title' + endSym + '" ' +
181          (options.useContentExp ?
182            'content-exp="contentExp()" ' :
183            'content="' + startSym + 'content' + endSym + '" ') +
184          'placement="' + startSym + 'placement' + endSym + '" ' +
185          'popup-class="' + startSym + 'popupClass' + endSym + '" ' +
186          'animation="animation" ' +
187          'is-open="isOpen" ' +
188          'origin-scope="origScope" ' +
189          'class="uib-position-measure"' +
190          '>' +
191        '</div>';
192
193      return {
194        compile: function(tElem, tAttrs) {
195          var tooltipLinker = $compile(template);
196
197          return function link(scope, element, attrs, tooltipCtrl) {
198            var tooltip;
199            var tooltipLinkedScope;
200            var transitionTimeout;
201            var showTimeout;
202            var hideTimeout;
203            var positionTimeout;
204            var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
205            var triggers = getTriggers(undefined);
206            var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
207            var ttScope = scope.$new(true);
208            var repositionScheduled = false;
209            var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
210            var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
211            var observers = [];
212            var lastPlacement;
213
214            var positionTooltip = function() {
215              // check if tooltip exists and is not empty
216              if (!tooltip || !tooltip.html()) { return; }
217
218              if (!positionTimeout) {
219                positionTimeout = $timeout(function() {
220                  var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
221                  tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
222
223                  if (!tooltip.hasClass(ttPosition.placement.split('-')[0])) {
224                    tooltip.removeClass(lastPlacement.split('-')[0]);
225                    tooltip.addClass(ttPosition.placement.split('-')[0]);
226                  }
227
228                  if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
229                    tooltip.removeClass(options.placementClassPrefix + lastPlacement);
230                    tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
231                  }
232
233                  // first time through tt element will have the
234                  // uib-position-measure class or if the placement
235                  // has changed we need to position the arrow.
236                  if (tooltip.hasClass('uib-position-measure')) {
237                    $position.positionArrow(tooltip, ttPosition.placement);
238                    tooltip.removeClass('uib-position-measure');
239                  } else if (lastPlacement !== ttPosition.placement) {
240                    $position.positionArrow(tooltip, ttPosition.placement);
241                  }
242                  lastPlacement = ttPosition.placement;
243
244                  positionTimeout = null;
245                }, 0, false);
246              }
247            };
248
249            // Set up the correct scope to allow transclusion later
250            ttScope.origScope = scope;
251
252            // By default, the tooltip is not open.
253            // TODO add ability to start tooltip opened
254            ttScope.isOpen = false;
255            openedTooltips.add(ttScope, {
256              close: hide
257            });
258
259            function toggleTooltipBind() {
260              if (!ttScope.isOpen) {
261                showTooltipBind();
262              } else {
263                hideTooltipBind();
264              }
265            }
266
267            // Show the tooltip with delay if specified, otherwise show it immediately
268            function showTooltipBind() {
269              if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
270                return;
271              }
272
273              cancelHide();
274              prepareTooltip();
275
276              if (ttScope.popupDelay) {
277                // Do nothing if the tooltip was already scheduled to pop-up.
278                // This happens if show is triggered multiple times before any hide is triggered.
279                if (!showTimeout) {
280                  showTimeout = $timeout(show, ttScope.popupDelay, false);
281                }
282              } else {
283                show();
284              }
285            }
286
287            function hideTooltipBind() {
288              cancelShow();
289
290              if (ttScope.popupCloseDelay) {
291                if (!hideTimeout) {
292                  hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
293                }
294              } else {
295                hide();
296              }
297            }
298
299            // Show the tooltip popup element.
300            function show() {
301              cancelShow();
302              cancelHide();
303
304              // Don't show empty tooltips.
305              if (!ttScope.content) {
306                return angular.noop;
307              }
308
309              createTooltip();
310
311              // And show the tooltip.
312              ttScope.$evalAsync(function() {
313                ttScope.isOpen = true;
314                assignIsOpen(true);
315                positionTooltip();
316              });
317            }
318
319            function cancelShow() {
320              if (showTimeout) {
321                $timeout.cancel(showTimeout);
322                showTimeout = null;
323              }
324
325              if (positionTimeout) {
326                $timeout.cancel(positionTimeout);
327                positionTimeout = null;
328              }
329            }
330
331            // Hide the tooltip popup element.
332            function hide() {
333              if (!ttScope) {
334                return;
335              }
336
337              // First things first: we don't show it anymore.
338              ttScope.$evalAsync(function() {
339                if (ttScope) {
340                  ttScope.isOpen = false;
341                  assignIsOpen(false);
342                  // And now we remove it from the DOM. However, if we have animation, we
343                  // need to wait for it to expire beforehand.
344                  // FIXME: this is a placeholder for a port of the transitions library.
345                  // The fade transition in TWBS is 150ms.
346                  if (ttScope.animation) {
347                    if (!transitionTimeout) {
348                      transitionTimeout = $timeout(removeTooltip, 150, false);
349                    }
350                  } else {
351                    removeTooltip();
352                  }
353                }
354              });
355            }
356
357            function cancelHide() {
358              if (hideTimeout) {
359                $timeout.cancel(hideTimeout);
360                hideTimeout = null;
361              }
362
363              if (transitionTimeout) {
364                $timeout.cancel(transitionTimeout);
365                transitionTimeout = null;
366              }
367            }
368
369            function createTooltip() {
370              // There can only be one tooltip element per directive shown at once.
371              if (tooltip) {
372                return;
373              }
374
375              tooltipLinkedScope = ttScope.$new();
376              tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {
377                if (appendToBody) {
378                  $document.find('body').append(tooltip);
379                } else {
380                  element.after(tooltip);
381                }
382              });
383
384              prepObservers();
385            }
386
387            function removeTooltip() {
388              cancelShow();
389              cancelHide();
390              unregisterObservers();
391
392              if (tooltip) {
393                tooltip.remove();
394                tooltip = null;
395              }
396              if (tooltipLinkedScope) {
397                tooltipLinkedScope.$destroy();
398                tooltipLinkedScope = null;
399              }
400            }
401
402            /**
403             * Set the initial scope values. Once
404             * the tooltip is created, the observers
405             * will be added to keep things in sync.
406             */
407            function prepareTooltip() {
408              ttScope.title = attrs[prefix + 'Title'];
409              if (contentParse) {
410                ttScope.content = contentParse(scope);
411              } else {
412                ttScope.content = attrs[ttType];
413              }
414
415              ttScope.popupClass = attrs[prefix + 'Class'];
416              ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
417              var placement = $position.parsePlacement(ttScope.placement);
418              lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];
419
420              var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
421              var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
422              ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
423              ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
424            }
425
426            function assignIsOpen(isOpen) {
427              if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
428                isOpenParse.assign(scope, isOpen);
429              }
430            }
431
432            ttScope.contentExp = function() {
433              return ttScope.content;
434            };
435
436            /**
437             * Observe the relevant attributes.
438             */
439            attrs.$observe('disabled', function(val) {
440              if (val) {
441                cancelShow();
442              }
443
444              if (val && ttScope.isOpen) {
445                hide();
446              }
447            });
448
449            if (isOpenParse) {
450              scope.$watch(isOpenParse, function(val) {
451                if (ttScope && !val === ttScope.isOpen) {
452                  toggleTooltipBind();
453                }
454              });
455            }
456
457            function prepObservers() {
458              observers.length = 0;
459
460              if (contentParse) {
461                observers.push(
462                  scope.$watch(contentParse, function(val) {
463                    ttScope.content = val;
464                    if (!val && ttScope.isOpen) {
465                      hide();
466                    }
467                  })
468                );
469
470                observers.push(
471                  tooltipLinkedScope.$watch(function() {
472                    if (!repositionScheduled) {
473                      repositionScheduled = true;
474                      tooltipLinkedScope.$$postDigest(function() {
475                        repositionScheduled = false;
476                        if (ttScope && ttScope.isOpen) {
477                          positionTooltip();
478                        }
479                      });
480                    }
481                  })
482                );
483              } else {
484                observers.push(
485                  attrs.$observe(ttType, function(val) {
486                    ttScope.content = val;
487                    if (!val && ttScope.isOpen) {
488                      hide();
489                    } else {
490                      positionTooltip();
491                    }
492                  })
493                );
494              }
495
496              observers.push(
497                attrs.$observe(prefix + 'Title', function(val) {
498                  ttScope.title = val;
499                  if (ttScope.isOpen) {
500                    positionTooltip();
501                  }
502                })
503              );
504
505              observers.push(
506                attrs.$observe(prefix + 'Placement', function(val) {
507                  ttScope.placement = val ? val : options.placement;
508                  if (ttScope.isOpen) {
509                    positionTooltip();
510                  }
511                })
512              );
513            }
514
515            function unregisterObservers() {
516              if (observers.length) {
517                angular.forEach(observers, function(observer) {
518                  observer();
519                });
520                observers.length = 0;
521              }
522            }
523
524            // hide tooltips/popovers for outsideClick trigger
525            function bodyHideTooltipBind(e) {
526              if (!ttScope || !ttScope.isOpen || !tooltip) {
527                return;
528              }
529              // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
530              if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
531                hideTooltipBind();
532              }
533            }
534
535            var unregisterTriggers = function() {
536              triggers.show.forEach(function(trigger) {
537                if (trigger === 'outsideClick') {
538                  element.off('click', toggleTooltipBind);
539                } else {
540                  element.off(trigger, showTooltipBind);
541                  element.off(trigger, toggleTooltipBind);
542                }
543              });
544              triggers.hide.forEach(function(trigger) {
545                if (trigger === 'outsideClick') {
546                  $document.off('click', bodyHideTooltipBind);
547                } else {
548                  element.off(trigger, hideTooltipBind);
549                }
550              });
551            };
552
553            function prepTriggers() {
554              var val = attrs[prefix + 'Trigger'];
555              unregisterTriggers();
556
557              triggers = getTriggers(val);
558
559              if (triggers.show !== 'none') {
560                triggers.show.forEach(function(trigger, idx) {
561                  if (trigger === 'outsideClick') {
562                    element.on('click', toggleTooltipBind);
563                    $document.on('click', bodyHideTooltipBind);
564                  } else if (trigger === triggers.hide[idx]) {
565                    element.on(trigger, toggleTooltipBind);
566                  } else if (trigger) {
567                    element.on(trigger, showTooltipBind);
568                    element.on(triggers.hide[idx], hideTooltipBind);
569                  }
570
571                  element.on('keypress', function(e) {
572                    if (e.which === 27) {
573                      hideTooltipBind();
574                    }
575                  });
576                });
577              }
578            }
579
580            prepTriggers();
581
582            var animation = scope.$eval(attrs[prefix + 'Animation']);
583            ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;
584
585            var appendToBodyVal;
586            var appendKey = prefix + 'AppendToBody';
587            if (appendKey in attrs && attrs[appendKey] === undefined) {
588              appendToBodyVal = true;
589            } else {
590              appendToBodyVal = scope.$eval(attrs[appendKey]);
591            }
592
593            appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;
594
595            // Make sure tooltip is destroyed and removed.
596            scope.$on('$destroy', function onDestroyTooltip() {
597              unregisterTriggers();
598              removeTooltip();
599              openedTooltips.remove(ttScope);
600              ttScope = null;
601            });
602          };
603        }
604      };
605    };
606  }];
607})
608
609// This is mostly ngInclude code but with a custom scope
610.directive('uibTooltipTemplateTransclude', [
611         '$animate', '$sce', '$compile', '$templateRequest',
612function ($animate, $sce, $compile, $templateRequest) {
613  return {
614    link: function(scope, elem, attrs) {
615      var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);
616
617      var changeCounter = 0,
618        currentScope,
619        previousElement,
620        currentElement;
621
622      var cleanupLastIncludeContent = function() {
623        if (previousElement) {
624          previousElement.remove();
625          previousElement = null;
626        }
627
628        if (currentScope) {
629          currentScope.$destroy();
630          currentScope = null;
631        }
632
633        if (currentElement) {
634          $animate.leave(currentElement).then(function() {
635            previousElement = null;
636          });
637          previousElement = currentElement;
638          currentElement = null;
639        }
640      };
641
642      scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {
643        var thisChangeId = ++changeCounter;
644
645        if (src) {
646          //set the 2nd param to true to ignore the template request error so that the inner
647          //contents and scope can be cleaned up.
648          $templateRequest(src, true).then(function(response) {
649            if (thisChangeId !== changeCounter) { return; }
650            var newScope = origScope.$new();
651            var template = response;
652
653            var clone = $compile(template)(newScope, function(clone) {
654              cleanupLastIncludeContent();
655              $animate.enter(clone, elem);
656            });
657
658            currentScope = newScope;
659            currentElement = clone;
660
661            currentScope.$emit('$includeContentLoaded', src);
662          }, function() {
663            if (thisChangeId === changeCounter) {
664              cleanupLastIncludeContent();
665              scope.$emit('$includeContentError', src);
666            }
667          });
668          scope.$emit('$includeContentRequested', src);
669        } else {
670          cleanupLastIncludeContent();
671        }
672      });
673
674      scope.$on('$destroy', cleanupLastIncludeContent);
675    }
676  };
677}])
678
679/**
680 * Note that it's intentional that these classes are *not* applied through $animate.
681 * They must not be animated as they're expected to be present on the tooltip on
682 * initialization.
683 */
684.directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {
685  return {
686    restrict: 'A',
687    link: function(scope, element, attrs) {
688      // need to set the primary position so the
689      // arrow has space during position measure.
690      // tooltip.positionTooltip()
691      if (scope.placement) {
692        // // There are no top-left etc... classes
693        // // in TWBS, so we need the primary position.
694        var position = $uibPosition.parsePlacement(scope.placement);
695        element.addClass(position[0]);
696      }
697
698      if (scope.popupClass) {
699        element.addClass(scope.popupClass);
700      }
701
702      if (scope.animation()) {
703        element.addClass(attrs.tooltipAnimationClass);
704      }
705    }
706  };
707}])
708
709.directive('uibTooltipPopup', function() {
710  return {
711    replace: true,
712    scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
713    templateUrl: 'uib/template/tooltip/tooltip-popup.html'
714  };
715})
716
717.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {
718  return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
719}])
720
721.directive('uibTooltipTemplatePopup', function() {
722  return {
723    replace: true,
724    scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
725      originScope: '&' },
726    templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
727  };
728})
729
730.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {
731  return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
732    useContentExp: true
733  });
734}])
735
736.directive('uibTooltipHtmlPopup', function() {
737  return {
738    replace: true,
739    scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
740    templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
741  };
742})
743
744.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {
745  return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
746    useContentExp: true
747  });
748}]);
749
750angular.module('ui.bootstrap.position', [])
751
752/**
753 * A set of utility methods for working with the DOM.
754 * It is meant to be used where we need to absolute-position elements in
755 * relation to another element (this is the case for tooltips, popovers,
756 * typeahead suggestions etc.).
757 */
758  .factory('$uibPosition', ['$document', '$window', function($document, $window) {
759    /**
760     * Used by scrollbarWidth() function to cache scrollbar's width.
761     * Do not access this variable directly, use scrollbarWidth() instead.
762     */
763    var SCROLLBAR_WIDTH;
764    /**
765     * scrollbar on body and html element in IE and Edge overlay
766     * content and should be considered 0 width.
767     */
768    var BODY_SCROLLBAR_WIDTH;
769    var OVERFLOW_REGEX = {
770      normal: /(auto|scroll)/,
771      hidden: /(auto|scroll|hidden)/
772    };
773    var PLACEMENT_REGEX = {
774      auto: /\s?auto?\s?/i,
775      primary: /^(top|bottom|left|right)$/,
776      secondary: /^(top|bottom|left|right|center)$/,
777      vertical: /^(top|bottom)$/
778    };
779    var BODY_REGEX = /(HTML|BODY)/;
780
781    return {
782
783      /**
784       * Provides a raw DOM element from a jQuery/jQLite element.
785       *
786       * @param {element} elem - The element to convert.
787       *
788       * @returns {element} A HTML element.
789       */
790      getRawNode: function(elem) {
791        return elem.nodeName ? elem : elem[0] || elem;
792      },
793
794      /**
795       * Provides a parsed number for a style property.  Strips
796       * units and casts invalid numbers to 0.
797       *
798       * @param {string} value - The style value to parse.
799       *
800       * @returns {number} A valid number.
801       */
802      parseStyle: function(value) {
803        value = parseFloat(value);
804        return isFinite(value) ? value : 0;
805      },
806
807      /**
808       * Provides the closest positioned ancestor.
809       *
810       * @param {element} element - The element to get the offest parent for.
811       *
812       * @returns {element} The closest positioned ancestor.
813       */
814      offsetParent: function(elem) {
815        elem = this.getRawNode(elem);
816
817        var offsetParent = elem.offsetParent || $document[0].documentElement;
818
819        function isStaticPositioned(el) {
820          return ($window.getComputedStyle(el).position || 'static') === 'static';
821        }
822
823        while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
824          offsetParent = offsetParent.offsetParent;
825        }
826
827        return offsetParent || $document[0].documentElement;
828      },
829
830      /**
831       * Provides the scrollbar width, concept from TWBS measureScrollbar()
832       * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
833       * In IE and Edge, scollbar on body and html element overlay and should
834       * return a width of 0.
835       *
836       * @returns {number} The width of the browser scollbar.
837       */
838      scrollbarWidth: function(isBody) {
839        if (isBody) {
840          if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
841            var bodyElem = $document.find('body');
842            bodyElem.addClass('uib-position-body-scrollbar-measure');
843            BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
844            BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
845            bodyElem.removeClass('uib-position-body-scrollbar-measure');
846          }
847          return BODY_SCROLLBAR_WIDTH;
848        }
849
850        if (angular.isUndefined(SCROLLBAR_WIDTH)) {
851          var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
852          $document.find('body').append(scrollElem);
853          SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
854          SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
855          scrollElem.remove();
856        }
857
858        return SCROLLBAR_WIDTH;
859      },
860
861      /**
862       * Provides the padding required on an element to replace the scrollbar.
863       *
864       * @returns {object} An object with the following properties:
865       *   <ul>
866       *     <li>**scrollbarWidth**: the width of the scrollbar</li>
867       *     <li>**widthOverflow**: whether the the width is overflowing</li>
868       *     <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
869       *     <li>**rightOriginal**: the amount of right padding currently on the element</li>
870       *     <li>**heightOverflow**: whether the the height is overflowing</li>
871       *     <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
872       *     <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
873       *   </ul>
874       */
875      scrollbarPadding: function(elem) {
876        elem = this.getRawNode(elem);
877
878        var elemStyle = $window.getComputedStyle(elem);
879        var paddingRight = this.parseStyle(elemStyle.paddingRight);
880        var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
881        var scrollParent = this.scrollParent(elem, false, true);
882        var scrollbarWidth = this.scrollbarWidth(scrollParent, 
vendor: 18,751 bytes, lines 882-1281
882BODY_REGEX.test(scrollParent.tagName));
883
884        return {
885          scrollbarWidth: scrollbarWidth,
886          widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
887          right: paddingRight + scrollbarWidth,
888          originalRight: paddingRight,
889          heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
890          bottom: paddingBottom + scrollbarWidth,
891          originalBottom: paddingBottom
892         };
893      },
894
895      /**
896       * Checks to see if the element is scrollable.
897       *
898       * @param {element} elem - The element to check.
899       * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
900       *   default is false.
901       *
902       * @returns {boolean} Whether the element is scrollable.
903       */
904      isScrollable: function(elem, includeHidden) {
905        elem = this.getRawNode(elem);
906
907        var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
908        var elemStyle = $window.getComputedStyle(elem);
909        return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
910      },
911
912      /**
913       * Provides the closest scrollable ancestor.
914       * A port of the jQuery UI scrollParent method:
915       * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
916       *
917       * @param {element} elem - The element to find the scroll parent of.
918       * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
919       *   default is false.
920       * @param {boolean=} [includeSelf=false] - Should the element being passed be
921       * included in the scrollable llokup.
922       *
923       * @returns {element} A HTML element.
924       */
925      scrollParent: function(elem, includeHidden, includeSelf) {
926        elem = this.getRawNode(elem);
927
928        var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
929        var documentEl = $document[0].documentElement;
930        var elemStyle = $window.getComputedStyle(elem);
931        if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
932          return elem;
933        }
934        var excludeStatic = elemStyle.position === 'absolute';
935        var scrollParent = elem.parentElement || documentEl;
936
937        if (scrollParent === documentEl || elemStyle.position === 'fixed') {
938          return documentEl;
939        }
940
941        while (scrollParent.parentElement && scrollParent !== documentEl) {
942          var spStyle = $window.getComputedStyle(scrollParent);
943          if (excludeStatic && spStyle.position !== 'static') {
944            excludeStatic = false;
945          }
946
947          if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
948            break;
949          }
950          scrollParent = scrollParent.parentElement;
951        }
952
953        return scrollParent;
954      },
955
956      /**
957       * Provides read-only equivalent of jQuery's position function:
958       * http://api.jquery.com/position/ - distance to closest positioned
959       * ancestor.  Does not account for margins by default like jQuery position.
960       *
961       * @param {element} elem - The element to caclulate the position on.
962       * @param {boolean=} [includeMargins=false] - Should margins be accounted
963       * for, default is false.
964       *
965       * @returns {object} An object with the following properties:
966       *   <ul>
967       *     <li>**width**: the width of the element</li>
968       *     <li>**height**: the height of the element</li>
969       *     <li>**top**: distance to top edge of offset parent</li>
970       *     <li>**left**: distance to left edge of offset parent</li>
971       *   </ul>
972       */
973      position: function(elem, includeMagins) {
974        elem = this.getRawNode(elem);
975
976        var elemOffset = this.offset(elem);
977        if (includeMagins) {
978          var elemStyle = $window.getComputedStyle(elem);
979          elemOffset.top -= this.parseStyle(elemStyle.marginTop);
980          elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
981        }
982        var parent = this.offsetParent(elem);
983        var parentOffset = {top: 0, left: 0};
984
985        if (parent !== $document[0].documentElement) {
986          parentOffset = this.offset(parent);
987          parentOffset.top += parent.clientTop - parent.scrollTop;
988          parentOffset.left += parent.clientLeft - parent.scrollLeft;
989        }
990
991        return {
992          width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
993          height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
994          top: Math.round(elemOffset.top - parentOffset.top),
995          left: Math.round(elemOffset.left - parentOffset.left)
996        };
997      },
998
999      /**
1000       * Provides read-only equivalent of jQuery's offset function:
1001       * http://api.jquery.com/offset/ - distance to viewport.  Does
1002       * not account for borders, margins, or padding on the body
1003       * element.
1004       *
1005       * @param {element} elem - The element to calculate the offset on.
1006       *
1007       * @returns {object} An object with the following properties:
1008       *   <ul>
1009       *     <li>**width**: the width of the element</li>
1010       *     <li>**height**: the height of the element</li>
1011       *     <li>**top**: distance to top edge of viewport</li>
1012       *     <li>**right**: distance to bottom edge of viewport</li>
1013       *   </ul>
1014       */
1015      offset: function(elem) {
1016        elem = this.getRawNode(elem);
1017
1018        var elemBCR = elem.getBoundingClientRect();
1019        return {
1020          width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
1021          height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
1022          top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
1023          left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
1024        };
1025      },
1026
1027      /**
1028       * Provides offset distance to the closest scrollable ancestor
1029       * or viewport.  Accounts for border and scrollbar width.
1030       *
1031       * Right and bottom dimensions represent the distance to the
1032       * respective edge of the viewport element.  If the element
1033       * edge extends beyond the viewport, a negative value will be
1034       * reported.
1035       *
1036       * @param {element} elem - The element to get the viewport offset for.
1037       * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
1038       * of the first scrollable element, default is false.
1039       * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
1040       * be accounted for, default is true.
1041       *
1042       * @returns {object} An object with the following properties:
1043       *   <ul>
1044       *     <li>**top**: distance to the top content edge of viewport element</li>
1045       *     <li>**bottom**: distance to the bottom content edge of viewport element</li>
1046       *     <li>**left**: distance to the left content edge of viewport element</li>
1047       *     <li>**right**: distance to the right content edge of viewport element</li>
1048       *   </ul>
1049       */
1050      viewportOffset: function(elem, useDocument, includePadding) {
1051        elem = this.getRawNode(elem);
1052        includePadding = includePadding !== false ? true : false;
1053
1054        var elemBCR = elem.getBoundingClientRect();
1055        var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
1056
1057        var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
1058        var offsetParentBCR = offsetParent.getBoundingClientRect();
1059
1060        offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
1061        offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
1062        if (offsetParent === $document[0].documentElement) {
1063          offsetBCR.top += $window.pageYOffset;
1064          offsetBCR.left += $window.pageXOffset;
1065        }
1066        offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
1067        offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
1068
1069        if (includePadding) {
1070          var offsetParentStyle = $window.getComputedStyle(offsetParent);
1071          offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
1072          offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
1073          offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
1074          offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
1075        }
1076
1077        return {
1078          top: Math.round(elemBCR.top - offsetBCR.top),
1079          bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
1080          left: Math.round(elemBCR.left - offsetBCR.left),
1081          right: Math.round(offsetBCR.right - elemBCR.right)
1082        };
1083      },
1084
1085      /**
1086       * Provides an array of placement values parsed from a placement string.
1087       * Along with the 'auto' indicator, supported placement strings are:
1088       *   <ul>
1089       *     <li>top: element on top, horizontally centered on host element.</li>
1090       *     <li>top-left: element on top, left edge aligned with host element left edge.</li>
1091       *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
1092       *     <li>bottom: element on bottom, horizontally centered on host element.</li>
1093       *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
1094       *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
1095       *     <li>left: element on left, vertically centered on host element.</li>
1096       *     <li>left-top: element on left, top edge aligned with host element top edge.</li>
1097       *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
1098       *     <li>right: element on right, vertically centered on host element.</li>
1099       *     <li>right-top: element on right, top edge aligned with host element top edge.</li>
1100       *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
1101       *   </ul>
1102       * A placement string with an 'auto' indicator is expected to be
1103       * space separated from the placement, i.e: 'auto bottom-left'  If
1104       * the primary and secondary placement values do not match 'top,
1105       * bottom, left, right' then 'top' will be the primary placement and
1106       * 'center' will be the secondary placement.  If 'auto' is passed, true
1107       * will be returned as the 3rd value of the array.
1108       *
1109       * @param {string} placement - The placement string to parse.
1110       *
1111       * @returns {array} An array with the following values
1112       * <ul>
1113       *   <li>**[0]**: The primary placement.</li>
1114       *   <li>**[1]**: The secondary placement.</li>
1115       *   <li>**[2]**: If auto is passed: true, else undefined.</li>
1116       * </ul>
1117       */
1118      parsePlacement: function(placement) {
1119        var autoPlace = PLACEMENT_REGEX.auto.test(placement);
1120        if (autoPlace) {
1121          placement = placement.replace(PLACEMENT_REGEX.auto, '');
1122        }
1123
1124        placement = placement.split('-');
1125
1126        placement[0] = placement[0] || 'top';
1127        if (!PLACEMENT_REGEX.primary.test(placement[0])) {
1128          placement[0] = 'top';
1129        }
1130
1131        placement[1] = placement[1] || 'center';
1132        if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
1133          placement[1] = 'center';
1134        }
1135
1136        if (autoPlace) {
1137          placement[2] = true;
1138        } else {
1139          placement[2] = false;
1140        }
1141
1142        return placement;
1143      },
1144
1145      /**
1146       * Provides coordinates for an element to be positioned relative to
1147       * another element.  Passing 'auto' as part of the placement parameter
1148       * will enable smart placement - where the element fits. i.e:
1149       * 'auto left-top' will check to see if there is enough space to the left
1150       * of the hostElem to fit the targetElem, if not place right (same for secondary
1151       * top placement).  Available space is calculated using the viewportOffset
1152       * function.
1153       *
1154       * @param {element} hostElem - The element to position against.
1155       * @param {element} targetElem - The element to position.
1156       * @param {string=} [placement=top] - The placement for the targetElem,
1157       *   default is 'top'. 'center' is assumed as secondary placement for
1158       *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:
1159       *   <ul>
1160       *     <li>top</li>
1161       *     <li>top-right</li>
1162       *     <li>top-left</li>
1163       *     <li>bottom</li>
1164       *     <li>bottom-left</li>
1165       *     <li>bottom-right</li>
1166       *     <li>left</li>
1167       *     <li>left-top</li>
1168       *     <li>left-bottom</li>
1169       *     <li>right</li>
1170       *     <li>right-top</li>
1171       *     <li>right-bottom</li>
1172       *   </ul>
1173       * @param {boolean=} [appendToBody=false] - Should the top and left values returned
1174       *   be calculated from the body element, default is false.
1175       *
1176       * @returns {object} An object with the following properties:
1177       *   <ul>
1178       *     <li>**top**: Value for targetElem top.</li>
1179       *     <li>**left**: Value for targetElem left.</li>
1180       *     <li>**placement**: The resolved placement.</li>
1181       *   </ul>
1182       */
1183      positionElements: function(hostElem, targetElem, placement, appendToBody) {
1184        hostElem = this.getRawNode(hostElem);
1185        targetElem = this.getRawNode(targetElem);
1186
1187        // need to read from prop to support tests.
1188        var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
1189        var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
1190
1191        placement = this.parsePlacement(placement);
1192
1193        var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
1194        var targetElemPos = {top: 0, left: 0, placement: ''};
1195
1196        if (placement[2]) {
1197          var viewportOffset = this.viewportOffset(hostElem, appendToBody);
1198
1199          var targetElemStyle = $window.getComputedStyle(targetElem);
1200          var adjustedSize = {
1201            width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
1202            height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
1203          };
1204
1205          placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
1206                         placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
1207                         placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
1208                         placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
1209                         placement[0];
1210
1211          placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
1212                         placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
1213                         placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
1214                         placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
1215                         placement[1];
1216
1217          if (placement[1] === 'center') {
1218            if (PLACEMENT_REGEX.vertical.test(placement[0])) {
1219              var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
1220              if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
1221                placement[1] = 'left';
1222              } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
1223                placement[1] = 'right';
1224              }
1225            } else {
1226              var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
1227              if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
1228                placement[1] = 'top';
1229              } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
1230                placement[1] = 'bottom';
1231              }
1232            }
1233          }
1234        }
1235
1236        switch (placement[0]) {
1237          case 'top':
1238            targetElemPos.top = hostElemPos.top - targetHeight;
1239            break;
1240          case 'bottom':
1241            targetElemPos.top = hostElemPos.top + hostElemPos.height;
1242            break;
1243          case 'left':
1244            targetElemPos.left = hostElemPos.left - targetWidth;
1245            break;
1246          case 'right':
1247            targetElemPos.left = hostElemPos.left + hostElemPos.width;
1248            break;
1249        }
1250
1251        switch (placement[1]) {
1252          case 'top':
1253            targetElemPos.top = hostElemPos.top;
1254            break;
1255          case 'bottom':
1256            targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
1257            break;
1258          case 'left':
1259            targetElemPos.left = hostElemPos.left;
1260            break;
1261          case 'right':
1262            targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
1263            break;
1264          case 'center':
1265            if (PLACEMENT_REGEX.vertical.test(placement[0])) {
1266              targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
1267            } else {
1268              targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
1269            }
1270            break;
1271        }
1272
1273        targetElemPos.top = Math.round(targetElemPos.top);
1274        targetElemPos.left = Math.round(targetElemPos.left);
1275        targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
1276
1277        return targetElemPos;
1278      },
1279
1280      /**
1281      
vendor: 7,414 bytes, lines 1281-1405
1281* Provides a way for positioning tooltip & dropdown
1282      * arrows when using placement options beyond the standard
1283      * left, right, top, or bottom.
1284      *
1285      * @param {element} elem - The tooltip/dropdown element.
1286      * @param {string} placement - The placement for the elem.
1287      */
1288      positionArrow: function(elem, placement) {
1289        elem = this.getRawNode(elem);
1290
1291        var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
1292        if (!innerElem) {
1293          return;
1294        }
1295
1296        var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
1297
1298        var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
1299        if (!arrowElem) {
1300          return;
1301        }
1302
1303        var arrowCss = {
1304          top: '',
1305          bottom: '',
1306          left: '',
1307          right: ''
1308        };
1309
1310        placement = this.parsePlacement(placement);
1311        if (placement[1] === 'center') {
1312          // no adjustment necessary - just reset styles
1313          angular.element(arrowElem).css(arrowCss);
1314          return;
1315        }
1316
1317        var borderProp = 'border-' + placement[0] + '-width';
1318        var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
1319
1320        var borderRadiusProp = 'border-';
1321        if (PLACEMENT_REGEX.vertical.test(placement[0])) {
1322          borderRadiusProp += placement[0] + '-' + placement[1];
1323        } else {
1324          borderRadiusProp += placement[1] + '-' + placement[0];
1325        }
1326        borderRadiusProp += '-radius';
1327        var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
1328
1329        switch (placement[0]) {
1330          case 'top':
1331            arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
1332            break;
1333          case 'bottom':
1334            arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
1335            break;
1336          case 'left':
1337            arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
1338            break;
1339          case 'right':
1340            arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
1341            break;
1342        }
1343
1344        arrowCss[placement[1]] = borderRadius;
1345
1346        angular.element(arrowElem).css(arrowCss);
1347      }
1348    };
1349  }]);
1350
1351angular.module('ui.bootstrap.stackedMap', [])
1352/**
1353 * A helper, internal data structure that acts as a map but also allows getting / removing
1354 * elements in the LIFO order
1355 */
1356  .factory('$$stackedMap', function() {
1357    return {
1358      createNew: function() {
1359        var stack = [];
1360
1361        return {
1362          add: function(key, value) {
1363            stack.push({
1364              key: key,
1365              value: value
1366            });
1367          },
1368          get: function(key) {
1369            for (var i = 0; i < stack.length; i++) {
1370              if (key === stack[i].key) {
1371                return stack[i];
1372              }
1373            }
1374          },
1375          keys: function() {
1376            var keys = [];
1377            for (var i = 0; i < stack.length; i++) {
1378              keys.push(stack[i].key);
1379            }
1380            return keys;
1381          },
1382          top: function() {
1383            return stack[stack.length - 1];
1384          },
1385          remove: function(key) {
1386            var idx = -1;
1387            for (var i = 0; i < stack.length; i++) {
1388              if (key === stack[i].key) {
1389                idx = i;
1390                break;
1391              }
1392            }
1393            return stack.splice(idx, 1)[0];
1394          },
1395          removeTop: function() {
1396            return stack.splice(stack.length - 1, 1)[0];
1397          },
1398          length: function() {
1399            return stack.length;
1400          }
1401        };
1402      }
1403    };
1404  });angular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
1405angular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.