angular-ui-bootstrap-rails 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,10 @@
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
+ */
1
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"]);
2
9
  angular.module('ui.bootstrap.transition', [])
3
10
 
@@ -133,7 +140,7 @@ angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])
133
140
  } else {
134
141
  // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
135
142
  element.css({ height: element[0].scrollHeight + 'px' });
136
- //trigger reflow so a browser relaizes that height was updated from auto to a specific value
143
+ //trigger reflow so a browser realizes that height was updated from auto to a specific value
137
144
  var x = element[0].offsetWidth;
138
145
 
139
146
  element.removeClass('collapse in').addClass('collapsing');
@@ -1166,9 +1173,11 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon
1166
1173
  'ng-model': 'date',
1167
1174
  'ng-change': 'dateSelection()'
1168
1175
  });
1169
- var datepickerEl = angular.element(popupEl.children()[0]);
1176
+ var datepickerEl = angular.element(popupEl.children()[0]),
1177
+ datepickerOptions = {};
1170
1178
  if (attrs.datepickerOptions) {
1171
- datepickerEl.attr(angular.extend({}, originalScope.$eval(attrs.datepickerOptions)));
1179
+ datepickerOptions = originalScope.$eval(attrs.datepickerOptions);
1180
+ datepickerEl.attr(angular.extend({}, datepickerOptions));
1172
1181
  }
1173
1182
 
1174
1183
  // TODO: reverse from dateFilter string to Date object
@@ -1234,7 +1243,7 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon
1234
1243
  if (attrs.showWeeks) {
1235
1244
  addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks');
1236
1245
  } else {
1237
- scope.showWeeks = datepickerConfig.showWeeks;
1246
+ scope.showWeeks = 'show-weeks' in datepickerOptions ? datepickerOptions['show-weeks'] : datepickerConfig.showWeeks;
1238
1247
  datepickerEl.attr('show-weeks', 'showWeeks');
1239
1248
  }
1240
1249
  if (attrs.dateDisabled) {
@@ -1354,7 +1363,7 @@ angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', ['
1354
1363
  };
1355
1364
  }]);
1356
1365
 
1357
- angular.module('ui.bootstrap.modal', [])
1366
+ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1358
1367
 
