angular-ui-bootstrap-rails 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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) {