angular-pack 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0183cf5e868db8d39ba6772d97cb349d22226850
4
- data.tar.gz: 5230b17d8055b27855f3b42581ceb2850c109b07
3
+ metadata.gz: 4e4aac2e14abaf25ca2ed1ceef5da03af90b80ce
4
+ data.tar.gz: 61b13263881153b81757f03cbd6d805731721204
5
5
  SHA512:
6
- metadata.gz: 2367f8ad283a0c3bfac0ac296f307a4071fafee1219e956c53414504245b58a6fc6dd4a51e5ab67502b6ec7b92e87f82d2b3c69f167e162842ccda14cdb08b56
7
- data.tar.gz: afa8a3be47ca6461fbc4616a04c6a3f21a32dd4eb03a3e871d60b03207ac755d64c826cf38a60e6152b7d60b4b27e7dd65f47bed29fea1072c55624b20e3b01b
6
+ metadata.gz: 4cb62acc76aa21c015b8dc74e0827a67628558293590ab892132b7f6b41d0f48c135ea7e78551f030e5f2ace04bf83a1dbfb242a7b773e71ea57557764038f6f
7
+ data.tar.gz: 68be51b8d6efc4a4d7b5ef0432693e11f7c8e5515c739ef49347adcd68349bb903881f96af8a7391378785e482fb6f2b7165e4e10737cf4290c3f10383fa4830
@@ -1,5 +1,5 @@
1
1
  module Angular
2
2
  module Pack
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
@@ -5,7 +5,8 @@
5
5
  * Version: 0.10.0 - 2014-01-13
6
6
  * License: MIT
7
7
  */
8
- angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
8
+ angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
9
+ angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]);
9
10
  angular.module('ui.bootstrap.transition', [])
10
11
 