1359
1368
  /**
1360
1369
  * A helper, internal data structure that acts as a map but also allows getting / removing
@@ -1434,7 +1443,8 @@ angular.module('ui.bootstrap.modal', [])
1434
1443
  return {
1435
1444
  restrict: 'EA',
1436
1445
  scope: {
1437
- index: '@'
1446
+ index: '@',
1447
+ animate: '='
1438
1448
  },
1439
1449
  replace: true,
1440
1450
  transclude: true,
@@ -1461,13 +1471,12 @@ angular.module('ui.bootstrap.modal', [])
1461
1471
  };
1462
1472
  }])
1463
1473
 
1464
- .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap',
1465
- function ($document, $compile, $rootScope, $$stackedMap) {
1474
+ .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
1475
+ function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1466
1476
 
1467
1477
  var OPENED_MODAL_CLASS = 'modal-open';
1468
1478
 
1469
- var backdropjqLiteEl, backdropDomEl;
1470
- var backdropScope = $rootScope.$new(true);
1479
+ var backdropDomEl, backdropScope;
1471
1480
  var openedWindows = $$stackedMap.createNew();
1472
1481
  var $modalStack = {};
1473
1482
 
@@ -1483,7 +1492,9 @@ angular.module('ui.bootstrap.modal', [])
1483
1492
  }
1484
1493
 
1485
1494
  $rootScope.$watch(backdropIndex, function(newBackdropIndex){
1486
- backdropScope.index = newBackdropIndex;
1495
+ if (backdropScope) {
1496
+ backdropScope.index = newBackdropIndex;
1497
+ }
1487
1498
  });
1488
1499
 
1489
1500
  function removeModalWindow(modalInstance) {
@@ -1495,17 +1506,53 @@ angular.module('ui.bootstrap.modal', [])
1495
1506
  openedWindows.remove(modalInstance);
1496
1507
 
1497
1508
  //remove window DOM element
1498
- modalWindow.modalDomEl.remove();
1509
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop);
1499
1510
  body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1511
+ }
1500
1512
 
1501
- //remove backdrop if no longer needed
1502
- if (backdropDomEl && backdropIndex() == -1) {
1503
- backdropDomEl.remove();
1504
- backdropDomEl = undefined;
1513
+ function checkRemoveBackdrop() {
1514
+ //remove backdrop if no longer needed
1515
+ if (backdropDomEl && backdropIndex() == -1) {
1516
+ var backdropScopeRef = backdropScope;
1517
+ removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
1518
+ backdropScopeRef.$destroy();
1519
+ backdropScopeRef = null;
1520
+ });
1521
+ backdropDomEl = undefined;
1522
+ backdropScope = undefined;
1523
+ }
1524
+ }
1525
+
1526
+ function removeAfterAnimate(domEl, scope, emulateTime, done) {
1527
+ // Closing animation
1528
+ scope.animate = false;
1529
+
1530
+ var transitionEndEventName = $transition.transitionEndEventName;
1531
+ if (transitionEndEventName) {
1532
+ // transition out
1533
+ var timeout = $timeout(afterAnimating, emulateTime);
1534
+
1535
+ domEl.bind(transitionEndEventName, function () {
1536
+ $timeout.cancel(timeout);
1537
+ afterAnimating();
1538
+ scope.$apply();
1539
+ });
1540
+ } else {
1541
+ // Ensure this call is async
1542
+ $timeout(afterAnimating, 0);
1505
1543
  }
1506
1544
 
1507
- //destroy scope
1508
- modalWindow.modalScope.$destroy();
1545
+ function afterAnimating() {
1546
+ if (afterAnimating.done) {
1547
+ return;
1548
+ }
1549
+ afterAnimating.done = true;
1550
+
1551
+ domEl.remove();
1552
+ if (done) {
1553
+ done();
1554
+ }
1555
+ }
1509
1556
  }
1510
1557
 
1511
1558
  $document.bind('keydown', function (evt) {
@@ -1530,17 +1577,20 @@ angular.module('ui.bootstrap.modal', [])
1530
1577
  keyboard: modal.keyboard
1531
1578
  });
1532
1579
 
1533
- var body = $document.find('body').eq(0);
1580
+ var body = $document.find('body').eq(0),
1581
+ currBackdropIndex = backdropIndex();
1534
1582
 
1535
- if (backdropIndex() >= 0 && !backdropDomEl) {
1536
- backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
1537
- backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
1538
- body.append(backdropDomEl);
1583
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
1584
+ backdropScope = $rootScope.$new(true);
1585
+ backdropScope.index = currBackdropIndex;
1586
+ backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
1587
+ body.append(backdropDomEl);
1539
1588
  }
1540
1589
 
1541
1590
  var angularDomEl = angular.element('<div modal-window></div>');
1542
1591
  angularDomEl.attr('window-class', modal.windowClass);
1543
1592
  angularDomEl.attr('index', openedWindows.length() - 1);
1593
+ angularDomEl.attr('animate', 'animate');
1544
1594
  angularDomEl.html(modal.content);
1545
1595
 
1546
1596
  var modalDomEl = $compile(angularDomEl)(modal.scope);
@@ -1565,6 +1615,14 @@ angular.module('ui.bootstrap.modal', [])
1565
1615
  }
1566
1616
  };
1567
1617
 
1618
+ $modalStack.dismissAll = function (reason) {
1619
+ var topModal = this.getTop();
1620
+ while (topModal) {
1621
+ this.dismiss(topModal.key, reason);
1622
+ topModal = this.getTop();
1623
+ }
1624
+ };
1625
+
1568
1626
  $modalStack.getTop = function () {
1569
1627
  return openedWindows.top();
1570
1628
  };
@@ -2032,224 +2090,245 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2032
2090
  return {
2033
2091
  restrict: 'EA',
2034
2092
  scope: true,
2035
- link: function link ( scope, element, attrs ) {
2036
- var tooltip = $compile( template )( scope );
2037
- var transitionTimeout;
2038
- var popupTimeout;
2039
- var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
2040
- var triggers = getTriggers( undefined );
2041
- var hasRegisteredTriggers = false;
2042
- var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
2043
-
2044
- var positionTooltip = function (){
2045
- var position,
2046
- ttWidth,
2047
- ttHeight,
2048
- ttPosition;
2049
- // Get the position of the directive element.
2050
- position = appendToBody ? $position.offset( element ) : $position.position( element );
2051
-
2052
- // Get the height and width of the tooltip so we can center it.
2053
- ttWidth = tooltip.prop( 'offsetWidth' );
2054
- ttHeight = tooltip.prop( 'offsetHeight' );
2055
-
2056
- // Calculate the tooltip's top and left coordinates to center it with
2057
- // this directive.
2058
- switch ( scope.tt_placement ) {
2059
- case 'right':
2060
- ttPosition = {
2061
- top: position.top + position.height / 2 - ttHeight / 2,
2062
- left: position.left + position.width
2063
- };
2064
- break;
2065
- case 'bottom':
2066
- ttPosition = {
2067
- top: position.top + position.height,
2068
- left: position.left + position.width / 2 - ttWidth / 2
2069
- };
2070
- break;
2071
- case 'left':
2072
- ttPosition = {
2073
- top: position.top + position.height / 2 - ttHeight / 2,
2074
- left: position.left - ttWidth
2075
- };
2076
- break;
2077
- default:
2078
- ttPosition = {
2079
- top: position.top - ttHeight,
2080
- left: position.left + position.width / 2 - ttWidth / 2
2081
- };
2082
- break;
2083
- }
2093
+ compile: function (tElem, tAttrs) {
2094
+ var tooltipLinker = $compile( template );
2095
+
2096
+ return function link ( scope, element, attrs ) {
2097
+ var tooltip;
2098
+ var transitionTimeout;
2099
+ var popupTimeout;
2100
+ var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
2101
+ var triggers = getTriggers( undefined );
2102
+ var hasRegisteredTriggers = false;
2103
+ var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
2104
+
2105
+ var positionTooltip = function (){
2106
+ var position,
2107
+ ttWidth,
2108
+ ttHeight,
2109
+ ttPosition;
2110
+ // Get the position of the directive element.
2111
+ position = appendToBody ? $position.offset( element ) : $position.position( element );
2112
+
2113
+ // Get the height and width of the tooltip so we can center it.
2114
+ ttWidth = tooltip.prop( 'offsetWidth' );
2115
+ ttHeight = tooltip.prop( 'offsetHeight' );
2116
+
2117
+ // Calculate the tooltip's top and left coordinates to center it with
2118
+ // this directive.
2119
+ switch ( scope.tt_placement ) {
2120
+ case 'right':
2121
+ ttPosition = {
2122
+ top: position.top + position.height / 2 - ttHeight / 2,
2123
+ left: position.left + position.width
2124
+ };
2125
+ break;
2126
+ case 'bottom':
2127
+ ttPosition = {
2128
+ top: position.top + position.height,
2129
+ left: position.left + position.width / 2 - ttWidth / 2
2130
+ };
2131
+ break;
2132
+ case 'left':
2133
+ ttPosition = {
2134
+ top: position.top + position.height / 2 - ttHeight / 2,
2135
+ left: position.left - ttWidth
2136
+ };
2137
+ break;
2138
+ default:
2139
+ ttPosition = {
2140
+ top: position.top - ttHeight,
2141
+ left: position.left + position.width / 2 - ttWidth / 2
2142
+ };
2143
+ break;
2144
+ }
2084
2145
 
2085
- ttPosition.top += 'px';
2086
- ttPosition.left += 'px';
2146
+ ttPosition.top += 'px';
2147
+ ttPosition.left += 'px';
2087
2148
 
2088
- // Now set the calculated positioning.
2089
- tooltip.css( ttPosition );
2149
+ // Now set the calculated positioning.
2150
+ tooltip.css( ttPosition );
2090
2151
 
2091
- };
2152
+ };
2092
2153
 
2093
- // By default, the tooltip is not open.
2094
- // TODO add ability to start tooltip opened
2095
- scope.tt_isOpen = false;
2154
+ // By default, the tooltip is not open.
2155
+ // TODO add ability to start tooltip opened
2156
+ scope.tt_isOpen = false;
2096
2157
 
2097
- function toggleTooltipBind () {
2098
- if ( ! scope.tt_isOpen ) {
2099
- showTooltipBind();
2100
- } else {
2101
- hideTooltipBind();
2158
+ function toggleTooltipBind () {
2159
+ if ( ! scope.tt_isOpen ) {
2160
+ showTooltipBind();
2161
+ } else {
2162
+ hideTooltipBind();
2163
+ }
2102
2164
  }
2103
- }
2104
-
2105
- // Show the tooltip with delay if specified, otherwise show it immediately
2106
- function showTooltipBind() {
2107
- if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
2108
- return;
2165
+
2166
+ // Show the tooltip with delay if specified, otherwise show it immediately
2167
+ function showTooltipBind() {
2168
+ if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
2169
+ return;
2170
+ }
2171
+ if ( scope.tt_popupDelay ) {
2172
+ popupTimeout = $timeout( show, scope.tt_popupDelay, false );
2173
+ popupTimeout.then(function(reposition){reposition();});
2174
+ } else {
2175
+ show()();
2176
+ }
2109
2177
  }
2110
- if ( scope.tt_popupDelay ) {
2111
- popupTimeout = $timeout( show, scope.tt_popupDelay );
2112
- popupTimeout.then(function(reposition){reposition();});
2113
- } else {
2114
- scope.$apply( show )();
2178
+
2179
+ function hideTooltipBind () {
2180
+ scope.$apply(function () {
2181
+ hide();
2182
+ });
2115
2183
  }
2116
- }
2117
2184
 
2118
- function hideTooltipBind () {
2119
- scope.$apply(function () {
2120
- hide();
2121
- });
2122
- }
2123
-
2124
- // Show the tooltip popup element.
2125
- function show() {
2185
+ // Show the tooltip popup element.
2186
+ function show() {
2126
2187
 
2127
2188
 
2128
- // Don't show empty tooltips.
2129
- if ( ! scope.tt_content ) {
2130
- return angular.noop;
2131
- }
2189
+ // Don't show empty tooltips.
2190
+ if ( ! scope.tt_content ) {
2191
+ return angular.noop;
2192
+ }
2132
2193
 
2133
- // If there is a pending remove transition, we must cancel it, lest the
2134
- // tooltip be mysteriously removed.
2135
- if ( transitionTimeout ) {
2136
- $timeout.cancel( transitionTimeout );
2137
- }
2138
-
2139
- // Set the initial positioning.
2140
- tooltip.css({ top: 0, left: 0, display: 'block' });
2141
-
2142
- // Now we add it to the DOM because need some info about it. But it's not
2143
- // visible yet anyway.
2144
- if ( appendToBody ) {
2145
- $document.find( 'body' ).append( tooltip );
2146
- } else {
2147
- element.after( tooltip );
2194
+ createTooltip();
2195
+
2196
+ // If there is a pending remove transition, we must cancel it, lest the
2197
+ // tooltip be mysteriously removed.
2198
+ if ( transitionTimeout ) {
2199
+ $timeout.cancel( transitionTimeout );
2200
+ }
2201
+
2202
+ // Set the initial positioning.
2203
+ tooltip.css({ top: 0, left: 0, display: 'block' });
2204
+
2205
+ // Now we add it to the DOM because need some info about it. But it's not
2206
+ // visible yet anyway.
2207
+ if ( appendToBody ) {
2208
+ $document.find( 'body' ).append( tooltip );
2209
+ } else {
2210
+ element.after( tooltip );
2211
+ }
2212
+
2213
+ positionTooltip();
2214
+
2215
+ // And show the tooltip.
2216
+ scope.tt_isOpen = true;
2217
+ scope.$digest(); // digest required as $apply is not called
2218
+
2219
+ // Return positioning function as promise callback for correct
2220
+ // positioning after draw.
2221
+ return positionTooltip;
2148
2222
  }
2149
2223
 
2150
- positionTooltip();
2224
+ // Hide the tooltip popup element.
2225
+ function hide() {
2226
+ // First things first: we don't show it anymore.
2227
+ scope.tt_isOpen = false;
2228
+
2229
+ //if tooltip is going to be shown after delay, we must cancel this
2230
+ $timeout.cancel( popupTimeout );
2231
+
2232
+ // And now we remove it from the DOM. However, if we have animation, we
2233
+ // need to wait for it to expire beforehand.
2234
+ // FIXME: this is a placeholder for a port of the transitions library.
2235
+ if ( scope.tt_animation ) {
2236
+ transitionTimeout = $timeout(removeTooltip, 500);
2237
+ } else {
2238
+ removeTooltip();
2239
+ }
2240
+ }
2151
2241
 
2152
- // And show the tooltip.
2153
- scope.tt_isOpen = true;
2242
+ function createTooltip() {
2243
+ // There can only be one tooltip element per directive shown at once.
2244
+ if (tooltip) {
2245
+ removeTooltip();
2246
+ }
2247
+ tooltip = tooltipLinker(scope, function () {});
2154
2248
 
2155
- // Return positioning function as promise callback for correct
2156
- // positioning after draw.
2157
- return positionTooltip;
2158
- }
2159
-
2160
- // Hide the tooltip popup element.
2161
- function hide() {
2162
- // First things first: we don't show it anymore.
2163
- scope.tt_isOpen = false;
2249
+ // Get contents rendered into the tooltip
2250
+ scope.$digest();
2251
+ }
2164
2252
 
2165
- //if tooltip is going to be shown after delay, we must cancel this
2166
- $timeout.cancel( popupTimeout );
2167
-
2168
- // And now we remove it from the DOM. However, if we have animation, we
2169
- // need to wait for it to expire beforehand.
2170
- // FIXME: this is a placeholder for a port of the transitions library.
2171
- if ( scope.tt_animation ) {
2172
- transitionTimeout = $timeout(function () {
2253
+ function removeTooltip() {
2254
+ if (tooltip) {
2173
2255
  tooltip.remove();
2174
- }, 500);
2175
- } else {
2176
- tooltip.remove();
2256
+ tooltip = null;
2257
+ }
2177
2258
  }
2178
- }
2179
2259
 
2180
- /**
2181
- * Observe the relevant attributes.
2182
- */
2183
- attrs.$observe( type, function ( val ) {
2184
- scope.tt_content = val;
2260
+ /**
2261
+ * Observe the relevant attributes.
2262
+ */
2263
+ attrs.$observe( type, function ( val ) {
2264
+ scope.tt_content = val;
2185
2265
 
2186
- if (!val && scope.tt_isOpen ) {
2187
- hide();
2188
- }
2189
- });
2266
+ if (!val && scope.tt_isOpen ) {
2267
+ hide();
2268
+ }
2269
+ });
2190
2270
 
2191
- attrs.$observe( prefix+'Title', function ( val ) {
2192
- scope.tt_title = val;
2193
- });
2271
+ attrs.$observe( prefix+'Title', function ( val ) {
2272
+ scope.tt_title = val;
2273
+ });
2194
2274
 
2195
- attrs.$observe( prefix+'Placement', function ( val ) {
2196
- scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
2197
- });
2275
+ attrs.$observe( prefix+'Placement', function ( val ) {
2276
+ scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
2277
+ });
2198
2278
 
2199
- attrs.$observe( prefix+'PopupDelay', function ( val ) {
2200
- var delay = parseInt( val, 10 );
2201
- scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
2202
- });
2279
+ attrs.$observe( prefix+'PopupDelay', function ( val ) {
2280
+ var delay = parseInt( val, 10 );
2281
+ scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
2282
+ });
2203
2283
 
2204
- var unregisterTriggers = function() {
2205
- if (hasRegisteredTriggers) {
2206
- element.unbind( triggers.show, showTooltipBind );
2207
- element.unbind( triggers.hide, hideTooltipBind );
2208
- }
2209
- };
2284
+ var unregisterTriggers = function() {
2285
+ if (hasRegisteredTriggers) {
2286
+ element.unbind( triggers.show, showTooltipBind );
2287
+ element.unbind( triggers.hide, hideTooltipBind );
2288
+ }
2289
+ };
2210
2290
 