11
12
  /**
@@ -3425,3 +3426,252 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3425
3426
  return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;
3426
3427
  };
3427
3428
  });
3429
+ angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
3430
+ $templateCache.put("template/accordion/accordion-group.html",
3431
+ "<div class=\"panel panel-default\">\n" +
3432
+ " <div class=\"panel-heading\">\n" +
3433
+ " <h4 class=\"panel-title\">\n" +
3434
+ " <a class=\"accordion-toggle\" ng-click=\"isOpen = !isOpen\" accordion-transclude=\"heading\">{{heading}}</a>\n" +
3435
+ " </h4>\n" +
3436
+ " </div>\n" +
3437
+ " <div class=\"panel-collapse\" collapse=\"!isOpen\">\n" +
3438
+ " <div class=\"panel-body\" ng-transclude></div>\n" +
3439
+ " </div>\n" +
3440
+ "</div>");
3441
+ }]);
3442
+
3443
+ angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
3444
+ $templateCache.put("template/accordion/accordion.html",
3445
+ "<div class=\"panel-group\" ng-transclude></div>");
3446
+ }]);
3447
+
3448
+ angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
3449
+ $templateCache.put("template/alert/alert.html",
3450
+ "<div class='alert' ng-class='\"alert-\" + (type || \"warning\")'>\n" +
3451
+ " <button ng-show='closeable' type='button' class='close' ng-click='close()'>&times;</button>\n" +
3452
+ " <div ng-transclude></div>\n" +
3453
+ "</div>\n" +
3454
+ "");
3455
+ }]);
3456
+
3457
+ angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
3458
+ $templateCache.put("template/carousel/carousel.html",
3459
+ "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\">\n" +
3460
+ " <ol class=\"carousel-indicators\" ng-show=\"slides().length > 1\">\n" +
3461
+ " <li ng-repeat=\"slide in slides()\" ng-class=\"{active: isActive(slide)}\" ng-click=\"select(slide)\"></li>\n" +
3462
+ " </ol>\n" +
3463
+ " <div class=\"carousel-inner\" ng-transclude></div>\n" +
3464
+ " <a class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides().length > 1\"><span class=\"icon-prev\"></span></a>\n" +
3465
+ " <a class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides().length > 1\"><span class=\"icon-next\"></span></a>\n" +
3466
+ "</div>\n" +
3467
+ "");
3468
+ }]);
3469
+
3470
+ angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
3471
+ $templateCache.put("template/carousel/slide.html",
3472
+ "<div ng-class=\"{\n" +
3473
+ " 'active': leaving || (active && !entering),\n" +
3474
+ " 'prev': (next || active) && direction=='prev',\n" +
3475
+ " 'next': (next || active) && direction=='next',\n" +
3476
+ " 'right': direction=='prev',\n" +
3477
+ " 'left': direction=='next'\n" +
3478
+ " }\" class=\"item text-center\" ng-transclude></div>\n" +
3479
+ "");
3480
+ }]);
3481
+
3482
+ angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
3483
+ $templateCache.put("template/datepicker/datepicker.html",
3484
+ "<table>\n" +
3485
+ " <thead>\n" +
3486
+ " <tr>\n" +
3487
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
3488
+ " <th colspan=\"{{rows[0].length - 2 + showWeekNumbers}}\"><button type=\"button\" class=\"btn btn-default btn-sm btn-block\" ng-click=\"toggleMode()\"><strong>{{title}}</strong></button></th>\n" +
3489
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
3490
+ " </tr>\n" +
3491
+ " <tr ng-show=\"labels.length > 0\" class=\"h6\">\n" +
3492
+ " <th ng-show=\"showWeekNumbers\" class=\"text-center\">#</th>\n" +
3493
+ " <th ng-repeat=\"label in labels\" class=\"text-center\">{{label}}</th>\n" +
3494
+ " </tr>\n" +
3495
+ " </thead>\n" +
3496
+ " <tbody>\n" +
3497
+ " <tr ng-repeat=\"row in rows\">\n" +
3498
+ " <td ng-show=\"showWeekNumbers\" class=\"text-center\"><em>{{ getWeekNumber(row) }}</em></td>\n" +
3499
+ " <td ng-repeat=\"dt in row\" class=\"text-center\">\n" +
3500
+ " <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\"><span ng-class=\"{'text-muted': dt.secondary}\">{{dt.label}}</span></button>\n" +
3501
+ " </td>\n" +
3502
+ " </tr>\n" +
3503
+ " </tbody>\n" +
3504
+ "</table>\n" +
3505
+ "");
3506
+ }]);
3507
+
3508
+ angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
3509
+ $templateCache.put("template/datepicker/popup.html",
3510
+ "<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
3511
+ " <li ng-transclude></li>\n" +
3512
+ " <li ng-show=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
3513
+ " <span class=\"btn-group\">\n" +
3514
+ " <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"today()\">{{currentText}}</button>\n" +
3515
+ " <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showWeeks = ! showWeeks\" ng-class=\"{active: showWeeks}\">{{toggleWeeksText}}</button>\n" +
3516
+ " <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"clear()\">{{clearText}}</button>\n" +
3517
+ " </span>\n" +
3518
+ " <button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"isOpen = false\">{{closeText}}</button>\n" +
3519
+ " </li>\n" +
3520
+ "</ul>\n" +
3521
+ "");
3522
+ }]);
3523
+
3524
+ angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
3525
+ $templateCache.put("template/modal/backdrop.html",
3526
+ "<div class=\"modal-backdrop fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1040 + index*10}\"></div>");
3527
+ }]);
3528
+
3529
+ angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
3530
+ $templateCache.put("template/modal/window.html",
3531
+ "<div tabindex=\"-1\" class=\"modal fade {{ windowClass }}\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
3532
+ " <div class=\"modal-dialog\"><div class=\"modal-content\" ng-transclude></div></div>\n" +
3533
+ "</div>");
3534
+ }]);
3535
+
3536
+ angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) {
3537
+ $templateCache.put("template/pagination/pager.html",
3538
+ "<ul class=\"pager\">\n" +
3539
+ " <li ng-repeat=\"page in pages\" ng-class=\"{disabled: page.disabled, previous: page.previous, next: page.next}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
3540
+ "</ul>");
3541
+ }]);
3542
+
3543
+ angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
3544
+ $templateCache.put("template/pagination/pagination.html",
3545
+ "<ul class=\"pagination\">\n" +
3546
+ " <li ng-repeat=\"page in pages\" ng-class=\"{active: page.active, disabled: page.disabled}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
3547
+ "</ul>");
3548
+ }]);
3549
+
3550
+ angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
3551
+ $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
3552
+ "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3553
+ " <div class=\"tooltip-arrow\"></div>\n" +
3554
+ " <div class=\"tooltip-inner\" bind-html-unsafe=\"content\"></div>\n" +
3555
+ "</div>\n" +
3556
+ "");
3557
+ }]);
3558
+
3559
+ angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
3560
+ $templateCache.put("template/tooltip/tooltip-popup.html",
3561
+ "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3562
+ " <div class=\"tooltip-arrow\"></div>\n" +
3563
+ " <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
3564
+ "</div>\n" +
3565
+ "");
3566
+ }]);
3567
+
3568
+ angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
3569
+ $templateCache.put("template/popover/popover.html",
3570
+ "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3571
+ " <div class=\"arrow\"></div>\n" +
3572
+ "\n" +
3573
+ " <div class=\"popover-inner\">\n" +
3574
+ " <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
3575
+ " <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
3576
+ " </div>\n" +
3577
+ "</div>\n" +
3578
+ "");
3579
+ }]);
3580
+
3581
+ angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
3582
+ $templateCache.put("template/progressbar/bar.html",
3583
+ "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div>");
3584
+ }]);
3585
+
3586
+ angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
3587
+ $templateCache.put("template/progressbar/progress.html",
3588
+ "<div class=\"progress\" ng-transclude></div>");
3589
+ }]);
3590
+
3591
+ angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
3592
+ $templateCache.put("template/progressbar/progressbar.html",
3593
+ "<div class=\"progress\"><div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div></div>");
3594
+ }]);
3595
+
3596
+ angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
3597
+ $templateCache.put("template/rating/rating.html",
3598
+ "<span ng-mouseleave=\"reset()\">\n" +
3599
+ " <i ng-repeat=\"r in range\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < val && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\"></i>\n" +
3600
+ "</span>");
3601
+ }]);
3602
+
3603
+ angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
3604
+ $templateCache.put("template/tabs/tab.html",
3605
+ "<li ng-class=\"{active: active, disabled: disabled}\">\n" +
3606
+ " <a ng-click=\"select()\" tab-heading-transclude>{{heading}}</a>\n" +
3607
+ "</li>\n" +
3608
+ "");
3609
+ }]);
3610
+
3611
+ angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
3612
+ $templateCache.put("template/tabs/tabset-titles.html",
3613
+ "<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n" +
3614
+ "</ul>\n" +
3615
+ "");
3616
+ }]);
3617
+
3618
+ angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
3619
+ $templateCache.put("template/tabs/tabset.html",
3620
+ "\n" +
3621
+ "<div class=\"tabbable\">\n" +
3622
+ " <ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
3623
+ " <div class=\"tab-content\">\n" +
3624
+ " <div class=\"tab-pane\" \n" +
3625
+ " ng-repeat=\"tab in tabs\" \n" +
3626
+ " ng-class=\"{active: tab.active}\"\n" +
3627
+ " tab-content-transclude=\"tab\">\n" +
3628
+ " </div>\n" +
3629
+ " </div>\n" +
3630
+ "</div>\n" +
3631
+ "");
3632
+ }]);
3633
+
3634
+ angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
3635
+ $templateCache.put("template/timepicker/timepicker.html",
3636
+ "<table>\n" +
3637
+ " <tbody>\n" +
3638
+ " <tr class=\"text-center\">\n" +
3639
+ " <td><a ng-click=\"incrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
3640
+ " <td>&nbsp;</td>\n" +
3641
+ " <td><a ng-click=\"incrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
3642
+ " <td ng-show=\"showMeridian\"></td>\n" +
3643
+ " </tr>\n" +
3644
+ " <tr>\n" +
3645
+ " <td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidHours}\">\n" +
3646
+ " <input type=\"text\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-mousewheel=\"incrementHours()\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
3647
+ " </td>\n" +
3648
+ " <td>:</td>\n" +
3649
+ " <td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
3650
+ " <input type=\"text\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
3651
+ " </td>\n" +
3652
+ " <td ng-show=\"showMeridian\"><button type=\"button\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\">{{meridian}}</button></td>\n" +
3653
+ " </tr>\n" +
3654
+ " <tr class=\"text-center\">\n" +
3655
+ " <td><a ng-click=\"decrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
3656
+ " <td>&nbsp;</td>\n" +
3657
+ " <td><a ng-click=\"decrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
3658
+ " <td ng-show=\"showMeridian\"></td>\n" +
3659
+ " </tr>\n" +
3660
+ " </tbody>\n" +
3661
+ "</table>\n" +
3662
+ "");
3663
+ }]);
3664
+
3665
+ angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
3666
+ $templateCache.put("template/typeahead/typeahead-match.html",
3667
+ "<a tabindex=\"-1\" bind-html-unsafe=\"match.label | typeaheadHighlight:query\"></a>");
3668
+ }]);
3669
+
3670
+ angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
3671
+ $templateCache.put("template/typeahead/typeahead-popup.html",
3672
+ "<ul class=\"dropdown-menu\" ng-style=\"{display: isOpen()&&'block' || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
3673
+ " <li ng-repeat=\"match in matches\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index)\">\n" +
3674
+ " <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
3675
+ " </li>\n" +
3676
+ "</ul>");
3677
+ }]);
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: angular-pack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ali Hasan Imam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-03 00:00:00.000000000 Z
11
+ date: 2014-05-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: AngularJS and AngularUI functionality.
14
14
  email:
@@ -39,7 +39,6 @@ files:
39
39
  - vendor/assets/javascripts/devise.js
40
40
  - vendor/assets/javascripts/es5-shim.js
41
41
  - vendor/assets/javascripts/ng-grid.js
42
- - vendor/assets/javascripts/ui-bootstrap-tpls.js
43
42
  - vendor/assets/javascripts/ui-bootstrap.js
44
43
  - vendor/assets/javascripts/ui-date.js
45
44
  - vendor/assets/javascripts/ui-map.js
@@ -1,3677 +0,0 @@
1
- /*
2
- * angular-ui-bootstrap
3
- * http://angular-ui.github.io/bootstrap/
4
-
5
- * Version: 0.10.0 - 2014-01-13
6
- * License: MIT
7
- */
8
- angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
9
- angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]);
10
- angular.module('ui.bootstrap.transition', [])
11
-
12
- /**
13
- * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
14
- * @param {DOMElement} element The DOMElement that will be animated.
15
- * @param {string|object|function} trigger The thing that will cause the transition to start:
16
- * - As a string, it represents the css class to be added to the element.
17
- * - As an object, it represents a hash of style attributes to be applied to the element.
18
- * - As a function, it represents a function to be called that will cause the transition to occur.
19
- * @return {Promise} A promise that is resolved when the transition finishes.
20
- */
21
- .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
22
-
23
- var $transition = function(element, trigger, options) {
24
- options = options || {};
25
- var deferred = $q.defer();
26
- var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
27
-
28
- var transitionEndHandler = function(event) {
29
- $rootScope.$apply(function() {
30
- element.unbind(endEventName, transitionEndHandler);
31
- deferred.resolve(element);
32
- });
33
- };
34
-
35
- if (endEventName) {
36
- element.bind(endEventName, transitionEndHandler);
37
- }
38
-
39
- // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
40
- $timeout(function() {
41
- if ( angular.isString(trigger) ) {
42
- element.addClass(trigger);
43
- } else if ( angular.isFunction(trigger) ) {
44
- trigger(element);
45
- } else if ( angular.isObject(trigger) ) {
46
- element.css(trigger);
47
- }
48
- //If browser does not support transitions, instantly resolve
49
- if ( !endEventName ) {
50
- deferred.resolve(element);
51
- }
52
- });
53
-
54
- // Add our custom cancel function to the promise that is returned
55
- // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
56
- // i.e. it will therefore never raise a transitionEnd event for that transition
57
- deferred.promise.cancel = function() {
58
- if ( endEventName ) {
59
- element.unbind(endEventName, transitionEndHandler);
60
- }
61
- deferred.reject('Transition cancelled');
62
- };
63
-
64
- return deferred.promise;
65
- };
66
-
67
- // Work out the name of the transitionEnd event
68
- var transElement = document.createElement('trans');
69
- var transitionEndEventNames = {
70
- 'WebkitTransition': 'webkitTransitionEnd',
71
- 'MozTransition': 'transitionend',
72
- 'OTransition': 'oTransitionEnd',
73
- 'transition': 'transitionend'
74
- };
75
- var animationEndEventNames = {
76
- 'WebkitTransition': 'webkitAnimationEnd',
77
- 'MozTransition': 'animationend',
78
- 'OTransition': 'oAnimationEnd',
79
- 'transition': 'animationend'
80
- };
81
- function findEndEventName(endEventNames) {
82
- for (var name in endEventNames){
83
- if (transElement.style[name] !== undefined) {
84
- return endEventNames[name];
85
- }
86
- }
87
- }
88
- $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
89
- $transition.animationEndEventName = findEndEventName(animationEndEventNames);
90
- return $transition;
91
- }]);
92
-
93
- angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])
94
-
95
- .directive('collapse', ['$transition', function ($transition, $timeout) {
96
-
97
- return {
98
- link: function (scope, element, attrs) {
99
-
100
- var initialAnimSkip = true;
101
- var currentTransition;
102
-
103
- function doTransition(change) {
104
- var newTransition = $transition(element, change);
105
- if (currentTransition) {
106
- currentTransition.cancel();
107
- }
108
- currentTransition = newTransition;
109
- newTransition.then(newTransitionDone, newTransitionDone);
110
- return newTransition;
111
-
112
- function newTransitionDone() {
113
- // Make sure it's this transition, otherwise, leave it alone.
114
- if (currentTransition === newTransition) {
115
- currentTransition = undefined;
116
- }
117
- }
118
- }
119
-
120
- function expand() {
121
- if (initialAnimSkip) {
122
- initialAnimSkip = false;
123
- expandDone();
124
- } else {
125
- element.removeClass('collapse').addClass('collapsing');
126
- doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);
127
- }
128
- }
129
-
130
- function expandDone() {
131
- element.removeClass('collapsing');
132
- element.addClass('collapse in');
133
- element.css({height: 'auto'});
134
- }
135
-
136
- function collapse() {
137
- if (initialAnimSkip) {
138
- initialAnimSkip = false;
139
- collapseDone();
140
- element.css({height: 0});
141
- } else {
142
- // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
143
- element.css({ height: element[0].scrollHeight + 'px' });
144
- //trigger reflow so a browser realizes that height was updated from auto to a specific value
145
- var x = element[0].offsetWidth;
146
-
147
- element.removeClass('collapse in').addClass('collapsing');
148
-
149
- doTransition({ height: 0 }).then(collapseDone);
150
- }
151
- }
152
-
153
- function collapseDone() {
154
- element.removeClass('collapsing');
155
- element.addClass('collapse');
156
- }
157
-
158
- scope.$watch(attrs.collapse, function (shouldCollapse) {
159
- if (shouldCollapse) {
160
- collapse();
161
- } else {
162
- expand();
163
- }
164
- });
165
- }
166
- };
167
- }]);
168
-
169
- angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
170
-
171
- .constant('accordionConfig', {
172
- closeOthers: true
173
- })
174
-
175
- .controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {
176
-
177
- // This array keeps track of the accordion groups
178
- this.groups = [];
179
-
180
- // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
181
- this.closeOthers = function(openGroup) {
182
- var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
183
- if ( closeOthers ) {
184
- angular.forEach(this.groups, function (group) {
185
- if ( group !== openGroup ) {
186
- group.isOpen = false;
187
- }
188
- });
189
- }
190
- };
191
-
192
- // This is called from the accordion-group directive to add itself to the accordion
193
- this.addGroup = function(groupScope) {
194
- var that = this;
195
- this.groups.push(groupScope);
196
-
197
- groupScope.$on('$destroy', function (event) {
198
- that.removeGroup(groupScope);
199
- });
200
- };
201
-
202
- // This is called from the accordion-group directive when to remove itself
203
- this.removeGroup = function(group) {
204
- var index = this.groups.indexOf(group);
205
- if ( index !== -1 ) {
206
- this.groups.splice(this.groups.indexOf(group), 1);
207
- }
208
- };
209
-
210
- }])
211
-
212
- // The accordion directive simply sets up the directive controller
213
- // and adds an accordion CSS class to itself element.
214
- .directive('accordion', function () {
215
- return {
216
- restrict:'EA',
217
- controller:'AccordionController',
218
- transclude: true,
219
- replace: false,
220
- templateUrl: 'template/accordion/accordion.html'
221
- };
222
- })
223
-
224
- // The accordion-group directive indicates a block of html that will expand and collapse in an accordion
225
- .directive('accordionGroup', ['$parse', function($parse) {
226
- return {
227
- require:'^accordion', // We need this directive to be inside an accordion
228
- restrict:'EA',
229
- transclude:true, // It transcludes the contents of the directive into the template
230
- replace: true, // The element containing the directive will be replaced with the template
231
- templateUrl:'template/accordion/accordion-group.html',
232
- scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope
233
- controller: function() {
234
- this.setHeading = function(element) {
235
- this.heading = element;
236
- };
237
- },
238
- link: function(scope, element, attrs, accordionCtrl) {
239
- var getIsOpen, setIsOpen;
240
-
241
- accordionCtrl.addGroup(scope);
242
-
243
- scope.isOpen = false;
244
-
245
- if ( attrs.isOpen ) {
246
- getIsOpen = $parse(attrs.isOpen);
247
- setIsOpen = getIsOpen.assign;
248
-
249
- scope.$parent.$watch(getIsOpen, function(value) {
250
- scope.isOpen = !!value;
251
- });
252
- }
253
-
254
- scope.$watch('isOpen', function(value) {
255
- if ( value ) {
256
- accordionCtrl.closeOthers(scope);
257
- }
258
- if ( setIsOpen ) {
259
- setIsOpen(scope.$parent, value);
260
- }
261
- });
262
- }
263
- };
264
- }])
265
-
266
- // Use accordion-heading below an accordion-group to provide a heading containing HTML
267
- // <accordion-group>
268
- // <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
269
- // </accordion-group>
270
- .directive('accordionHeading', function() {
271
- return {
272
- restrict: 'EA',
273
- transclude: true, // Grab the contents to be used as the heading
274
- template: '', // In effect remove this element!
275
- replace: true,
276
- require: '^accordionGroup',
277
- compile: function(element, attr, transclude) {
278
- return function link(scope, element, attr, accordionGroupCtrl) {
279
- // Pass the heading to the accordion-group controller
280
- // so that it can be transcluded into the right place in the template
281
- // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
282
- accordionGroupCtrl.setHeading(transclude(scope, function() {}));
283
- };
284
- }
285
- };
286
- })
287
-
288
- // Use in the accordion-group template to indicate where you want the heading to be transcluded
289
- // You must provide the property on the accordion-group controller that will hold the transcluded element
290
- // <div class="accordion-group">
291
- // <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
292
- // ...
293
- // </div>
294
- .directive('accordionTransclude', function() {
295
- return {
296
- require: '^accordionGroup',
297
- link: function(scope, element, attr, controller) {
298
- scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {
299
- if ( heading ) {
300
- element.html('');
301
- element.append(heading);
302
- }
303
- });
304
- }
305
- };
306
- });
307
-
308
- angular.module("ui.bootstrap.alert", [])
309
-
310
- .controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
311
- $scope.closeable = 'close' in $attrs;
312
- }])
313
-
314
- .directive('alert', function () {
315
- return {
316
- restrict:'EA',
317
- controller:'AlertController',
318
- templateUrl:'template/alert/alert.html',
319
- transclude:true,
320
- replace:true,
321
- scope: {
322
- type: '=',
323
- close: '&'
324
- }
325
- };
326
- });
327
-
328
- angular.module('ui.bootstrap.bindHtml', [])
329
-
330
- .directive('bindHtmlUnsafe', function () {
331
- return function (scope, element, attr) {
332
- element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe);
333
- scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) {
334
- element.html(value || '');
335
- });
336
- };
337
- });
338
- angular.module('ui.bootstrap.buttons', [])
339
-
340
- .constant('buttonConfig', {
341
- activeClass: 'active',
342
- toggleEvent: 'click'
343
- })
344
-
345
- .controller('ButtonsController', ['buttonConfig', function(buttonConfig) {
346
- this.activeClass = buttonConfig.activeClass || 'active';
347
- this.toggleEvent = buttonConfig.toggleEvent || 'click';
348
- }])
349
-
350
- .directive('btnRadio', function () {
351
- return {
352
- require: ['btnRadio', 'ngModel'],
353
- controller: 'ButtonsController',
354
- link: function (scope, element, attrs, ctrls) {
355
- var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
356
-
357
- //model -> UI
358
- ngModelCtrl.$render = function () {
359
- element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
360
- };
361
-
362
- //ui->model
363
- element.bind(buttonsCtrl.toggleEvent, function () {
364
- if (!element.hasClass(buttonsCtrl.activeClass)) {
365
- scope.$apply(function () {
366
- ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio));
367
- ngModelCtrl.$render();
368
- });
369
- }
370
- });
371
- }
372
- };
373
- })
374
-
375
- .directive('btnCheckbox', function () {
376
- return {
377
- require: ['btnCheckbox', 'ngModel'],
378
- controller: 'ButtonsController',
379
- link: function (scope, element, attrs, ctrls) {
380
- var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
381
-
382
- function getTrueValue() {
383
- return getCheckboxValue(attrs.btnCheckboxTrue, true);
384
- }
385
-
386
- function getFalseValue() {
387
- return getCheckboxValue(attrs.btnCheckboxFalse, false);
388
- }
389
-
390
- function getCheckboxValue(attributeValue, defaultValue) {
391
- var val = scope.$eval(attributeValue);
392
- return angular.isDefined(val) ? val : defaultValue;
393
- }
394
-
395
- //model -> UI
396
- ngModelCtrl.$render = function () {
397
- element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
398
- };
399
-
400
- //ui->model
401
- element.bind(buttonsCtrl.toggleEvent, function () {
402
- scope.$apply(function () {
403
- ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
404
- ngModelCtrl.$render();
405
- });
406
- });
407
- }
408
- };
409
- });
410
-
411
- /**
412
- * @ngdoc overview
413
- * @name ui.bootstrap.carousel
414
- *
415
- * @description
416
- * AngularJS version of an image carousel.
417
- *
418
- */
419
- angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
420
- .controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) {
421
- var self = this,
422
- slides = self.slides = [],
423
- currentIndex = -1,
424
- currentTimeout, isPlaying;
425
- self.currentSlide = null;
426
-
427
- var destroyed = false;
428
- /* direction: "prev" or "next" */
429
- self.select = function(nextSlide, direction) {
430
- var nextIndex = slides.indexOf(nextSlide);
431
- //Decide direction if it's not given
432
- if (direction === undefined) {
433
- direction = nextIndex > currentIndex ? "next" : "prev";
434
- }
435
- if (nextSlide && nextSlide !== self.currentSlide) {
436
- if ($scope.$currentTransition) {
437
- $scope.$currentTransition.cancel();
438
- //Timeout so ng-class in template has time to fix classes for finished slide
439
- $timeout(goNext);
440
- } else {
441
- goNext();
442
- }
443
- }
444
- function goNext() {
445
- // Scope has been destroyed, stop here.
446
- if (destroyed) { return; }
447
- //If we have a slide to transition from and we have a transition type and we're allowed, go
448
- if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {
449
- //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime
450
- nextSlide.$element.addClass(direction);
451
- var reflow = nextSlide.$element[0].offsetWidth; //force reflow
452
-
453
- //Set all other slides to stop doing their stuff for the new transition
454
- angular.forEach(slides, function(slide) {
455
- angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});
456
- });
457
- angular.extend(nextSlide, {direction: direction, active: true, entering: true});
458
- angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});
459
-
460
- $scope.$currentTransition = $transition(nextSlide.$element, {});
461
- //We have to create new pointers inside a closure since next & current will change
462
- (function(next,current) {
463
- $scope.$currentTransition.then(
464
- function(){ transitionDone(next, current); },
465
- function(){ transitionDone(next, current); }
466
- );
467
- }(nextSlide, self.currentSlide));
468
- } else {
469
- transitionDone(nextSlide, self.currentSlide);
470
- }
471
- self.currentSlide = nextSlide;
472
- currentIndex = nextIndex;
473
- //every time you change slides, reset the timer
474
- restartTimer();
475
- }
476
- function transitionDone(next, current) {
477
- angular.extend(next, {direction: '', active: true, leaving: false, entering: false});
478
- angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});
479
- $scope.$currentTransition = null;
480
- }
481
- };
482
- $scope.$on('$destroy', function () {
483
- destroyed = true;
484
- });
485
-
486
- /* Allow outside people to call indexOf on slides array */
487
- self.indexOfSlide = function(slide) {
488
- return slides.indexOf(slide);
489
- };
490
-
491
- $scope.next = function() {
492
- var newIndex = (currentIndex + 1) % slides.length;
493
-
494
- //Prevent this user-triggered transition from occurring if there is already one in progress
495
- if (!$scope.$currentTransition) {
496
- return self.select(slides[newIndex], 'next');
497
- }
498
- };
499
-
500
- $scope.prev = function() {
501
- var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;
502
-
503
- //Prevent this user-triggered transition from occurring if there is already one in progress
504
- if (!$scope.$currentTransition) {
505
- return self.select(slides[newIndex], 'prev');
506
- }
507
- };
508
-
509
- $scope.select = function(slide) {
510
- self.select(slide);
511
- };
512
-
513
- $scope.isActive = function(slide) {
514
- return self.currentSlide === slide;
515
- };
516
-
517
- $scope.slides = function() {
518
- return slides;
519
- };
520
-
521
- $scope.$watch('interval', restartTimer);
522
- $scope.$on('$destroy', resetTimer);
523
-
524
- function restartTimer() {
525
- resetTimer();
526
- var interval = +$scope.interval;
527
- if (!isNaN(interval) && interval>=0) {
528
- currentTimeout = $timeout(timerFn, interval);
529
- }
530
- }
531
-
532
- function resetTimer() {
533
- if (currentTimeout) {
534
- $timeout.cancel(currentTimeout);
535
- currentTimeout = null;
536
- }
537
- }
538
-
539
- function timerFn() {
540
- if (isPlaying) {
541
- $scope.next();
542
- restartTimer();
543
- } else {
544
- $scope.pause();
545
- }
546
- }
547
-
548
- $scope.play = function() {
549
- if (!isPlaying) {
550
- isPlaying = true;
551
- restartTimer();
552
- }
553
- };
554
- $scope.pause = function() {
555
- if (!$scope.noPause) {
556
- isPlaying = false;
557
- resetTimer();
558
- }
559
- };
560
-
561
- self.addSlide = function(slide, element) {
562
- slide.$element = element;
563
- slides.push(slide);
564
- //if this is the first slide or the slide is set to active, select it
565
- if(slides.length === 1 || slide.active) {
566
- self.select(slides[slides.length-1]);
567
- if (slides.length == 1) {
568
- $scope.play();
569
- }
570
- } else {
571
- slide.active = false;
572
- }
573
- };
574
-
575
- self.removeSlide = function(slide) {
576
- //get the index of the slide inside the carousel
577
- var index = slides.indexOf(slide);
578
- slides.splice(index, 1);
579
- if (slides.length > 0 && slide.active) {
580
- if (index >= slides.length) {
581
- self.select(slides[index-1]);
582
- } else {
583
- self.select(slides[index]);
584
- }
585
- } else if (currentIndex > index) {
586
- currentIndex--;
587
- }
588
- };
589
-
590
- }])
591
-
592
- /**
593
- * @ngdoc directive
594
- * @name ui.bootstrap.carousel.directive:carousel
595
- * @restrict EA
596
- *
597
- * @description
598
- * Carousel is the outer container for a set of image 'slides' to showcase.
599
- *
600
- * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.
601
- * @param {boolean=} noTransition Whether to disable transitions on the carousel.
602
- * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).
603
- *
604
- * @example
605
- <example module="ui.bootstrap">
606
- <file name="index.html">
607
- <carousel>
608
- <slide>
609
- <img src="http://placekitten.com/150/150" style="margin:auto;">
610
- <div class="carousel-caption">
611
- <p>Beautiful!</p>
612
- </div>
613
- </slide>
614
- <slide>
615
- <img src="http://placekitten.com/100/150" style="margin:auto;">
616
- <div class="carousel-caption">
617
- <p>D'aww!</p>
618
- </div>
619
- </slide>
620
- </carousel>
621
- </file>
622
- <file name="demo.css">
623
- .carousel-indicators {
624
- top: auto;
625
- bottom: 15px;
626
- }
627
- </file>
628
- </example>
629
- */
630
- .directive('carousel', [function() {
631
- return {
632
- restrict: 'EA',
633
- transclude: true,
634
- replace: true,
635
- controller: 'CarouselController',
636
- require: 'carousel',
637
- templateUrl: 'template/carousel/carousel.html',
638
- scope: {
639
- interval: '=',
640
- noTransition: '=',
641
- noPause: '='
642
- }
643
- };
644
- }])
645
-
646
- /**
647
- * @ngdoc directive
648
- * @name ui.bootstrap.carousel.directive:slide
649
- * @restrict EA
650
- *
651
- * @description
652
- * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element.
653
- *
654
- * @param {boolean=} active Model binding, whether or not this slide is currently active.
655
- *
656
- * @example
657
- <example module="ui.bootstrap">
658
- <file name="index.html">
659
- <div ng-controller="CarouselDemoCtrl">
660
- <carousel>
661
- <slide ng-repeat="slide in slides" active="slide.active">
662
- <img ng-src="{{slide.image}}" style="margin:auto;">
663
- <div class="carousel-caption">
664
- <h4>Slide {{$index}}</h4>
665
- <p>{{slide.text}}</p>
666
- </div>
667
- </slide>
668
- </carousel>
669
- <div class="row-fluid">
670
- <div class="span6">
671
- <ul>
672
- <li ng-repeat="slide in slides">
673
- <button class="btn btn-mini" ng-class="{'btn-info': !slide.active, 'btn-success': slide.active}" ng-disabled="slide.active" ng-click="slide.active = true">select</button>
674
- {{$index}}: {{slide.text}}
675
- </li>
676
- </ul>
677
- <a class="btn" ng-click="addSlide()">Add Slide</a>
678
- </div>
679
- <div class="span6">
680
- Interval, in milliseconds: <input type="number" ng-model="myInterval">
681
- <br />Enter a negative number to stop the interval.
682
- </div>
683
- </div>
684
- </div>
685
- </file>
686
- <file name="script.js">
687
- function CarouselDemoCtrl($scope) {
688
- $scope.myInterval = 5000;
689
- var slides = $scope.slides = [];
690
- $scope.addSlide = function() {
691
- var newWidth = 200 + ((slides.length + (25 * slides.length)) % 150);
692
- slides.push({
693
- image: 'http://placekitten.com/' + newWidth + '/200',
694
- text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' '
695
- ['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4]
696
- });
697
- };
698
- for (var i=0; i<4; i++) $scope.addSlide();
699
- }
700
- </file>
701
- <file name="demo.css">
702
- .carousel-indicators {
703
- top: auto;
704
- bottom: 15px;
705
- }
706
- </file>
707
- </example>
708
- */
709
-
710
- .directive('slide', ['$parse', function($parse) {
711
- return {
712
- require: '^carousel',
713
- restrict: 'EA',
714
- transclude: true,
715
- replace: true,
716
- templateUrl: 'template/carousel/slide.html',
717
- scope: {
718
- },
719
- link: function (scope, element, attrs, carouselCtrl) {
720
- //Set up optional 'active' = binding
721
- if (attrs.active) {
722
- var getActive = $parse(attrs.active);
723
- var setActive = getActive.assign;
724
- var lastValue = scope.active = getActive(scope.$parent);
725
- scope.$watch(function parentActiveWatch() {
726
- var parentActive = getActive(scope.$parent);
727
-
728
- if (parentActive !== scope.active) {
729
- // we are out of sync and need to copy
730
- if (parentActive !== lastValue) {
731
- // parent changed and it has precedence
732
- lastValue = scope.active = parentActive;
733
- } else {
734
- // if the parent can be assigned then do so
735
- setActive(scope.$parent, parentActive = lastValue = scope.active);
736
- }
737
- }
738
- return parentActive;
739
- });
740
- }
741
-
742
- carouselCtrl.addSlide(scope, element);
743
- //when the scope is destroyed then remove the slide from the current slides array
744
- scope.$on('$destroy', function() {
745
- carouselCtrl.removeSlide(scope);
746
- });
747
-
748
- scope.$watch('active', function(active) {
749
- if (active) {
750
- carouselCtrl.select(scope);
751
- }
752
- });
753
- }
754
- };
755
- }]);
756
-
757
- angular.module('ui.bootstrap.position', [])
758
-
759
- /**
760
- * A set of utility methods that can be use to retrieve position of DOM elements.
761
- * It is meant to be used where we need to absolute-position DOM elements in
762
- * relation to other, existing elements (this is the case for tooltips, popovers,
763
- * typeahead suggestions etc.).
764
- */
765
- .factory('$position', ['$document', '$window', function ($document, $window) {
766
-
767
- function getStyle(el, cssprop) {
768
- if (el.currentStyle) { //IE
769
- return el.currentStyle[cssprop];
770
- } else if ($window.getComputedStyle) {
771
- return $window.getComputedStyle(el)[cssprop];
772
- }
773
- // finally try and get inline style
774
- return el.style[cssprop];
775
- }
776
-
777
- /**
778
- * Checks if a given element is statically positioned
779
- * @param element - raw DOM element
780
- */
781
- function isStaticPositioned(element) {
782
- return (getStyle(element, "position") || 'static' ) === 'static';
783
- }
784
-
785
- /**
786
- * returns the closest, non-statically positioned parentOffset of a given element
787
- * @param element
788
- */
789
- var parentOffsetEl = function (element) {
790
- var docDomEl = $document[0];
791
- var offsetParent = element.offsetParent || docDomEl;
792
- while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
793
- offsetParent = offsetParent.offsetParent;
794
- }
795
- return offsetParent || docDomEl;
796
- };
797
-
798
- return {
799
- /**
800
- * Provides read-only equivalent of jQuery's position function:
801
- * http://api.jquery.com/position/
802
- */
803
- position: function (element) {
804
- var elBCR = this.offset(element);
805
- var offsetParentBCR = { top: 0, left: 0 };
806
- var offsetParentEl = parentOffsetEl(element[0]);
807
- if (offsetParentEl != $document[0]) {
808
- offsetParentBCR = this.offset(angular.element(offsetParentEl));
809
- offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
810
- offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
811
- }
812
-
813
- var boundingClientRect = element[0].getBoundingClientRect();
814
- return {
815
- width: boundingClientRect.width || element.prop('offsetWidth'),
816
- height: boundingClientRect.height || element.prop('offsetHeight'),
817
- top: elBCR.top - offsetParentBCR.top,
818
- left: elBCR.left - offsetParentBCR.left
819
- };
820
- },
821
-
822
- /**
823
- * Provides read-only equivalent of jQuery's offset function:
824
- * http://api.jquery.com/offset/
825
- */
826
- offset: function (element) {
827
- var boundingClientRect = element[0].getBoundingClientRect();
828
- return {
829
- width: boundingClientRect.width || element.prop('offsetWidth'),
830
- height: boundingClientRect.height || element.prop('offsetHeight'),
831
- top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
832
- left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
833
- };
834
- }
835
- };
836
- }]);
837
-
838
- angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
839
-
840
- .constant('datepickerConfig', {
841
- dayFormat: 'dd',
842
- monthFormat: 'MMMM',
843
- yearFormat: 'yyyy',
844
- dayHeaderFormat: 'EEE',
845
- dayTitleFormat: 'MMMM yyyy',
846
- monthTitleFormat: 'yyyy',
847
- showWeeks: true,
848
- startingDay: 0,
849
- yearRange: 20,
850
- minDate: null,
851
- maxDate: null
852
- })
853
-
854
- .controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
855
- var format = {
856
- day: getValue($attrs.dayFormat, dtConfig.dayFormat),
857
- month: getValue($attrs.monthFormat, dtConfig.monthFormat),
858
- year: getValue($attrs.yearFormat, dtConfig.yearFormat),
859
- dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
860
- dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
861
- monthTitle: getValue($attrs.monthTitleFormat, dtConfig.monthTitleFormat)
862
- },
863
- startingDay = getValue($attrs.startingDay, dtConfig.startingDay),
864
- yearRange = getValue($attrs.yearRange, dtConfig.yearRange);
865
-
866
- this.minDate = dtConfig.minDate ? new Date(dtConfig.minDate) : null;
867
- this.maxDate = dtConfig.maxDate ? new Date(dtConfig.maxDate) : null;
868
-
869
- function getValue(value, defaultValue) {
870
- return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
871
- }
872
-
873
- function getDaysInMonth( year, month ) {
874
- return new Date(year, month, 0).getDate();
875
- }
876
-
877
- function getDates(startDate, n) {
878
- var dates = new Array(n);
879
- var current = startDate, i = 0;
880
- while (i < n) {
881
- dates[i++] = new Date(current);
882
- current.setDate( current.getDate() + 1 );
883
- }
884
- return dates;
885
- }
886
-
887
- function makeDate(date, format, isSelected, isSecondary) {
888
- return { date: date, label: dateFilter(date, format), selected: !!isSelected, secondary: !!isSecondary };
889
- }
890
-
891
- this.modes = [
892
- {
893
- name: 'day',
894
- getVisibleDates: function(date, selected) {
895
- var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1);
896
- var difference = startingDay - firstDayOfMonth.getDay(),
897
- numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,
898
- firstDate = new Date(firstDayOfMonth), numDates = 0;
899
-
900
- if ( numDisplayedFromPreviousMonth > 0 ) {
901
- firstDate.setDate( - numDisplayedFromPreviousMonth + 1 );
902
- numDates += numDisplayedFromPreviousMonth; // Previous
903
- }
904
- numDates += getDaysInMonth(year, month + 1); // Current
905
- numDates += (7 - numDates % 7) % 7; // Next
906
-
907
- var days = getDates(firstDate, numDates), labels = new Array(7);
908
- for (var i = 0; i < numDates; i ++) {
909
- var dt = new Date(days[i]);
910
- days[i] = makeDate(dt, format.day, (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear()), dt.getMonth() !== month);
911
- }
912
- for (var j = 0; j < 7; j++) {
913
- labels[j] = dateFilter(days[j].date, format.dayHeader);
914
- }
915
- return { objects: days, title: dateFilter(date, format.dayTitle), labels: labels };
916
- },
917
- compare: function(date1, date2) {
918
- return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) );
919
- },
920
- split: 7,
921
- step: { months: 1 }
922
- },
923
- {
924
- name: 'month',
925
- getVisibleDates: function(date, selected) {
926
- var months = new Array(12), year = date.getFullYear();
927
- for ( var i = 0; i < 12; i++ ) {
928
- var dt = new Date(year, i, 1);
929
- months[i] = makeDate(dt, format.month, (selected && selected.getMonth() === i && selected.getFullYear() === year));
930
- }
931
- return { objects: months, title: dateFilter(date, format.monthTitle) };
932
- },
933
- compare: function(date1, date2) {
934
- return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() );
935
- },
936
- split: 3,
937
- step: { years: 1 }
938
- },
939
- {
940
- name: 'year',
941
- getVisibleDates: function(date, selected) {
942
- var years = new Array(yearRange), year = date.getFullYear(), startYear = parseInt((year - 1) / yearRange, 10) * yearRange + 1;
943
- for ( var i = 0; i < yearRange; i++ ) {
944
- var dt = new Date(startYear + i, 0, 1);
945
- years[i] = makeDate(dt, format.year, (selected && selected.getFullYear() === dt.getFullYear()));
946
- }
947
- return { objects: years, title: [years[0].label, years[yearRange - 1].label].join(' - ') };
948
- },
949
- compare: function(date1, date2) {
950
- return date1.getFullYear() - date2.getFullYear();
951
- },
952
- split: 5,
953
- step: { years: yearRange }
954
- }
955
- ];
956
-
957
- this.isDisabled = function(date, mode) {
958
- var currentMode = this.modes[mode || 0];
959
- return ((this.minDate && currentMode.compare(date, this.minDate) < 0) || (this.maxDate && currentMode.compare(date, this.maxDate) > 0) || ($scope.dateDisabled && $scope.dateDisabled({date: date, mode: currentMode.name})));
960
- };
961
- }])
962
-
963
- .directive( 'datepicker', ['dateFilter', '$parse', 'datepickerConfig', '$log', function (dateFilter, $parse, datepickerConfig, $log) {
964
- return {
965
- restrict: 'EA',
966
- replace: true,
967
- templateUrl: 'template/datepicker/datepicker.html',
968
- scope: {
969
- dateDisabled: '&'
970
- },
971
- require: ['datepicker', '?^ngModel'],
972
- controller: 'DatepickerController',
973
- link: function(scope, element, attrs, ctrls) {
974
- var datepickerCtrl = ctrls[0], ngModel = ctrls[1];
975
-
976
- if (!ngModel) {
977
- return; // do nothing if no ng-model
978
- }
979
-
980
- // Configuration parameters
981
- var mode = 0, selected = new Date(), showWeeks = datepickerConfig.showWeeks;
982
-
983
- if (attrs.showWeeks) {
984
- scope.$parent.$watch($parse(attrs.showWeeks), function(value) {
985
- showWeeks = !! value;
986
- updateShowWeekNumbers();
987
- });
988
- } else {
989
- updateShowWeekNumbers();
990
- }
991
-
992
- if (attrs.min) {
993
- scope.$parent.$watch($parse(attrs.min), function(value) {
994
- datepickerCtrl.minDate = value ? new Date(value) : null;
995
- refill();
996
- });
997
- }
998
- if (attrs.max) {
999
- scope.$parent.$watch($parse(attrs.max), function(value) {
1000
- datepickerCtrl.maxDate = value ? new Date(value) : null;
1001
- refill();
1002
- });
1003
- }
1004
-
1005
- function updateShowWeekNumbers() {
1006
- scope.showWeekNumbers = mode === 0 && showWeeks;
1007
- }
1008
-
1009
- // Split array into smaller arrays
1010
- function split(arr, size) {
1011
- var arrays = [];
1012
- while (arr.length > 0) {
1013
- arrays.push(arr.splice(0, size));
1014
- }
1015
- return arrays;
1016
- }
1017
-
1018
- function refill( updateSelected ) {
1019
- var date = null, valid = true;
1020
-
1021
- if ( ngModel.$modelValue ) {
1022
- date = new Date( ngModel.$modelValue );
1023
-
1024
- if ( isNaN(date) ) {
1025
- valid = false;
1026
- $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
1027
- } else if ( updateSelected ) {
1028
- selected = date;
1029
- }
1030
- }
1031
- ngModel.$setValidity('date', valid);
1032
-
1033
- var currentMode = datepickerCtrl.modes[mode], data = currentMode.getVisibleDates(selected, date);
1034
- angular.forEach(data.objects, function(obj) {
1035
- obj.disabled = datepickerCtrl.isDisabled(obj.date, mode);
1036
- });
1037
-
1038
- ngModel.$setValidity('date-disabled', (!date || !datepickerCtrl.isDisabled(date)));
1039
-
1040
- scope.rows = split(data.objects, currentMode.split);
1041
- scope.labels = data.labels || [];
1042
- scope.title = data.title;
1043
- }
1044
-
1045
- function setMode(value) {
1046
- mode = value;
1047
- updateShowWeekNumbers();
1048
- refill();
1049
- }
1050
-
1051
- ngModel.$render = function() {
1052
- refill( true );
1053
- };
1054
-
1055
- scope.select = function( date ) {
1056
- if ( mode === 0 ) {
1057
- var dt = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);
1058
- dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );
1059
- ngModel.$setViewValue( dt );
1060
- refill( true );
1061
- } else {
1062
- selected = date;
1063
- setMode( mode - 1 );
1064
- }
1065
- };
1066
- scope.move = function(direction) {
1067
- var step = datepickerCtrl.modes[mode].step;
1068
- selected.setMonth( selected.getMonth() + direction * (step.months || 0) );
1069
- selected.setFullYear( selected.getFullYear() + direction * (step.years || 0) );
1070
- refill();
1071
- };
1072
- scope.toggleMode = function() {
1073
- setMode( (mode + 1) % datepickerCtrl.modes.length );
1074
- };
1075
- scope.getWeekNumber = function(row) {
1076
- return ( mode === 0 && scope.showWeekNumbers && row.length === 7 ) ? getISO8601WeekNumber(row[0].date) : null;
1077
- };
1078
-
1079
- function getISO8601WeekNumber(date) {
1080
- var checkDate = new Date(date);
1081
- checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
1082
- var time = checkDate.getTime();
1083
- checkDate.setMonth(0); // Compare with Jan 1
1084
- checkDate.setDate(1);
1085
- return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1086
- }
1087
- }
1088
- };
1089
- }])
1090
-
1091
- .constant('datepickerPopupConfig', {
1092
- dateFormat: 'yyyy-MM-dd',
1093
- currentText: 'Today',
1094
- toggleWeeksText: 'Weeks',
1095
- clearText: 'Clear',
1096
- closeText: 'Done',
1097
- closeOnDateSelection: true,
1098
- appendToBody: false,
1099
- showButtonBar: true
1100
- })
1101
-
1102
- .directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'datepickerConfig',
1103
- function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, datepickerConfig) {
1104
- return {
1105
- restrict: 'EA',
1106
- require: 'ngModel',
1107
- link: function(originalScope, element, attrs, ngModel) {
1108
- var scope = originalScope.$new(), // create a child scope so we are not polluting original one
1109
- dateFormat,
1110
- closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? originalScope.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,
1111
- appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? originalScope.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;
1112
-
1113
- attrs.$observe('datepickerPopup', function(value) {
1114
- dateFormat = value || datepickerPopupConfig.dateFormat;
1115
- ngModel.$render();
1116
- });
1117
-
1118
- scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? originalScope.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;
1119
-
1120
- originalScope.$on('$destroy', function() {
1121
- $popup.remove();
1122
- scope.$destroy();
1123
- });
1124
-
1125
- attrs.$observe('currentText', function(text) {
1126
- scope.currentText = angular.isDefined(text) ? text : datepickerPopupConfig.currentText;
1127
- });
1128
- attrs.$observe('toggleWeeksText', function(text) {
1129
- scope.toggleWeeksText = angular.isDefined(text) ? text : datepickerPopupConfig.toggleWeeksText;
1130
- });
1131
- attrs.$observe('clearText', function(text) {
1132
- scope.clearText = angular.isDefined(text) ? text : datepickerPopupConfig.clearText;
1133
- });
1134
- attrs.$observe('closeText', function(text) {
1135
- scope.closeText = angular.isDefined(text) ? text : datepickerPopupConfig.closeText;
1136
- });
1137
-
1138
- var getIsOpen, setIsOpen;
1139
- if ( attrs.isOpen ) {
1140
- getIsOpen = $parse(attrs.isOpen);
1141
- setIsOpen = getIsOpen.assign;
1142
-
1143
- originalScope.$watch(getIsOpen, function updateOpen(value) {
1144
- scope.isOpen = !! value;
1145
- });
1146
- }
1147
- scope.isOpen = getIsOpen ? getIsOpen(originalScope) : false; // Initial state
1148
-
1149
- function setOpen( value ) {
1150
- if (setIsOpen) {
1151
- setIsOpen(originalScope, !!value);
1152
- } else {
1153
- scope.isOpen = !!value;
1154
- }
1155
- }
1156
-
1157
- var documentClickBind = function(event) {
1158
- if (scope.isOpen && event.target !== element[0]) {
1159
- scope.$apply(function() {
1160
- setOpen(false);
1161
- });
1162
- }
1163
- };
1164
-
1165
- var elementFocusBind = function() {
1166
- scope.$apply(function() {
1167
- setOpen( true );
1168
- });
1169
- };
1170
-
1171
- // popup element used to display calendar
1172
- var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
1173
- popupEl.attr({
1174
- 'ng-model': 'date',
1175
- 'ng-change': 'dateSelection()'
1176
- });
1177
- var datepickerEl = angular.element(popupEl.children()[0]),
1178
- datepickerOptions = {};
1179
- if (attrs.datepickerOptions) {
1180
- datepickerOptions = originalScope.$eval(attrs.datepickerOptions);
1181
- datepickerEl.attr(angular.extend({}, datepickerOptions));
1182
- }
1183
-
1184
- // TODO: reverse from dateFilter string to Date object
1185
- function parseDate(viewValue) {
1186
- if (!viewValue) {
1187
- ngModel.$setValidity('date', true);
1188
- return null;
1189
- } else if (angular.isDate(viewValue)) {
1190
- ngModel.$setValidity('date', true);
1191
- return viewValue;
1192
- } else if (angular.isString(viewValue)) {
1193
- var date = new Date(viewValue);
1194
- if (isNaN(date)) {
1195
- ngModel.$setValidity('date', false);
1196
- return undefined;
1197
- } else {
1198
- ngModel.$setValidity('date', true);
1199
- return date;
1200
- }
1201
- } else {
1202
- ngModel.$setValidity('date', false);
1203
- return undefined;
1204
- }
1205
- }
1206
- ngModel.$parsers.unshift(parseDate);
1207
-
1208
- // Inner change
1209
- scope.dateSelection = function(dt) {
1210
- if (angular.isDefined(dt)) {
1211
- scope.date = dt;
1212
- }
1213
- ngModel.$setViewValue(scope.date);
1214
- ngModel.$render();
1215
-
1216
- if (closeOnDateSelection) {
1217
- setOpen( false );
1218
- }
1219
- };
1220
-
1221
- element.bind('input change keyup', function() {
1222
- scope.$apply(function() {
1223
- scope.date = ngModel.$modelValue;
1224
- });
1225
- });
1226
-
1227
- // Outter change
1228
- ngModel.$render = function() {
1229
- var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
1230
- element.val(date);
1231
- scope.date = ngModel.$modelValue;
1232
- };
1233
-
1234
- function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) {
1235
- if (attribute) {
1236
- originalScope.$watch($parse(attribute), function(value){
1237
- scope[scopeProperty] = value;
1238
- });
1239
- datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty);
1240
- }
1241
- }
1242
- addWatchableAttribute(attrs.min, 'min');
1243
- addWatchableAttribute(attrs.max, 'max');
1244
- if (attrs.showWeeks) {
1245
- addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks');
1246
- } else {
1247
- scope.showWeeks = 'show-weeks' in datepickerOptions ? datepickerOptions['show-weeks'] : datepickerConfig.showWeeks;
1248
- datepickerEl.attr('show-weeks', 'showWeeks');
1249
- }
1250
- if (attrs.dateDisabled) {
1251
- datepickerEl.attr('date-disabled', attrs.dateDisabled);
1252
- }
1253
-
1254
- function updatePosition() {
1255
- scope.position = appendToBody ? $position.offset(element) : $position.position(element);
1256
- scope.position.top = scope.position.top + element.prop('offsetHeight');
1257
- }
1258
-
1259
- var documentBindingInitialized = false, elementFocusInitialized = false;
1260
- scope.$watch('isOpen', function(value) {
1261
- if (value) {
1262
- updatePosition();
1263
- $document.bind('click', documentClickBind);
1264
- if(elementFocusInitialized) {
1265
- element.unbind('focus', elementFocusBind);
1266
- }
1267
- element[0].focus();
1268
- documentBindingInitialized = true;
1269
- } else {
1270
- if(documentBindingInitialized) {
1271
- $document.unbind('click', documentClickBind);
1272
- }
1273
- element.bind('focus', elementFocusBind);
1274
- elementFocusInitialized = true;
1275
- }
1276
-
1277
- if ( setIsOpen ) {
1278
- setIsOpen(originalScope, value);
1279
- }
1280
- });
1281
-
1282
- scope.today = function() {
1283
- scope.dateSelection(new Date());
1284
- };
1285
- scope.clear = function() {
1286
- scope.dateSelection(null);
1287
- };
1288
-
1289
- var $popup = $compile(popupEl)(scope);
1290
- if ( appendToBody ) {
1291
- $document.find('body').append($popup);
1292
- } else {
1293
- element.after($popup);
1294
- }
1295
- }
1296
- };
1297
- }])
1298
-
1299
- .directive('datepickerPopupWrap', function() {
1300
- return {
1301
- restrict:'EA',
1302
- replace: true,
1303
- transclude: true,
1304
- templateUrl: 'template/datepicker/popup.html',
1305
- link:function (scope, element, attrs) {
1306
- element.bind('click', function(event) {
1307
- event.preventDefault();
1308
- event.stopPropagation();
1309
- });
1310
- }
1311
- };
1312
- });
1313
-
1314
- /*
1315
- * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js
1316
- * @restrict class or attribute
1317
- * @example:
1318
- <li class="dropdown">
1319
- <a class="dropdown-toggle">My Dropdown Menu</a>
1320
- <ul class="dropdown-menu">
1321
- <li ng-repeat="choice in dropChoices">
1322
- <a ng-href="{{choice.href}}">{{choice.text}}</a>
1323
- </li>
1324
- </ul>
1325
- </li>
1326
- */
1327
-
1328
- angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', ['$document', '$location', function ($document, $location) {
1329
- var openElement = null,
1330
- closeMenu = angular.noop;
1331
- return {
1332
- restrict: 'CA',
1333
- link: function(scope, element, attrs) {
1334
- scope.$watch('$location.path', function() { closeMenu(); });
1335
- element.parent().bind('click', function() { closeMenu(); });
1336
- element.bind('click', function (event) {
1337
-
1338
- var elementWasOpen = (element === openElement);
1339
-
1340
- event.preventDefault();
1341
- event.stopPropagation();
1342
-
1343
- if (!!openElement) {
1344
- closeMenu();
1345
- }
1346
-
1347
- if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) {
1348
- element.parent().addClass('open');
1349
- openElement = element;
1350
- closeMenu = function (event) {
1351
- if (event) {
1352
- event.preventDefault();
1353
- event.stopPropagation();
1354
- }
1355
- $document.unbind('click', closeMenu);
1356
- element.parent().removeClass('open');
1357
- closeMenu = angular.noop;
1358
- openElement = null;
1359
- };
1360
- $document.bind('click', closeMenu);
1361
- }
1362
- });
1363
- }
1364
- };
1365
- }]);
1366
-
1367
- angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1368
-
1369
- /**
1370
- * A helper, internal data structure that acts as a map but also allows getting / removing
1371
- * elements in the LIFO order
1372
- */
1373
- .factory('$$stackedMap', function () {
1374
- return {
1375
- createNew: function () {
1376
- var stack = [];
1377
-
1378
- return {
1379
- add: function (key, value) {
1380
- stack.push({
1381
- key: key,
1382
- value: value
1383
- });
1384
- },
1385
- get: function (key) {
1386
- for (var i = 0; i < stack.length; i++) {
1387
- if (key == stack[i].key) {
1388
- return stack[i];
1389
- }
1390
- }
1391
- },
1392
- keys: function() {
1393
- var keys = [];
1394
- for (var i = 0; i < stack.length; i++) {
1395
- keys.push(stack[i].key);
1396
- }
1397
- return keys;
1398
- },
1399
- top: function () {
1400
- return stack[stack.length - 1];
1401
- },
1402
- remove: function (key) {
1403
- var idx = -1;
1404
- for (var i = 0; i < stack.length; i++) {
1405
- if (key == stack[i].key) {
1406
- idx = i;
1407
- break;
1408
- }
1409
- }
1410
- return stack.splice(idx, 1)[0];
1411
- },
1412
- removeTop: function () {
1413
- return stack.splice(stack.length - 1, 1)[0];
1414
- },
1415
- length: function () {
1416
- return stack.length;
1417
- }
1418
- };
1419
- }
1420
- };
1421
- })
1422
-
1423
- /**
1424
- * A helper directive for the $modal service. It creates a backdrop element.
1425
- */
1426
- .directive('modalBackdrop', ['$timeout', function ($timeout) {
1427
- return {
1428
- restrict: 'EA',
1429
- replace: true,
1430
- templateUrl: 'template/modal/backdrop.html',
1431
- link: function (scope) {
1432
-
1433
- scope.animate = false;
1434
-
1435
- //trigger CSS transitions
1436
- $timeout(function () {
1437
- scope.animate = true;
1438
- });
1439
- }
1440
- };
1441
- }])
1442
-
1443
- .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
1444
- return {
1445
- restrict: 'EA',
1446
- scope: {
1447
- index: '@',
1448
- animate: '='
1449
- },
1450
- replace: true,
1451
- transclude: true,
1452
- templateUrl: 'template/modal/window.html',
1453
- link: function (scope, element, attrs) {
1454
- scope.windowClass = attrs.windowClass || '';
1455
-
1456
- $timeout(function () {
1457
- // trigger CSS transitions
1458
- scope.animate = true;
1459
- // focus a freshly-opened modal
1460
- element[0].focus();
1461
- });
1462
-
1463
- scope.close = function (evt) {
1464
- var modal = $modalStack.getTop();
1465
- if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
1466
- evt.preventDefault();
1467
- evt.stopPropagation();
1468
- $modalStack.dismiss(modal.key, 'backdrop click');
1469
- }
1470
- };
1471
- }
1472
- };
1473
- }])
1474
-
1475
- .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
1476
- function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1477
-
1478
- var OPENED_MODAL_CLASS = 'modal-open';
1479
-
1480
- var backdropDomEl, backdropScope;
1481
- var openedWindows = $$stackedMap.createNew();
1482
- var $modalStack = {};
1483
-
1484
- function backdropIndex() {
1485
- var topBackdropIndex = -1;
1486
- var opened = openedWindows.keys();
1487
- for (var i = 0; i < opened.length; i++) {
1488
- if (openedWindows.get(opened[i]).value.backdrop) {
1489
- topBackdropIndex = i;
1490
- }
1491
- }
1492
- return topBackdropIndex;
1493
- }
1494
-
1495
- $rootScope.$watch(backdropIndex, function(newBackdropIndex){
1496
- if (backdropScope) {
1497
- backdropScope.index = newBackdropIndex;
1498
- }
1499
- });
1500
-
1501
- function removeModalWindow(modalInstance) {
1502
-
1503
- var body = $document.find('body').eq(0);
1504
- var modalWindow = openedWindows.get(modalInstance).value;
1505
-
1506
- //clean up the stack
1507
- openedWindows.remove(modalInstance);
1508
-
1509
- //remove window DOM element
1510
- removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop);
1511
- body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1512
- }
1513
-
1514
- function checkRemoveBackdrop() {
1515
- //remove backdrop if no longer needed
1516
- if (backdropDomEl && backdropIndex() == -1) {
1517
- var backdropScopeRef = backdropScope;
1518
- removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
1519
- backdropScopeRef.$destroy();
1520
- backdropScopeRef = null;
1521
- });
1522
- backdropDomEl = undefined;
1523
- backdropScope = undefined;
1524
- }
1525
- }
1526
-
1527
- function removeAfterAnimate(domEl, scope, emulateTime, done) {
1528
- // Closing animation
1529
- scope.animate = false;
1530
-
1531
- var transitionEndEventName = $transition.transitionEndEventName;
1532
- if (transitionEndEventName) {
1533
- // transition out
1534
- var timeout = $timeout(afterAnimating, emulateTime);
1535
-
1536
- domEl.bind(transitionEndEventName, function () {
1537
- $timeout.cancel(timeout);
1538
- afterAnimating();
1539
- scope.$apply();
1540
- });
1541
- } else {
1542
- // Ensure this call is async
1543
- $timeout(afterAnimating, 0);
1544
- }
1545
-
1546
- function afterAnimating() {
1547
- if (afterAnimating.done) {
1548
- return;
1549
- }
1550
- afterAnimating.done = true;
1551
-
1552
- domEl.remove();
1553
- if (done) {
1554
- done();
1555
- }
1556
- }
1557
- }
1558
-
1559
- $document.bind('keydown', function (evt) {
1560
- var modal;
1561
-
1562
- if (evt.which === 27) {
1563
- modal = openedWindows.top();
1564
- if (modal && modal.value.keyboard) {
1565
- $rootScope.$apply(function () {
1566
- $modalStack.dismiss(modal.key);
1567
- });
1568
- }
1569
- }
1570
- });
1571
-
1572
- $modalStack.open = function (modalInstance, modal) {
1573
-
1574
- openedWindows.add(modalInstance, {
1575
- deferred: modal.deferred,
1576
- modalScope: modal.scope,
1577
- backdrop: modal.backdrop,
1578
- keyboard: modal.keyboard
1579
- });
1580
-
1581
- var body = $document.find('body').eq(0),
1582
- currBackdropIndex = backdropIndex();
1583
-
1584
- if (currBackdropIndex >= 0 && !backdropDomEl) {
1585
- backdropScope = $rootScope.$new(true);
1586
- backdropScope.index = currBackdropIndex;
1587
- backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
1588
- body.append(backdropDomEl);
1589
- }
1590
-
1591
- var angularDomEl = angular.element('<div modal-window></div>');
1592
- angularDomEl.attr('window-class', modal.windowClass);
1593
- angularDomEl.attr('index', openedWindows.length() - 1);
1594
- angularDomEl.attr('animate', 'animate');
1595
- angularDomEl.html(modal.content);
1596
-
1597
- var modalDomEl = $compile(angularDomEl)(modal.scope);
1598
- openedWindows.top().value.modalDomEl = modalDomEl;
1599
- body.append(modalDomEl);
1600
- body.addClass(OPENED_MODAL_CLASS);
1601
- };
1602
-
1603
- $modalStack.close = function (modalInstance, result) {
1604
- var modalWindow = openedWindows.get(modalInstance).value;
1605
- if (modalWindow) {
1606
- modalWindow.deferred.resolve(result);
1607
- removeModalWindow(modalInstance);
1608
- }
1609
- };
1610
-
1611
- $modalStack.dismiss = function (modalInstance, reason) {
1612
- var modalWindow = openedWindows.get(modalInstance).value;
1613
- if (modalWindow) {
1614
- modalWindow.deferred.reject(reason);
1615
- removeModalWindow(modalInstance);
1616
- }
1617
- };
1618
-
1619
- $modalStack.dismissAll = function (reason) {
1620
- var topModal = this.getTop();
1621
- while (topModal) {
1622
- this.dismiss(topModal.key, reason);
1623
- topModal = this.getTop();
1624
- }
1625
- };
1626
-
1627
- $modalStack.getTop = function () {
1628
- return openedWindows.top();
1629
- };
1630
-
1631
- return $modalStack;
1632
- }])
1633
-
1634
- .provider('$modal', function () {
1635
-
1636
- var $modalProvider = {
1637
- options: {
1638
- backdrop: true, //can be also false or 'static'
1639
- keyboard: true
1640
- },
1641
- $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
1642
- function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
1643
-
1644
- var $modal = {};
1645
-
1646
- function getTemplatePromise(options) {
1647
- return options.template ? $q.when(options.template) :
1648
- $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
1649
- return result.data;
1650
- });
1651
- }
1652
-
1653
- function getResolvePromises(resolves) {
1654
- var promisesArr = [];
1655
- angular.forEach(resolves, function (value, key) {
1656
- if (angular.isFunction(value) || angular.isArray(value)) {
1657
- promisesArr.push($q.when($injector.invoke(value)));
1658
- }
1659
- });
1660
- return promisesArr;
1661
- }
1662
-
1663
- $modal.open = function (modalOptions) {
1664
-
1665
- var modalResultDeferred = $q.defer();
1666
- var modalOpenedDeferred = $q.defer();
1667
-
1668
- //prepare an instance of a modal to be injected into controllers and returned to a caller
1669
- var modalInstance = {
1670
- result: modalResultDeferred.promise,
1671
- opened: modalOpenedDeferred.promise,
1672
- close: function (result) {
1673
- $modalStack.close(modalInstance, result);
1674
- },
1675
- dismiss: function (reason) {
1676
- $modalStack.dismiss(modalInstance, reason);
1677
- }
1678
- };
1679
-
1680
- //merge and clean up options
1681
- modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
1682
- modalOptions.resolve = modalOptions.resolve || {};
1683
-
1684
- //verify options
1685
- if (!modalOptions.template && !modalOptions.templateUrl) {
1686
- throw new Error('One of template or templateUrl options is required.');
1687
- }
1688
-
1689
- var templateAndResolvePromise =
1690
- $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
1691
-
1692
-
1693
- templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {
1694
-
1695
- var modalScope = (modalOptions.scope || $rootScope).$new();
1696
- modalScope.$close = modalInstance.close;
1697
- modalScope.$dismiss = modalInstance.dismiss;
1698
-
1699
- var ctrlInstance, ctrlLocals = {};
1700
- var resolveIter = 1;
1701
-
1702
- //controllers
1703
- if (modalOptions.controller) {
1704
- ctrlLocals.$scope = modalScope;
1705
- ctrlLocals.$modalInstance = modalInstance;
1706
- angular.forEach(modalOptions.resolve, function (value, key) {
1707
- ctrlLocals[key] = tplAndVars[resolveIter++];
1708
- });
1709
-
1710
- ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
1711
- }
1712
-
1713
- $modalStack.open(modalInstance, {
1714
- scope: modalScope,
1715
- deferred: modalResultDeferred,
1716
- content: tplAndVars[0],
1717
- backdrop: modalOptions.backdrop,
1718
- keyboard: modalOptions.keyboard,
1719
- windowClass: modalOptions.windowClass
1720
- });
1721
-
1722
- }, function resolveError(reason) {
1723
- modalResultDeferred.reject(reason);
1724
- });
1725
-
1726
- templateAndResolvePromise.then(function () {
1727
- modalOpenedDeferred.resolve(true);
1728
- }, function () {
1729
- modalOpenedDeferred.reject(false);
1730
- });
1731
-
1732
- return modalInstance;
1733
- };
1734
-
1735
- return $modal;
1736
- }]
1737
- };
1738
-
1739
- return $modalProvider;
1740
- });
1741
-
1742
- angular.module('ui.bootstrap.pagination', [])
1743
-
1744
- .controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) {
1745
- var self = this,
1746
- setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
1747
-
1748
- this.init = function(defaultItemsPerPage) {
1749
- if ($attrs.itemsPerPage) {
1750
- $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {
1751
- self.itemsPerPage = parseInt(value, 10);
1752
- $scope.totalPages = self.calculateTotalPages();
1753
- });
1754
- } else {
1755
- this.itemsPerPage = defaultItemsPerPage;
1756
- }
1757
- };
1758
-
1759
- this.noPrevious = function() {
1760
- return this.page === 1;
1761
- };
1762
- this.noNext = function() {
1763
- return this.page === $scope.totalPages;
1764
- };
1765
-
1766
- this.isActive = function(page) {
1767
- return this.page === page;
1768
- };
1769
-
1770
- this.calculateTotalPages = function() {
1771
- var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);
1772
- return Math.max(totalPages || 0, 1);
1773
- };
1774
-
1775
- this.getAttributeValue = function(attribute, defaultValue, interpolate) {
1776
- return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue;
1777
- };
1778
-
1779
- this.render = function() {
1780
- this.page = parseInt($scope.page, 10) || 1;
1781
- if (this.page > 0 && this.page <= $scope.totalPages) {
1782
- $scope.pages = this.getPages(this.page, $scope.totalPages);
1783
- }
1784
- };
1785
-
1786
- $scope.selectPage = function(page) {
1787
- if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) {
1788
- $scope.page = page;
1789
- $scope.onSelectPage({ page: page });
1790
- }
1791
- };
1792
-
1793
- $scope.$watch('page', function() {
1794
- self.render();
1795
- });
1796
-
1797
- $scope.$watch('totalItems', function() {
1798
- $scope.totalPages = self.calculateTotalPages();
1799
- });
1800
-
1801
- $scope.$watch('totalPages', function(value) {
1802
- setNumPages($scope.$parent, value); // Readonly variable
1803
-
1804
- if ( self.page > value ) {
1805
- $scope.selectPage(value);
1806
- } else {
1807
- self.render();
1808
- }
1809
- });
1810
- }])
1811
-
1812
- .constant('paginationConfig', {
1813
- itemsPerPage: 10,
1814
- boundaryLinks: false,
1815
- directionLinks: true,
1816
- firstText: 'First',
1817
- previousText: 'Previous',
1818
- nextText: 'Next',
1819
- lastText: 'Last',
1820
- rotate: true
1821
- })
1822
-
1823
- .directive('pagination', ['$parse', 'paginationConfig', function($parse, config) {
1824
- return {
1825
- restrict: 'EA',
1826
- scope: {
1827
- page: '=',
1828
- totalItems: '=',
1829
- onSelectPage:' &'
1830
- },
1831
- controller: 'PaginationController',
1832
- templateUrl: 'template/pagination/pagination.html',
1833
- replace: true,
1834
- link: function(scope, element, attrs, paginationCtrl) {
1835
-
1836
- // Setup configuration parameters
1837
- var maxSize,
1838
- boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ),
1839
- directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ),
1840
- firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true),
1841
- previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true),
1842
- nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true),
1843
- lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true),
1844
- rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate);
1845
-
1846
- paginationCtrl.init(config.itemsPerPage);
1847
-
1848
- if (attrs.maxSize) {
1849
- scope.$parent.$watch($parse(attrs.maxSize), function(value) {
1850
- maxSize = parseInt(value, 10);
1851
- paginationCtrl.render();
1852
- });
1853
- }
1854
-
1855
- // Create page object used in template
1856
- function makePage(number, text, isActive, isDisabled) {
1857
- return {
1858
- number: number,
1859
- text: text,
1860
- active: isActive,
1861
- disabled: isDisabled
1862
- };
1863
- }
1864
-
1865
- paginationCtrl.getPages = function(currentPage, totalPages) {
1866
- var pages = [];
1867
-
1868
- // Default page limits
1869
- var startPage = 1, endPage = totalPages;
1870
- var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages );
1871
-
1872
- // recompute if maxSize
1873
- if ( isMaxSized ) {
1874
- if ( rotate ) {
1875
- // Current page is displayed in the middle of the visible ones
1876
- startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);
1877
- endPage = startPage + maxSize - 1;
1878
-
1879
- // Adjust if limit is exceeded
1880
- if (endPage > totalPages) {
1881
- endPage = totalPages;
1882
- startPage = endPage - maxSize + 1;
1883
- }
1884
- } else {
1885
- // Visible pages are paginated with maxSize
1886
- startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;
1887
-
1888
- // Adjust last page if limit is exceeded
1889
- endPage = Math.min(startPage + maxSize - 1, totalPages);
1890
- }
1891
- }
1892
-
1893
- // Add page number links
1894
- for (var number = startPage; number <= endPage; number++) {
1895
- var page = makePage(number, number, paginationCtrl.isActive(number), false);
1896
- pages.push(page);
1897
- }
1898
-
1899
- // Add links to move between page sets
1900
- if ( isMaxSized && ! rotate ) {
1901
- if ( startPage > 1 ) {
1902
- var previousPageSet = makePage(startPage - 1, '...', false, false);
1903
- pages.unshift(previousPageSet);
1904
- }
1905
-
1906
- if ( endPage < totalPages ) {
1907
- var nextPageSet = makePage(endPage + 1, '...', false, false);
1908
- pages.push(nextPageSet);
1909
- }
1910
- }
1911
-
1912
- // Add previous & next links
1913
- if (directionLinks) {
1914
- var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious());
1915
- pages.unshift(previousPage);
1916
-
1917
- var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext());
1918
- pages.push(nextPage);
1919
- }
1920
-
1921
- // Add first & last links
1922
- if (boundaryLinks) {
1923
- var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious());
1924
- pages.unshift(firstPage);
1925
-
1926
- var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext());
1927
- pages.push(lastPage);
1928
- }
1929
-
1930
- return pages;
1931
- };
1932
- }
1933
- };
1934
- }])
1935
-
1936
- .constant('pagerConfig', {
1937
- itemsPerPage: 10,
1938
- previousText: '« Previous',
1939
- nextText: 'Next »',
1940
- align: true
1941
- })
1942
-
1943
- .directive('pager', ['pagerConfig', function(config) {
1944
- return {
1945
- restrict: 'EA',
1946
- scope: {
1947
- page: '=',
1948
- totalItems: '=',
1949
- onSelectPage:' &'
1950
- },
1951
- controller: 'PaginationController',
1952
- templateUrl: 'template/pagination/pager.html',
1953
- replace: true,
1954
- link: function(scope, element, attrs, paginationCtrl) {
1955
-
1956
- // Setup configuration parameters
1957
- var previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true),
1958
- nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true),
1959
- align = paginationCtrl.getAttributeValue(attrs.align, config.align);
1960
-
1961
- paginationCtrl.init(config.itemsPerPage);
1962
-
1963
- // Create page object used in template
1964
- function makePage(number, text, isDisabled, isPrevious, isNext) {
1965
- return {
1966
- number: number,
1967
- text: text,
1968
- disabled: isDisabled,
1969
- previous: ( align && isPrevious ),
1970
- next: ( align && isNext )
1971
- };
1972
- }
1973
-
1974
- paginationCtrl.getPages = function(currentPage) {
1975
- return [
1976
- makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false),
1977
- makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true)
1978
- ];
1979
- };
1980
- }
1981
- };
1982
- }]);
1983
-
1984
- /**
1985
- * The following features are still outstanding: animation as a
1986
- * function, placement as a function, inside, support for more triggers than
1987
- * just mouse enter/leave, html tooltips, and selector delegation.
1988
- */
1989
- angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] )
1990
-
1991
- /**
1992
- * The $tooltip service creates tooltip- and popover-like directives as well as
1993
- * houses global options for them.
1994
- */
1995
- .provider( '$tooltip', function () {
1996
- // The default options tooltip and popover.
1997
- var defaultOptions = {
1998
- placement: 'top',
1999
- animation: true,
2000
- popupDelay: 0
2001
- };
2002
-
2003
- // Default hide triggers for each show trigger
2004
- var triggerMap = {
2005
- 'mouseenter': 'mouseleave',
2006
- 'click': 'click',
2007
- 'focus': 'blur'
2008
- };
2009
-
2010
- // The options specified to the provider globally.
2011
- var globalOptions = {};
2012
-
2013
- /**
2014
- * `options({})` allows global configuration of all tooltips in the
2015
- * application.
2016
- *
2017
- * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
2018
- * // place tooltips left instead of top by default
2019
- * $tooltipProvider.options( { placement: 'left' } );
2020
- * });
2021
- */
2022
- this.options = function( value ) {
2023
- angular.extend( globalOptions, value );
2024
- };
2025
-
2026
- /**
2027
- * This allows you to extend the set of trigger mappings available. E.g.:
2028
- *
2029
- * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
2030
- */
2031
- this.setTriggers = function setTriggers ( triggers ) {
2032
- angular.extend( triggerMap, triggers );
2033
- };
2034
-
2035
- /**
2036
- * This is a helper function for translating camel-case to snake-case.
2037
- */
2038
- function snake_case(name){
2039
- var regexp = /[A-Z]/g;
2040
- var separator = '-';
2041
- return name.replace(regexp, function(letter, pos) {
2042
- return (pos ? separator : '') + letter.toLowerCase();
2043
- });
2044
- }
2045
-
2046
- /**
2047
- * Returns the actual instance of the $tooltip service.
2048
- * TODO support multiple triggers
2049
- */
2050
- this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) {
2051
- return function $tooltip ( type, prefix, defaultTriggerShow ) {
2052
- var options = angular.extend( {}, defaultOptions, globalOptions );
2053
-
2054
- /**
2055
- * Returns an object of show and hide triggers.
2056
- *
2057
- * If a trigger is supplied,
2058
- * it is used to show the tooltip; otherwise, it will use the `trigger`
2059
- * option passed to the `$tooltipProvider.options` method; else it will
2060
- * default to the trigger supplied to this directive factory.
2061
- *
2062
- * The hide trigger is based on the show trigger. If the `trigger` option
2063
- * was passed to the `$tooltipProvider.options` method, it will use the
2064
- * mapped trigger from `triggerMap` or the passed trigger if the map is
2065
- * undefined; otherwise, it uses the `triggerMap` value of the show
2066
- * trigger; else it will just use the show trigger.
2067
- */
2068
- function getTriggers ( trigger ) {
2069
- var show = trigger || options.trigger || defaultTriggerShow;
2070
- var hide = triggerMap[show] || show;
2071
- return {
2072
- show: show,
2073
- hide: hide
2074
- };
2075
- }
2076
-
2077
- var directiveName = snake_case( type );
2078
-
2079
- var startSym = $interpolate.startSymbol();
2080
- var endSym = $interpolate.endSymbol();
2081
- var template =
2082
- '<div '+ directiveName +'-popup '+
2083
- 'title="'+startSym+'tt_title'+endSym+'" '+
2084
- 'content="'+startSym+'tt_content'+endSym+'" '+
2085
- 'placement="'+startSym+'tt_placement'+endSym+'" '+
2086
- 'animation="tt_animation" '+
2087
- 'is-open="tt_isOpen"'+
2088
- '>'+
2089
- '</div>';
2090
-
2091
- return {
2092
- restrict: 'EA',
2093
- scope: true,
2094
- compile: function (tElem, tAttrs) {
2095
- var tooltipLinker = $compile( template );
2096
-
2097
- return function link ( scope, element, attrs ) {
2098
- var tooltip;
2099
- var transitionTimeout;
2100
- var popupTimeout;
2101
- var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
2102
- var triggers = getTriggers( undefined );
2103
- var hasRegisteredTriggers = false;
2104
- var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
2105
-
2106
- var positionTooltip = function (){
2107
- var position,
2108
- ttWidth,
2109
- ttHeight,
2110
- ttPosition;
2111
- // Get the position of the directive element.
2112
- position = appendToBody ? $position.offset( element ) : $position.position( element );
2113
-
2114
- // Get the height and width of the tooltip so we can center it.
2115
- ttWidth = tooltip.prop( 'offsetWidth' );
2116
- ttHeight = tooltip.prop( 'offsetHeight' );
2117
-
2118
- // Calculate the tooltip's top and left coordinates to center it with
2119
- // this directive.
2120
- switch ( scope.tt_placement ) {
2121
- case 'right':
2122
- ttPosition = {
2123
- top: position.top + position.height / 2 - ttHeight / 2,
2124
- left: position.left + position.width
2125
- };
2126
- break;
2127
- case 'bottom':
2128
- ttPosition = {
2129
- top: position.top + position.height,
2130
- left: position.left + position.width / 2 - ttWidth / 2
2131
- };
2132
- break;
2133
- case 'left':
2134
- ttPosition = {
2135
- top: position.top + position.height / 2 - ttHeight / 2,
2136
- left: position.left - ttWidth
2137
- };
2138
- break;
2139
- default:
2140
- ttPosition = {
2141
- top: position.top - ttHeight,
2142
- left: position.left + position.width / 2 - ttWidth / 2
2143
- };
2144
- break;
2145
- }
2146
-
2147
- ttPosition.top += 'px';
2148
- ttPosition.left += 'px';
2149
-
2150
- // Now set the calculated positioning.
2151
- tooltip.css( ttPosition );
2152
-
2153
- };
2154
-
2155
- // By default, the tooltip is not open.
2156
- // TODO add ability to start tooltip opened
2157
- scope.tt_isOpen = false;
2158
-
2159
- function toggleTooltipBind () {
2160
- if ( ! scope.tt_isOpen ) {
2161
- showTooltipBind();
2162
- } else {
2163
- hideTooltipBind();
2164
- }
2165
- }
2166
-
2167
- // Show the tooltip with delay if specified, otherwise show it immediately
2168
- function showTooltipBind() {
2169
- if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
2170
- return;
2171
- }
2172
- if ( scope.tt_popupDelay ) {
2173
- popupTimeout = $timeout( show, scope.tt_popupDelay, false );
2174
- popupTimeout.then(function(reposition){reposition();});
2175
- } else {
2176
- show()();
2177
- }
2178
- }
2179
-
2180
- function hideTooltipBind () {
2181
- scope.$apply(function () {
2182
- hide();
2183
- });
2184
- }
2185
-
2186
- // Show the tooltip popup element.
2187
- function show() {
2188
-
2189
-
2190
- // Don't show empty tooltips.
2191
- if ( ! scope.tt_content ) {
2192
- return angular.noop;
2193
- }
2194
-
2195
- createTooltip();
2196
-
2197
- // If there is a pending remove transition, we must cancel it, lest the
2198
- // tooltip be mysteriously removed.
2199
- if ( transitionTimeout ) {
2200
- $timeout.cancel( transitionTimeout );
2201
- }
2202
-
2203
- // Set the initial positioning.
2204
- tooltip.css({ top: 0, left: 0, display: 'block' });
2205
-
2206
- // Now we add it to the DOM because need some info about it. But it's not
2207
- // visible yet anyway.
2208
- if ( appendToBody ) {
2209
- $document.find( 'body' ).append( tooltip );
2210
- } else {
2211
- element.after( tooltip );
2212
- }
2213
-
2214
- positionTooltip();
2215
-
2216
- // And show the tooltip.
2217
- scope.tt_isOpen = true;
2218
- scope.$digest(); // digest required as $apply is not called
2219
-
2220
- // Return positioning function as promise callback for correct
2221
- // positioning after draw.
2222
- return positionTooltip;
2223
- }
2224
-
2225
- // Hide the tooltip popup element.
2226
- function hide() {
2227
- // First things first: we don't show it anymore.
2228
- scope.tt_isOpen = false;
2229
-
2230
- //if tooltip is going to be shown after delay, we must cancel this
2231
- $timeout.cancel( popupTimeout );
2232
-
2233
- // And now we remove it from the DOM. However, if we have animation, we
2234
- // need to wait for it to expire beforehand.
2235
- // FIXME: this is a placeholder for a port of the transitions library.
2236
- if ( scope.tt_animation ) {
2237
- transitionTimeout = $timeout(removeTooltip, 500);
2238
- } else {
2239
- removeTooltip();
2240
- }
2241
- }
2242
-
2243
- function createTooltip() {
2244
- // There can only be one tooltip element per directive shown at once.
2245
- if (tooltip) {
2246
- removeTooltip();
2247
- }
2248
- tooltip = tooltipLinker(scope, function () {});
2249
-
2250
- // Get contents rendered into the tooltip
2251
- scope.$digest();
2252
- }
2253
-
2254
- function removeTooltip() {
2255
- if (tooltip) {
2256
- tooltip.remove();
2257
- tooltip = null;
2258
- }
2259
- }
2260
-
2261
- /**
2262
- * Observe the relevant attributes.
2263
- */
2264
- attrs.$observe( type, function ( val ) {
2265
- scope.tt_content = val;
2266
-
2267
- if (!val && scope.tt_isOpen ) {
2268
- hide();
2269
- }
2270
- });
2271
-
2272
- attrs.$observe( prefix+'Title', function ( val ) {
2273
- scope.tt_title = val;
2274
- });
2275
-
2276
- attrs.$observe( prefix+'Placement', function ( val ) {
2277
- scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
2278
- });
2279
-
2280
- attrs.$observe( prefix+'PopupDelay', function ( val ) {
2281
- var delay = parseInt( val, 10 );
2282
- scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
2283
- });
2284
-
2285
- var unregisterTriggers = function() {
2286
- if (hasRegisteredTriggers) {
2287
- element.unbind( triggers.show, showTooltipBind );
2288
- element.unbind( triggers.hide, hideTooltipBind );
2289
- }
2290
- };
2291
-
2292
- attrs.$observe( prefix+'Trigger', function ( val ) {
2293
- unregisterTriggers();
2294
-
2295
- triggers = getTriggers( val );
2296
-
2297
- if ( triggers.show === triggers.hide ) {
2298
- element.bind( triggers.show, toggleTooltipBind );
2299
- } else {
2300
- element.bind( triggers.show, showTooltipBind );
2301
- element.bind( triggers.hide, hideTooltipBind );
2302
- }
2303
-
2304
- hasRegisteredTriggers = true;
2305
- });
2306
-
2307
- var animation = scope.$eval(attrs[prefix + 'Animation']);
2308
- scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
2309
-
2310
- attrs.$observe( prefix+'AppendToBody', function ( val ) {
2311
- appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
2312
- });
2313
-
2314
- // if a tooltip is attached to <body> we need to remove it on
2315
- // location change as its parent scope will probably not be destroyed
2316
- // by the change.
2317
- if ( appendToBody ) {
2318
- scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
2319
- if ( scope.tt_isOpen ) {
2320
- hide();
2321
- }
2322
- });
2323
- }
2324
-
2325
- // Make sure tooltip is destroyed and removed.
2326
- scope.$on('$destroy', function onDestroyTooltip() {
2327
- $timeout.cancel( transitionTimeout );
2328
- $timeout.cancel( popupTimeout );
2329
- unregisterTriggers();
2330
- removeTooltip();
2331
- });
2332
- };
2333
- }
2334
- };
2335
- };
2336
- }];
2337
- })
2338
-
2339
- .directive( 'tooltipPopup', function () {
2340
- return {
2341
- restrict: 'EA',
2342
- replace: true,
2343
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
2344
- templateUrl: 'template/tooltip/tooltip-popup.html'
2345
- };
2346
- })
2347
-
2348
- .directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {
2349
- return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );
2350
- }])
2351
-
2352
- .directive( 'tooltipHtmlUnsafePopup', function () {
2353
- return {
2354
- restrict: 'EA',
2355
- replace: true,
2356
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
2357
- templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
2358
- };
2359
- })
2360
-
2361
- .directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
2362
- return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
2363
- }]);
2364
-
2365
- /**
2366
- * The following features are still outstanding: popup delay, animation as a
2367
- * function, placement as a function, inside, support for more triggers than
2368
- * just mouse enter/leave, html popovers, and selector delegatation.
2369
- */
2370
- angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )
2371
-
2372
- .directive( 'popoverPopup', function () {
2373
- return {
2374
- restrict: 'EA',
2375
- replace: true,
2376
- scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
2377
- templateUrl: 'template/popover/popover.html'
2378
- };
2379
- })
2380
-
2381
- .directive( 'popover', [ '$tooltip', function ( $tooltip ) {
2382
- return $tooltip( 'popover', 'popover', 'click' );
2383
- }]);
2384
-
2385
- angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])
2386
-
2387
- .constant('progressConfig', {
2388
- animate: true,
2389
- max: 100
2390
- })
2391
-
2392
- .controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) {
2393
- var self = this,
2394
- bars = [],
2395
- max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max,
2396
- animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
2397
-
2398
- this.addBar = function(bar, element) {
2399
- var oldValue = 0, index = bar.$parent.$index;
2400
- if ( angular.isDefined(index) && bars[index] ) {
2401
- oldValue = bars[index].value;
2402
- }
2403
- bars.push(bar);
2404
-
2405
- this.update(element, bar.value, oldValue);
2406
-
2407
- bar.$watch('value', function(value, oldValue) {
2408
- if (value !== oldValue) {
2409
- self.update(element, value, oldValue);
2410
- }
2411
- });
2412
-
2413
- bar.$on('$destroy', function() {
2414
- self.removeBar(bar);
2415
- });
2416
- };
2417
-
2418
- // Update bar element width
2419
- this.update = function(element, newValue, oldValue) {
2420
- var percent = this.getPercentage(newValue);
2421
-
2422
- if (animate) {
2423
- element.css('width', this.getPercentage(oldValue) + '%');
2424
- $transition(element, {width: percent + '%'});
2425
- } else {
2426
- element.css({'transition': 'none', 'width': percent + '%'});
2427
- }
2428
- };
2429
-
2430
- this.removeBar = function(bar) {
2431
- bars.splice(bars.indexOf(bar), 1);
2432
- };
2433
-
2434
- this.getPercentage = function(value) {
2435
- return Math.round(100 * value / max);
2436
- };
2437
- }])
2438
-
2439
- .directive('progress', function() {
2440
- return {
2441
- restrict: 'EA',
2442
- replace: true,
2443
- transclude: true,
2444
- controller: 'ProgressController',
2445
- require: 'progress',
2446
- scope: {},
2447
- template: '<div class="progress" ng-transclude></div>'
2448
- //templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2
2449
- };
2450
- })
2451
-
2452
- .directive('bar', function() {
2453
- return {
2454
- restrict: 'EA',
2455
- replace: true,
2456
- transclude: true,
2457
- require: '^progress',
2458
- scope: {
2459
- value: '=',
2460
- type: '@'
2461
- },
2462
- templateUrl: 'template/progressbar/bar.html',
2463
- link: function(scope, element, attrs, progressCtrl) {
2464
- progressCtrl.addBar(scope, element);
2465
- }
2466
- };
2467
- })
2468
-
2469
- .directive('progressbar', function() {
2470
- return {
2471
- restrict: 'EA',
2472
- replace: true,
2473
- transclude: true,
2474
- controller: 'ProgressController',
2475
- scope: {
2476
- value: '=',
2477
- type: '@'
2478
- },
2479
- templateUrl: 'template/progressbar/progressbar.html',
2480
- link: function(scope, element, attrs, progressCtrl) {
2481
- progressCtrl.addBar(scope, angular.element(element.children()[0]));
2482
- }
2483
- };
2484
- });
2485
- angular.module('ui.bootstrap.rating', [])
2486
-
2487
- .constant('ratingConfig', {
2488
- max: 5,
2489
- stateOn: null,
2490
- stateOff: null
2491
- })
2492
-
2493
- .controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) {
2494
-
2495
- this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max;
2496
- this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
2497
- this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
2498
-
2499
- this.createRateObjects = function(states) {
2500
- var defaultOptions = {
2501
- stateOn: this.stateOn,
2502
- stateOff: this.stateOff
2503
- };
2504
-
2505
- for (var i = 0, n = states.length; i < n; i++) {
2506
- states[i] = angular.extend({ index: i }, defaultOptions, states[i]);
2507
- }
2508
- return states;
2509
- };
2510
-
2511
- // Get objects used in template
2512
- $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange));
2513
-
2514
- $scope.rate = function(value) {
2515
- if ( $scope.value !== value && !$scope.readonly ) {
2516
- $scope.value = value;
2517
- }
2518
- };
2519
-
2520
- $scope.enter = function(value) {
2521
- if ( ! $scope.readonly ) {
2522
- $scope.val = value;
2523
- }
2524
- $scope.onHover({value: value});
2525
- };
2526
-
2527
- $scope.reset = function() {
2528
- $scope.val = angular.copy($scope.value);
2529
- $scope.onLeave();
2530
- };
2531
-
2532
- $scope.$watch('value', function(value) {
2533
- $scope.val = value;
2534
- });
2535
-
2536
- $scope.readonly = false;
2537
- if ($attrs.readonly) {
2538
- $scope.$parent.$watch($parse($attrs.readonly), function(value) {
2539
- $scope.readonly = !!value;
2540
- });
2541
- }
2542
- }])
2543
-
2544
- .directive('rating', function() {
2545
- return {
2546
- restrict: 'EA',
2547
- scope: {
2548
- value: '=',
2549
- onHover: '&',
2550
- onLeave: '&'
2551
- },
2552
- controller: 'RatingController',
2553
- templateUrl: 'template/rating/rating.html',
2554
- replace: true
2555
- };
2556
- });
2557
-
2558
- /**
2559
- * @ngdoc overview
2560
- * @name ui.bootstrap.tabs
2561
- *
2562
- * @description
2563
- * AngularJS version of the tabs directive.
2564
- */
2565
-
2566
- angular.module('ui.bootstrap.tabs', [])
2567
-
2568
- .controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
2569
- var ctrl = this,
2570
- tabs = ctrl.tabs = $scope.tabs = [];
2571
-
2572
- ctrl.select = function(tab) {
2573
- angular.forEach(tabs, function(tab) {
2574
- tab.active = false;
2575
- });
2576
- tab.active = true;
2577
- };
2578
-
2579
- ctrl.addTab = function addTab(tab) {
2580
- tabs.push(tab);
2581
- if (tabs.length === 1 || tab.active) {
2582
- ctrl.select(tab);
2583
- }
2584
- };
2585
-
2586
- ctrl.removeTab = function removeTab(tab) {
2587
- var index = tabs.indexOf(tab);
2588
- //Select a new tab if the tab to be removed is selected
2589
- if (tab.active && tabs.length > 1) {
2590
- //If this is the last tab, select the previous tab. else, the next tab.
2591
- var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;
2592
- ctrl.select(tabs[newActiveIndex]);
2593
- }
2594
- tabs.splice(index, 1);
2595
- };
2596
- }])
2597
-
2598
- /**
2599
- * @ngdoc directive
2600
- * @name ui.bootstrap.tabs.directive:tabset
2601
- * @restrict EA
2602
- *
2603
- * @description
2604
- * Tabset is the outer container for the tabs directive
2605
- *
2606
- * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.
2607
- * @param {boolean=} justified Whether or not to use justified styling for the tabs.
2608
- *
2609
- * @example
2610
- <example module="ui.bootstrap">
2611
- <file name="index.html">
2612
- <tabset>
2613
- <tab heading="Tab 1"><b>First</b> Content!</tab>
2614
- <tab heading="Tab 2"><i>Second</i> Content!</tab>
2615
- </tabset>
2616
- <hr />
2617
- <tabset vertical="true">
2618
- <tab heading="Vertical Tab 1"><b>First</b> Vertical Content!</tab>
2619
- <tab heading="Vertical Tab 2"><i>Second</i> Vertical Content!</tab>
2620
- </tabset>
2621
- <tabset justified="true">
2622
- <tab heading="Justified Tab 1"><b>First</b> Justified Content!</tab>
2623
- <tab heading="Justified Tab 2"><i>Second</i> Justified Content!</tab>
2624
- </tabset>
2625
- </file>
2626
- </example>
2627
- */
2628
- .directive('tabset', function() {
2629
- return {
2630
- restrict: 'EA',
2631
- transclude: true,
2632
- replace: true,
2633
- scope: {},
2634
- controller: 'TabsetController',
2635
- templateUrl: 'template/tabs/tabset.html',
2636
- link: function(scope, element, attrs) {
2637
- scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;
2638
- scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;
2639
- scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs';
2640
- }
2641
- };
2642
- })
2643
-
2644
- /**
2645
- * @ngdoc directive
2646
- * @name ui.bootstrap.tabs.directive:tab
2647
- * @restrict EA
2648
- *
2649
- * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.
2650
- * @param {string=} select An expression to evaluate when the tab is selected.
2651
- * @param {boolean=} active A binding, telling whether or not this tab is selected.
2652
- * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.
2653
- *
2654
- * @description
2655
- * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.
2656
- *
2657
- * @example
2658
- <example module="ui.bootstrap">
2659
- <file name="index.html">
2660
- <div ng-controller="TabsDemoCtrl">
2661
- <button class="btn btn-small" ng-click="items[0].active = true">
2662
- Select item 1, using active binding
2663
- </button>
2664
- <button class="btn btn-small" ng-click="items[1].disabled = !items[1].disabled">
2665
- Enable/disable item 2, using disabled binding
2666
- </button>
2667
- <br />
2668
- <tabset>
2669
- <tab heading="Tab 1">First Tab</tab>
2670
- <tab select="alertMe()">
2671
- <tab-heading><i class="icon-bell"></i> Alert me!</tab-heading>
2672
- Second Tab, with alert callback and html heading!
2673
- </tab>
2674
- <tab ng-repeat="item in items"
2675
- heading="{{item.title}}"
2676
- disabled="item.disabled"
2677
- active="item.active">
2678
- {{item.content}}
2679
- </tab>
2680
- </tabset>
2681
- </div>
2682
- </file>
2683
- <file name="script.js">
2684
- function TabsDemoCtrl($scope) {
2685
- $scope.items = [
2686
- { title:"Dynamic Title 1", content:"Dynamic Item 0" },
2687
- { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true }
2688
- ];
2689
-
2690
- $scope.alertMe = function() {
2691
- setTimeout(function() {
2692
- alert("You've selected the alert tab!");
2693
- });
2694
- };
2695
- };
2696
- </file>
2697
- </example>
2698
- */
2699
-
2700
- /**
2701
- * @ngdoc directive
2702
- * @name ui.bootstrap.tabs.directive:tabHeading
2703
- * @restrict EA
2704
- *
2705
- * @description
2706
- * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.
2707
- *
2708
- * @example
2709
- <example module="ui.bootstrap">
2710
- <file name="index.html">
2711
- <tabset>
2712
- <tab>
2713
- <tab-heading><b>HTML</b> in my titles?!</tab-heading>
2714
- And some content, too!
2715
- </tab>
2716
- <tab>
2717
- <tab-heading><i class="icon-heart"></i> Icon heading?!?</tab-heading>
2718
- That's right.
2719
- </tab>
2720
- </tabset>
2721
- </file>
2722
- </example>
2723
- */
2724
- .directive('tab', ['$parse', function($parse) {
2725
- return {
2726
- require: '^tabset',
2727
- restrict: 'EA',
2728
- replace: true,
2729
- templateUrl: 'template/tabs/tab.html',
2730
- transclude: true,
2731
- scope: {
2732
- heading: '@',
2733
- onSelect: '&select', //This callback is called in contentHeadingTransclude
2734
- //once it inserts the tab's content into the dom
2735
- onDeselect: '&deselect'
2736
- },
2737
- controller: function() {
2738
- //Empty controller so other directives can require being 'under' a tab
2739
- },
2740
- compile: function(elm, attrs, transclude) {
2741
- return function postLink(scope, elm, attrs, tabsetCtrl) {
2742
- var getActive, setActive;
2743
- if (attrs.active) {
2744
- getActive = $parse(attrs.active);
2745
- setActive = getActive.assign;
2746
- scope.$parent.$watch(getActive, function updateActive(value, oldVal) {
2747
- // Avoid re-initializing scope.active as it is already initialized
2748
- // below. (watcher is called async during init with value ===
2749
- // oldVal)
2750
- if (value !== oldVal) {
2751
- scope.active = !!value;
2752
- }
2753
- });
2754
- scope.active = getActive(scope.$parent);
2755
- } else {
2756
- setActive = getActive = angular.noop;
2757
- }
2758
-
2759
- scope.$watch('active', function(active) {
2760
- // Note this watcher also initializes and assigns scope.active to the
2761
- // attrs.active expression.
2762
- setActive(scope.$parent, active);
2763
- if (active) {
2764
- tabsetCtrl.select(scope);
2765
- scope.onSelect();
2766
- } else {
2767
- scope.onDeselect();
2768
- }
2769
- });
2770
-
2771
- scope.disabled = false;
2772
- if ( attrs.disabled ) {
2773
- scope.$parent.$watch($parse(attrs.disabled), function(value) {
2774
- scope.disabled = !! value;
2775
- });
2776
- }
2777
-
2778
- scope.select = function() {
2779
- if ( ! scope.disabled ) {
2780
- scope.active = true;
2781
- }
2782
- };
2783
-
2784
- tabsetCtrl.addTab(scope);
2785
- scope.$on('$destroy', function() {
2786
- tabsetCtrl.removeTab(scope);
2787
- });
2788
-
2789
-
2790
- //We need to transclude later, once the content container is ready.
2791
- //when this link happens, we're inside a tab heading.
2792
- scope.$transcludeFn = transclude;
2793
- };
2794
- }
2795
- };
2796
- }])
2797
-
2798
- .directive('tabHeadingTransclude', [function() {
2799
- return {
2800
- restrict: 'A',
2801
- require: '^tab',
2802
- link: function(scope, elm, attrs, tabCtrl) {
2803
- scope.$watch('headingElement', function updateHeadingElement(heading) {
2804
- if (heading) {
2805
- elm.html('');
2806
- elm.append(heading);
2807
- }
2808
- });
2809
- }
2810
- };
2811
- }])
2812
-
2813
- .directive('tabContentTransclude', function() {
2814
- return {
2815
- restrict: 'A',
2816
- require: '^tabset',
2817
- link: function(scope, elm, attrs) {
2818
- var tab = scope.$eval(attrs.tabContentTransclude);
2819
-
2820
- //Now our tab is ready to be transcluded: both the tab heading area
2821
- //and the tab content area are loaded. Transclude 'em both.
2822
- tab.$transcludeFn(tab.$parent, function(contents) {
2823
- angular.forEach(contents, function(node) {
2824
- if (isTabHeading(node)) {
2825
- //Let tabHeadingTransclude know.
2826
- tab.headingElement = node;
2827
- } else {
2828
- elm.append(node);
2829
- }
2830
- });
2831
- });
2832
- }
2833
- };
2834
- function isTabHeading(node) {
2835
- return node.tagName && (
2836
- node.hasAttribute('tab-heading') ||
2837
- node.hasAttribute('data-tab-heading') ||
2838
- node.tagName.toLowerCase() === 'tab-heading' ||
2839
- node.tagName.toLowerCase() === 'data-tab-heading'
2840
- );
2841
- }
2842
- })
2843
-
2844
- ;
2845
-
2846
- angular.module('ui.bootstrap.timepicker', [])
2847
-
2848
- .constant('timepickerConfig', {
2849
- hourStep: 1,
2850
- minuteStep: 1,
2851
- showMeridian: true,
2852
- meridians: null,
2853
- readonlyInput: false,
2854
- mousewheel: true
2855
- })
2856
-
2857
- .directive('timepicker', ['$parse', '$log', 'timepickerConfig', '$locale', function ($parse, $log, timepickerConfig, $locale) {
2858
- return {
2859
- restrict: 'EA',
2860
- require:'?^ngModel',
2861
- replace: true,
2862
- scope: {},
2863
- templateUrl: 'template/timepicker/timepicker.html',
2864
- link: function(scope, element, attrs, ngModel) {
2865
- if ( !ngModel ) {
2866
- return; // do nothing if no ng-model
2867
- }
2868
-
2869
- var selected = new Date(),
2870
- meridians = angular.isDefined(attrs.meridians) ? scope.$parent.$eval(attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;
2871
-
2872
- var hourStep = timepickerConfig.hourStep;
2873
- if (attrs.hourStep) {
2874
- scope.$parent.$watch($parse(attrs.hourStep), function(value) {
2875
- hourStep = parseInt(value, 10);
2876
- });
2877
- }
2878
-
2879
- var minuteStep = timepickerConfig.minuteStep;
2880
- if (attrs.minuteStep) {
2881
- scope.$parent.$watch($parse(attrs.minuteStep), function(value) {
2882
- minuteStep = parseInt(value, 10);
2883
- });
2884
- }
2885
-
2886
- // 12H / 24H mode
2887
- scope.showMeridian = timepickerConfig.showMeridian;
2888
- if (attrs.showMeridian) {
2889
- scope.$parent.$watch($parse(attrs.showMeridian), function(value) {
2890
- scope.showMeridian = !!value;
2891
-
2892
- if ( ngModel.$error.time ) {
2893
- // Evaluate from template
2894
- var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
2895
- if (angular.isDefined( hours ) && angular.isDefined( minutes )) {
2896
- selected.setHours( hours );
2897
- refresh();
2898
- }
2899
- } else {
2900
- updateTemplate();
2901
- }
2902
- });
2903
- }
2904
-
2905
- // Get scope.hours in 24H mode if valid
2906
- function getHoursFromTemplate ( ) {
2907
- var hours = parseInt( scope.hours, 10 );
2908
- var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);
2909
- if ( !valid ) {
2910
- return undefined;
2911
- }
2912
-
2913
- if ( scope.showMeridian ) {
2914
- if ( hours === 12 ) {
2915
- hours = 0;
2916
- }
2917
- if ( scope.meridian === meridians[1] ) {
2918
- hours = hours + 12;
2919
- }
2920
- }
2921
- return hours;
2922
- }
2923
-
2924
- function getMinutesFromTemplate() {
2925
- var minutes = parseInt(scope.minutes, 10);
2926
- return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined;
2927
- }
2928
-
2929
- function pad( value ) {
2930
- return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value;
2931
- }
2932
-
2933
- // Input elements
2934
- var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1);
2935
-
2936
- // Respond on mousewheel spin
2937
- var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel;
2938
- if ( mousewheel ) {
2939
-
2940
- var isScrollingUp = function(e) {
2941
- if (e.originalEvent) {
2942
- e = e.originalEvent;
2943
- }
2944
- //pick correct delta variable depending on event
2945
- var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;
2946
- return (e.detail || delta > 0);
2947
- };
2948
-
2949
- hoursInputEl.bind('mousewheel wheel', function(e) {
2950
- scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() );
2951
- e.preventDefault();
2952
- });
2953
-
2954
- minutesInputEl.bind('mousewheel wheel', function(e) {
2955
- scope.$apply( (isScrollingUp(e)) ? scope.incrementMinutes() : scope.decrementMinutes() );
2956
- e.preventDefault();
2957
- });
2958
- }
2959
-
2960
- scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput;
2961
- if ( ! scope.readonlyInput ) {
2962
-
2963
- var invalidate = function(invalidHours, invalidMinutes) {
2964
- ngModel.$setViewValue( null );
2965
- ngModel.$setValidity('time', false);
2966
- if (angular.isDefined(invalidHours)) {
2967
- scope.invalidHours = invalidHours;
2968
- }
2969
- if (angular.isDefined(invalidMinutes)) {
2970
- scope.invalidMinutes = invalidMinutes;
2971
- }
2972
- };
2973
-
2974
- scope.updateHours = function() {
2975
- var hours = getHoursFromTemplate();
2976
-
2977
- if ( angular.isDefined(hours) ) {
2978
- selected.setHours( hours );
2979
- refresh( 'h' );
2980
- } else {
2981
- invalidate(true);
2982
- }
2983
- };
2984
-
2985
- hoursInputEl.bind('blur', function(e) {
2986
- if ( !scope.validHours && scope.hours < 10) {
2987
- scope.$apply( function() {
2988
- scope.hours = pad( scope.hours );
2989
- });
2990
- }
2991
- });
2992
-
2993
- scope.updateMinutes = function() {
2994
- var minutes = getMinutesFromTemplate();
2995
-
2996
- if ( angular.isDefined(minutes) ) {
2997
- selected.setMinutes( minutes );
2998
- refresh( 'm' );
2999
- } else {
3000
- invalidate(undefined, true);
3001
- }
3002
- };
3003
-
3004
- minutesInputEl.bind('blur', function(e) {
3005
- if ( !scope.invalidMinutes && scope.minutes < 10 ) {
3006
- scope.$apply( function() {
3007
- scope.minutes = pad( scope.minutes );
3008
- });
3009
- }
3010
- });
3011
- } else {
3012
- scope.updateHours = angular.noop;
3013
- scope.updateMinutes = angular.noop;
3014
- }
3015
-
3016
- ngModel.$render = function() {
3017
- var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null;
3018
-
3019
- if ( isNaN(date) ) {
3020
- ngModel.$setValidity('time', false);
3021
- $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
3022
- } else {
3023
- if ( date ) {
3024
- selected = date;
3025
- }
3026
- makeValid();
3027
- updateTemplate();
3028
- }
3029
- };
3030
-
3031
- // Call internally when we know that model is valid.
3032
- function refresh( keyboardChange ) {
3033
- makeValid();
3034
- ngModel.$setViewValue( new Date(selected) );
3035
- updateTemplate( keyboardChange );
3036
- }
3037
-
3038
- function makeValid() {
3039
- ngModel.$setValidity('time', true);
3040
- scope.invalidHours = false;
3041
- scope.invalidMinutes = false;
3042
- }
3043
-
3044
- function updateTemplate( keyboardChange ) {
3045
- var hours = selected.getHours(), minutes = selected.getMinutes();
3046
-
3047
- if ( scope.showMeridian ) {
3048
- hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system
3049
- }
3050
- scope.hours = keyboardChange === 'h' ? hours : pad(hours);
3051
- scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes);
3052
- scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
3053
- }
3054
-
3055
- function addMinutes( minutes ) {
3056
- var dt = new Date( selected.getTime() + minutes * 60000 );
3057
- selected.setHours( dt.getHours(), dt.getMinutes() );
3058
- refresh();
3059
- }
3060
-
3061
- scope.incrementHours = function() {
3062
- addMinutes( hourStep * 60 );
3063
- };
3064
- scope.decrementHours = function() {
3065
- addMinutes( - hourStep * 60 );
3066
- };
3067
- scope.incrementMinutes = function() {
3068
- addMinutes( minuteStep );
3069
- };
3070
- scope.decrementMinutes = function() {
3071
- addMinutes( - minuteStep );
3072
- };
3073
- scope.toggleMeridian = function() {
3074
- addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) );
3075
- };
3076
- }
3077
- };
3078
- }]);
3079
-
3080
- angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])
3081
-
3082
- /**
3083
- * A helper service that can parse typeahead's syntax (string provided by users)
3084
- * Extracted to a separate service for ease of unit testing
3085
- */
3086
- .factory('typeaheadParser', ['$parse', function ($parse) {
3087
-
3088
- // 00000111000000000000022200000000000000003333333333333330000000000044000
3089
- var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;
3090
-
3091
- return {
3092
- parse:function (input) {
3093
-
3094
- var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source;
3095
- if (!match) {
3096
- throw new Error(
3097
- "Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" +
3098
- " but got '" + input + "'.");
3099
- }
3100
-
3101
- return {
3102
- itemName:match[3],
3103
- source:$parse(match[4]),
3104
- viewMapper:$parse(match[2] || match[1]),
3105
- modelMapper:$parse(match[1])
3106
- };
3107
- }
3108
- };
3109
- }])
3110
-
3111
- .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',
3112
- function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {
3113
-
3114
- var HOT_KEYS = [9, 13, 27, 38, 40];
3115
-
3116
- return {
3117
- require:'ngModel',
3118
- link:function (originalScope, element, attrs, modelCtrl) {
3119
-
3120
- //SUPPORTED ATTRIBUTES (OPTIONS)
3121
-
3122
- //minimal no of characters that needs to be entered before typeahead kicks-in
3123
- var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
3124
-
3125
- //minimal wait time after last character typed before typehead kicks-in
3126
- var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
3127
-
3128
- //should it restrict model values to the ones selected from the popup only?
3129
- var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
3130
-
3131
- //binding to a variable that indicates if matches are being retrieved asynchronously
3132
- var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
3133
-
3134
- //a callback executed when a match is selected
3135
- var onSelectCallback = $parse(attrs.typeaheadOnSelect);
3136
-
3137
- var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
3138
-
3139
- var appendToBody = attrs.typeaheadAppendToBody ? $parse(attrs.typeaheadAppendToBody) : false;
3140
-
3141
- //INTERNAL VARIABLES
3142
-
3143
- //model setter executed upon match selection
3144
- var $setModelValue = $parse(attrs.ngModel).assign;
3145
-
3146
- //expressions used by typeahead
3147
- var parserResult = typeaheadParser.parse(attrs.typeahead);
3148
-
3149
- var hasFocus;
3150
-
3151
- //pop-up element used to display matches
3152
- var popUpEl = angular.element('<div typeahead-popup></div>');
3153
- popUpEl.attr({
3154
- matches: 'matches',
3155
- active: 'activeIdx',
3156
- select: 'select(activeIdx)',
3157
- query: 'query',
3158
- position: 'position'
3159
- });
3160
- //custom item template
3161
- if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
3162
- popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
3163
- }
3164
-
3165
- //create a child scope for the typeahead directive so we are not polluting original scope
3166
- //with typeahead-specific data (matches, query etc.)
3167
- var scope = originalScope.$new();
3168
- originalScope.$on('$destroy', function(){
3169
- scope.$destroy();
3170
- });
3171
-
3172
- var resetMatches = function() {
3173
- scope.matches = [];
3174
- scope.activeIdx = -1;
3175
- };
3176
-
3177
- var getMatchesAsync = function(inputValue) {
3178
-
3179
- var locals = {$viewValue: inputValue};
3180
- isLoadingSetter(originalScope, true);
3181
- $q.when(parserResult.source(originalScope, locals)).then(function(matches) {
3182
-
3183
- //it might happen that several async queries were in progress if a user were typing fast
3184
- //but we are interested only in responses that correspond to the current view value
3185
- if (inputValue === modelCtrl.$viewValue && hasFocus) {
3186
- if (matches.length > 0) {
3187
-
3188
- scope.activeIdx = 0;
3189
- scope.matches.length = 0;
3190
-
3191
- //transform labels
3192
- for(var i=0; i<matches.length; i++) {
3193
- locals[parserResult.itemName] = matches[i];
3194
- scope.matches.push({
3195
- label: parserResult.viewMapper(scope, locals),
3196
- model: matches[i]
3197
- });
3198
- }
3199
-
3200
- scope.query = inputValue;
3201
- //position pop-up with matches - we need to re-calculate its position each time we are opening a window
3202
- //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
3203
- //due to other elements being rendered
3204
- scope.position = appendToBody ? $position.offset(element) : $position.position(element);
3205
- scope.position.top = scope.position.top + element.prop('offsetHeight');
3206
-
3207
- } else {
3208
- resetMatches();
3209
- }
3210
- isLoadingSetter(originalScope, false);
3211
- }
3212
- }, function(){
3213
- resetMatches();
3214
- isLoadingSetter(originalScope, false);
3215
- });
3216
- };
3217
-
3218
- resetMatches();
3219
-
3220
- //we need to propagate user's query so we can higlight matches
3221
- scope.query = undefined;
3222
-
3223
- //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
3224
- var timeoutPromise;
3225
-
3226
- //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
3227
- //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
3228
- modelCtrl.$parsers.unshift(function (inputValue) {
3229
-
3230
- hasFocus = true;
3231
-
3232
- if (inputValue && inputValue.length >= minSearch) {
3233
- if (waitTime > 0) {
3234
- if (timeoutPromise) {
3235
- $timeout.cancel(timeoutPromise);//cancel previous timeout
3236
- }
3237
- timeoutPromise = $timeout(function () {
3238
- getMatchesAsync(inputValue);
3239
- }, waitTime);
3240
- } else {
3241
- getMatchesAsync(inputValue);
3242
- }
3243
- } else {
3244
- isLoadingSetter(originalScope, false);
3245
- resetMatches();
3246
- }
3247
-
3248
- if (isEditable) {
3249
- return inputValue;
3250
- } else {
3251
- if (!inputValue) {
3252
- // Reset in case user had typed something previously.
3253
- modelCtrl.$setValidity('editable', true);
3254
- return inputValue;
3255
- } else {
3256
- modelCtrl.$setValidity('editable', false);
3257
- return undefined;
3258
- }
3259
- }
3260
- });
3261
-
3262
- modelCtrl.$formatters.push(function (modelValue) {
3263
-
3264
- var candidateViewValue, emptyViewValue;
3265
- var locals = {};
3266
-
3267
- if (inputFormatter) {
3268
-
3269
- locals['$model'] = modelValue;
3270
- return inputFormatter(originalScope, locals);
3271
-
3272
- } else {
3273
-
3274
- //it might happen that we don't have enough info to properly render input value
3275
- //we need to check for this situation and simply return model value if we can't apply custom formatting
3276
- locals[parserResult.itemName] = modelValue;
3277
- candidateViewValue = parserResult.viewMapper(originalScope, locals);
3278
- locals[parserResult.itemName] = undefined;
3279
- emptyViewValue = parserResult.viewMapper(originalScope, locals);
3280
-
3281
- return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
3282
- }
3283
- });
3284
-
3285
- scope.select = function (activeIdx) {
3286
- //called from within the $digest() cycle
3287
- var locals = {};
3288
- var model, item;
3289
-
3290
- locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
3291
- model = parserResult.modelMapper(originalScope, locals);
3292
- $setModelValue(originalScope, model);
3293
- modelCtrl.$setValidity('editable', true);
3294
-
3295
- onSelectCallback(originalScope, {
3296
- $item: item,
3297
- $model: model,
3298
- $label: parserResult.viewMapper(originalScope, locals)
3299
- });
3300
-
3301
- resetMatches();
3302
-
3303
- //return focus to the input element if a mach was selected via a mouse click event
3304
- element[0].focus();
3305
- };
3306
-
3307
- //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
3308
- element.bind('keydown', function (evt) {
3309
-
3310
- //typeahead is open and an "interesting" key was pressed
3311
- if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
3312
- return;
3313
- }
3314
-
3315
- evt.preventDefault();
3316
-
3317
- if (evt.which === 40) {
3318
- scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
3319
- scope.$digest();
3320
-
3321
- } else if (evt.which === 38) {
3322
- scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1;
3323
- scope.$digest();
3324
-
3325
- } else if (evt.which === 13 || evt.which === 9) {
3326
- scope.$apply(function () {
3327
- scope.select(scope.activeIdx);
3328
- });
3329
-
3330
- } else if (evt.which === 27) {
3331
- evt.stopPropagation();
3332
-
3333
- resetMatches();
3334
- scope.$digest();
3335
- }
3336
- });
3337
-
3338
- element.bind('blur', function (evt) {
3339
- hasFocus = false;
3340
- });
3341
-
3342
- // Keep reference to click handler to unbind it.
3343
- var dismissClickHandler = function (evt) {
3344
- if (element[0] !== evt.target) {
3345
- resetMatches();
3346
- scope.$digest();
3347
- }
3348
- };
3349
-
3350
- $document.bind('click', dismissClickHandler);
3351
-
3352
- originalScope.$on('$destroy', function(){
3353
- $document.unbind('click', dismissClickHandler);
3354
- });
3355
-
3356
- var $popup = $compile(popUpEl)(scope);
3357
- if ( appendToBody ) {
3358
- $document.find('body').append($popup);
3359
- } else {
3360
- element.after($popup);
3361
- }
3362
- }
3363
- };
3364
-
3365
- }])
3366
-
3367
- .directive('typeaheadPopup', function () {
3368
- return {
3369
- restrict:'EA',
3370
- scope:{
3371
- matches:'=',
3372
- query:'=',
3373
- active:'=',
3374
- position:'=',
3375
- select:'&'
3376
- },
3377
- replace:true,
3378
- templateUrl:'template/typeahead/typeahead-popup.html',
3379
- link:function (scope, element, attrs) {
3380
-
3381
- scope.templateUrl = attrs.templateUrl;
3382
-
3383
- scope.isOpen = function () {
3384
- return scope.matches.length > 0;
3385
- };
3386
-
3387
- scope.isActive = function (matchIdx) {
3388
- return scope.active == matchIdx;
3389
- };
3390
-
3391
- scope.selectActive = function (matchIdx) {
3392
- scope.active = matchIdx;
3393
- };
3394
-
3395
- scope.selectMatch = function (activeIdx) {
3396
- scope.select({activeIdx:activeIdx});
3397
- };
3398
- }
3399
- };
3400
- })
3401
-
3402
- .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {
3403
- return {
3404
- restrict:'EA',
3405
- scope:{
3406
- index:'=',
3407
- match:'=',
3408
- query:'='
3409
- },
3410
- link:function (scope, element, attrs) {
3411
- var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';
3412
- $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){
3413
- element.replaceWith($compile(tplContent.trim())(scope));
3414
- });
3415
- }
3416
- };
3417
- }])
3418
-
3419
- .filter('typeaheadHighlight', function() {
3420
-
3421
- function escapeRegexp(queryToEscape) {
3422
- return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
3423
- }
3424
-
3425
- return function(matchItem, query) {
3426
- return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;
3427
- };
3428
- });
3429
- angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
3430
- $templateCache.put("template/accordion/accordion-group.html",
3431
- "<div class=\"panel panel-default\">\n" +
3432
- " <div class=\"panel-heading\">\n" +
3433
- " <h4 class=\"panel-title\">\n" +
3434
- " <a class=\"accordion-toggle\" ng-click=\"isOpen = !isOpen\" accordion-transclude=\"heading\">{{heading}}</a>\n" +
3435
- " </h4>\n" +
3436
- " </div>\n" +
3437
- " <div class=\"panel-collapse\" collapse=\"!isOpen\">\n" +
3438
- " <div class=\"panel-body\" ng-transclude></div>\n" +
3439
- " </div>\n" +
3440
- "</div>");
3441
- }]);
3442
-
3443
- angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
3444
- $templateCache.put("template/accordion/accordion.html",
3445
- "<div class=\"panel-group\" ng-transclude></div>");
3446
- }]);
3447
-
3448
- angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
3449
- $templateCache.put("template/alert/alert.html",
3450
- "<div class='alert' ng-class='\"alert-\" + (type || \"warning\")'>\n" +
3451
- " <button ng-show='closeable' type='button' class='close' ng-click='close()'>&times;</button>\n" +
3452
- " <div ng-transclude></div>\n" +
3453
- "</div>\n" +
3454
- "");
3455
- }]);
3456
-
3457
- angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
3458
- $templateCache.put("template/carousel/carousel.html",
3459
- "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\">\n" +
3460
- " <ol class=\"carousel-indicators\" ng-show=\"slides().length > 1\">\n" +
3461
- " <li ng-repeat=\"slide in slides()\" ng-class=\"{active: isActive(slide)}\" ng-click=\"select(slide)\"></li>\n" +
3462
- " </ol>\n" +
3463
- " <div class=\"carousel-inner\" ng-transclude></div>\n" +
3464
- " <a class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides().length > 1\"><span class=\"icon-prev\"></span></a>\n" +
3465
- " <a class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides().length > 1\"><span class=\"icon-next\"></span></a>\n" +
3466
- "</div>\n" +
3467
- "");
3468
- }]);
3469
-
3470
- angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
3471
- $templateCache.put("template/carousel/slide.html",
3472
- "<div ng-class=\"{\n" +
3473
- " 'active': leaving || (active && !entering),\n" +
3474
- " 'prev': (next || active) && direction=='prev',\n" +
3475
- " 'next': (next || active) && direction=='next',\n" +
3476
- " 'right': direction=='prev',\n" +
3477
- " 'left': direction=='next'\n" +
3478
- " }\" class=\"item text-center\" ng-transclude></div>\n" +
3479
- "");
3480
- }]);
3481
-
3482
- angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
3483
- $templateCache.put("template/datepicker/datepicker.html",
3484
- "<table>\n" +
3485
- " <thead>\n" +
3486
- " <tr>\n" +
3487
- " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
3488
- " <th colspan=\"{{rows[0].length - 2 + showWeekNumbers}}\"><button type=\"button\" class=\"btn btn-default btn-sm btn-block\" ng-click=\"toggleMode()\"><strong>{{title}}</strong></button></th>\n" +
3489
- " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
3490
- " </tr>\n" +
3491
- " <tr ng-show=\"labels.length > 0\" class=\"h6\">\n" +
3492
- " <th ng-show=\"showWeekNumbers\" class=\"text-center\">#</th>\n" +
3493
- " <th ng-repeat=\"label in labels\" class=\"text-center\">{{label}}</th>\n" +
3494
- " </tr>\n" +
3495
- " </thead>\n" +
3496
- " <tbody>\n" +
3497
- " <tr ng-repeat=\"row in rows\">\n" +
3498
- " <td ng-show=\"showWeekNumbers\" class=\"text-center\"><em>{{ getWeekNumber(row) }}</em></td>\n" +
3499
- " <td ng-repeat=\"dt in row\" class=\"text-center\">\n" +
3500
- " <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\"><span ng-class=\"{'text-muted': dt.secondary}\">{{dt.label}}</span></button>\n" +
3501
- " </td>\n" +
3502
- " </tr>\n" +
3503
- " </tbody>\n" +
3504
- "</table>\n" +
3505
- "");
3506
- }]);
3507
-
3508
- angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
3509
- $templateCache.put("template/datepicker/popup.html",
3510
- "<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
3511
- " <li ng-transclude></li>\n" +
3512
- " <li ng-show=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
3513
- " <span class=\"btn-group\">\n" +
3514
- " <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"today()\">{{currentText}}</button>\n" +
3515
- " <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showWeeks = ! showWeeks\" ng-class=\"{active: showWeeks}\">{{toggleWeeksText}}</button>\n" +
3516
- " <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"clear()\">{{clearText}}</button>\n" +
3517
- " </span>\n" +
3518
- " <button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"isOpen = false\">{{closeText}}</button>\n" +
3519
- " </li>\n" +
3520
- "</ul>\n" +
3521
- "");
3522
- }]);
3523
-
3524
- angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
3525
- $templateCache.put("template/modal/backdrop.html",
3526
- "<div class=\"modal-backdrop fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1040 + index*10}\"></div>");
3527
- }]);
3528
-
3529
- angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
3530
- $templateCache.put("template/modal/window.html",
3531
- "<div tabindex=\"-1\" class=\"modal fade {{ windowClass }}\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
3532
- " <div class=\"modal-dialog\"><div class=\"modal-content\" ng-transclude></div></div>\n" +
3533
- "</div>");
3534
- }]);
3535
-
3536
- angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) {
3537
- $templateCache.put("template/pagination/pager.html",
3538
- "<ul class=\"pager\">\n" +
3539
- " <li ng-repeat=\"page in pages\" ng-class=\"{disabled: page.disabled, previous: page.previous, next: page.next}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
3540
- "</ul>");
3541
- }]);
3542
-
3543
- angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
3544
- $templateCache.put("template/pagination/pagination.html",
3545
- "<ul class=\"pagination\">\n" +
3546
- " <li ng-repeat=\"page in pages\" ng-class=\"{active: page.active, disabled: page.disabled}\"><a ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
3547
- "</ul>");
3548
- }]);
3549
-
3550
- angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
3551
- $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
3552
- "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3553
- " <div class=\"tooltip-arrow\"></div>\n" +
3554
- " <div class=\"tooltip-inner\" bind-html-unsafe=\"content\"></div>\n" +
3555
- "</div>\n" +
3556
- "");
3557
- }]);
3558
-
3559
- angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
3560
- $templateCache.put("template/tooltip/tooltip-popup.html",
3561
- "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3562
- " <div class=\"tooltip-arrow\"></div>\n" +
3563
- " <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
3564
- "</div>\n" +
3565
- "");
3566
- }]);
3567
-
3568
- angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
3569
- $templateCache.put("template/popover/popover.html",
3570
- "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
3571
- " <div class=\"arrow\"></div>\n" +
3572
- "\n" +
3573
- " <div class=\"popover-inner\">\n" +
3574
- " <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
3575
- " <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
3576
- " </div>\n" +
3577
- "</div>\n" +
3578
- "");
3579
- }]);
3580
-
3581
- angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
3582
- $templateCache.put("template/progressbar/bar.html",
3583
- "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div>");
3584
- }]);
3585
-
3586
- angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
3587
- $templateCache.put("template/progressbar/progress.html",
3588
- "<div class=\"progress\" ng-transclude></div>");
3589
- }]);
3590
-
3591
- angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
3592
- $templateCache.put("template/progressbar/progressbar.html",
3593
- "<div class=\"progress\"><div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div></div>");
3594
- }]);
3595
-
3596
- angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
3597
- $templateCache.put("template/rating/rating.html",
3598
- "<span ng-mouseleave=\"reset()\">\n" +
3599
- " <i ng-repeat=\"r in range\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < val && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\"></i>\n" +
3600
- "</span>");
3601
- }]);
3602
-
3603
- angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
3604
- $templateCache.put("template/tabs/tab.html",
3605
- "<li ng-class=\"{active: active, disabled: disabled}\">\n" +
3606
- " <a ng-click=\"select()\" tab-heading-transclude>{{heading}}</a>\n" +
3607
- "</li>\n" +
3608
- "");
3609
- }]);
3610
-
3611
- angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
3612
- $templateCache.put("template/tabs/tabset-titles.html",
3613
- "<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n" +
3614
- "</ul>\n" +
3615
- "");
3616
- }]);
3617
-
3618
- angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
3619
- $templateCache.put("template/tabs/tabset.html",
3620
- "\n" +
3621
- "<div class=\"tabbable\">\n" +
3622
- " <ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
3623
- " <div class=\"tab-content\">\n" +
3624
- " <div class=\"tab-pane\" \n" +
3625
- " ng-repeat=\"tab in tabs\" \n" +
3626
- " ng-class=\"{active: tab.active}\"\n" +
3627
- " tab-content-transclude=\"tab\">\n" +
3628
- " </div>\n" +
3629
- " </div>\n" +
3630
- "</div>\n" +
3631
- "");
3632
- }]);
3633
-
3634
- angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
3635
- $templateCache.put("template/timepicker/timepicker.html",
3636
- "<table>\n" +
3637
- " <tbody>\n" +
3638
- " <tr class=\"text-center\">\n" +
3639
- " <td><a ng-click=\"incrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
3640
- " <td>&nbsp;</td>\n" +
3641
- " <td><a ng-click=\"incrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
3642
- " <td ng-show=\"showMeridian\"></td>\n" +
3643
- " </tr>\n" +
3644
- " <tr>\n" +
3645
- " <td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidHours}\">\n" +
3646
- " <input type=\"text\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-mousewheel=\"incrementHours()\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
3647
- " </td>\n" +
3648
- " <td>:</td>\n" +
3649
- " <td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
3650
- " <input type=\"text\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
3651
- " </td>\n" +
3652
- " <td ng-show=\"showMeridian\"><button type=\"button\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\">{{meridian}}</button></td>\n" +
3653
- " </tr>\n" +
3654
- " <tr class=\"text-center\">\n" +
3655
- " <td><a ng-click=\"decrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
3656
- " <td>&nbsp;</td>\n" +
3657
- " <td><a ng-click=\"decrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
3658
- " <td ng-show=\"showMeridian\"></td>\n" +
3659
- " </tr>\n" +
3660
- " </tbody>\n" +
3661
- "</table>\n" +
3662
- "");
3663
- }]);
3664
-
3665
- angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
3666
- $templateCache.put("template/typeahead/typeahead-match.html",
3667
- "<a tabindex=\"-1\" bind-html-unsafe=\"match.label | typeaheadHighlight:query\"></a>");
3668
- }]);
3669
-
3670
- angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
3671
- $templateCache.put("template/typeahead/typeahead-popup.html",
3672
- "<ul class=\"dropdown-menu\" ng-style=\"{display: isOpen()&&'block' || 'none', top: position.top+'px', left: position.left+'px'}\">\n" +
3673
- " <li ng-repeat=\"match in matches\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index)\">\n" +
3674
- " <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
3675
- " </li>\n" +
3676
- "</ul>");
3677
- }]);