2211
- attrs.$observe( prefix+'Trigger', function ( val ) {
2212
- unregisterTriggers();
2291
+ attrs.$observe( prefix+'Trigger', function ( val ) {
2292
+ unregisterTriggers();
2213
2293
 
2214
- triggers = getTriggers( val );
2294
+ triggers = getTriggers( val );
2215
2295
 
2216
- if ( triggers.show === triggers.hide ) {
2217
- element.bind( triggers.show, toggleTooltipBind );
2218
- } else {
2219
- element.bind( triggers.show, showTooltipBind );
2220
- element.bind( triggers.hide, hideTooltipBind );
2221
- }
2296
+ if ( triggers.show === triggers.hide ) {
2297
+ element.bind( triggers.show, toggleTooltipBind );
2298
+ } else {
2299
+ element.bind( triggers.show, showTooltipBind );
2300
+ element.bind( triggers.hide, hideTooltipBind );
2301
+ }
2222
2302
 
2223
- hasRegisteredTriggers = true;
2224
- });
2303
+ hasRegisteredTriggers = true;
2304
+ });
2225
2305
 
2226
- var animation = scope.$eval(attrs[prefix + 'Animation']);
2227
- scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
2306
+ var animation = scope.$eval(attrs[prefix + 'Animation']);
2307
+ scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
2228
2308
 
2229
- attrs.$observe( prefix+'AppendToBody', function ( val ) {
2230
- appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
2231
- });
2309
+ attrs.$observe( prefix+'AppendToBody', function ( val ) {
2310
+ appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
2311
+ });
2232
2312
 
2233
- // if a tooltip is attached to <body> we need to remove it on
2234
- // location change as its parent scope will probably not be destroyed
2235
- // by the change.
2236
- if ( appendToBody ) {
2237
- scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
2238
- if ( scope.tt_isOpen ) {
2239
- hide();
2313
+ // if a tooltip is attached to <body> we need to remove it on
2314
+ // location change as its parent scope will probably not be destroyed
2315
+ // by the change.
2316
+ if ( appendToBody ) {
2317
+ scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
2318
+ if ( scope.tt_isOpen ) {
2319
+ hide();
2320
+ }
2321
+ });
2240
2322
  }
2241
- });
2242
- }
2243
2323
 
2244
- // Make sure tooltip is destroyed and removed.
2245
- scope.$on('$destroy', function onDestroyTooltip() {
2246
- $timeout.cancel( transitionTimeout );
2247
- $timeout.cancel( popupTimeout );
2248
- unregisterTriggers();
2249
- tooltip.remove();
2250
- tooltip.unbind();
2251
- tooltip = null;
2252
- });
2324
+ // Make sure tooltip is destroyed and removed.
2325
+ scope.$on('$destroy', function onDestroyTooltip() {
2326
+ $timeout.cancel( transitionTimeout );
2327
+ $timeout.cancel( popupTimeout );
2328
+ unregisterTriggers();
2329
+ removeTooltip();
2330
+ });
2331
+ };
2253
2332
  }
2254
2333
  };
2255
2334
  };
@@ -2288,6 +2367,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2288
2367
  * just mouse enter/leave, html popovers, and selector delegatation.
2289
2368
  */
2290
2369
  angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )
2370
+
2291
2371
  .directive( 'popoverPopup', function () {
2292
2372
  return {
2293
2373
  restrict: 'EA',
@@ -2296,11 +2376,11 @@ angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )
2296
2376
  templateUrl: 'template/popover/popover.html'
2297
2377
  };
2298
2378
  })
2299
- .directive( 'popover', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
2379
+
2380
+ .directive( 'popover', [ '$tooltip', function ( $tooltip ) {
2300
2381
  return $tooltip( 'popover', 'popover', 'click' );
2301
2382
  }]);
2302
2383
 
2303
-
2304
2384
  angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])
2305
2385
 
2306
2386
  .constant('progressConfig', {
@@ -2431,11 +2511,9 @@ angular.module('ui.bootstrap.rating', [])
2431
2511
  $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange));
2432
2512
 
2433
2513
  $scope.rate = function(value) {
2434
- if ( $scope.readonly || $scope.value === value) {
2435
- return;
2514
+ if ( $scope.value !== value && !$scope.readonly ) {
2515
+ $scope.value = value;
2436
2516
  }
2437
-
2438
- $scope.value = value;
2439
2517
  };
2440
2518
 
2441
2519
  $scope.enter = function(value) {