angular-ui-bootstrap-rails 0.11.0 → 0.11.1

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: 85f812e3f7f178e10580078d59e6a10ec3a972d8
4
- data.tar.gz: 13e0843c45c3a3f4e49caebe5810d734f24a69c6
3
+ metadata.gz: 27e4bece79303fd2da07e638a82cbfd6804c577c
4
+ data.tar.gz: 00475d11b2f375ce5e66e2325c67df12ea54038d
5
5
  SHA512:
6
- metadata.gz: 4259ed0ada0ea8c87aade0067cbfc7c85440eab8e13b84a81c950798ef8002148807114d96a2cf7215bc6ac5a2a94f9f339ac3e36ab77420935cf41aa2344640
7
- data.tar.gz: 87a81f50fb592b85e7be03e413abdfd32bc875751e505ade49c5dbdcdf999990740c52a2ac5a399c0f9247fbd03c05ff4abd2ddd4646e3c3f57f8ceca20e4244
6
+ metadata.gz: 1b6dabb638ff4e3e744d9973cbd19841ee1b059cc4e45c173e26e9b61fb328591272005d6ca0aa6d1e26fd5b6535a2989b535684dbb5ed5bd3dcda916b5169a5
7
+ data.tar.gz: 73def3d19c170800d216f6a22d0738f87f885a5ef047b5031e800d942cb3d07f23d88796ead7a157b1bfac6d88083fb308722edd53a36d1769e8ada9aec2915b
@@ -1,7 +1,7 @@
1
1
  module AngularUI
2
2
  module Bootstrap
3
3
  module Rails
4
- VERSION = "0.11.0"
4
+ VERSION = "0.11.1"
5
5
  end
6
6
  end
7
7
  end
@@ -2,7 +2,7 @@
2
2
  * angular-ui-bootstrap
3
3
  * http://angular-ui.github.io/bootstrap/
4
4
 
5
- * Version: 0.11.0 - 2014-05-01
5
+ * Version: 0.11.1 - 2014-09-26
6
6
  * License: MIT
7
7
  */
8
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.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","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"]);
@@ -747,7 +747,7 @@ angular.module('ui.bootstrap.dateparser', [])
747
747
  }
748
748
  };
749
749
 
750
- this.createParser = function(format) {
750
+ function createParser(format) {
751
751
  var map = [], regex = format.split('');
752
752
 
753
753
  angular.forEach(formatCodeToRegex, function(data, code) {
@@ -772,17 +772,17 @@ angular.module('ui.bootstrap.dateparser', [])
772
772
  regex: new RegExp('^' + regex.join('') + '$'),
773
773
  map: orderByFilter(map, 'index')
774
774
  };
775
- };
775
+ }
776
776
 
777
777
  this.parse = function(input, format) {
778
- if ( !angular.isString(input) ) {
778
+ if ( !angular.isString(input) || !format ) {
779
779
  return input;
780
780
  }
781
781
 
782
782
  format = $locale.DATETIME_FORMATS[format] || format;
783
783
 
784
784
  if ( !this.parsers[format] ) {
785
- this.parsers[format] = this.createParser(format);
785
+ this.parsers[format] = createParser(format);
786
786
  }
787
787
 
788
788
  var parser = this.parsers[format],
@@ -1008,7 +1008,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1008
1008
  self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];
1009
1009
  });
1010
1010
 
1011
- // Watchable attributes
1011
+ // Watchable date attributes
1012
1012
  angular.forEach(['minDate', 'maxDate'], function( key ) {
1013
1013
  if ( $attrs[key] ) {
1014
1014
  $scope.$parent.$watch($parse($attrs[key]), function(value) {
@@ -1455,12 +1455,24 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1455
1455
  });
1456
1456
  }
1457
1457
 
1458
- angular.forEach(['minDate', 'maxDate'], function( key ) {
1458
+ scope.watchData = {};
1459
+ angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) {
1459
1460
  if ( attrs[key] ) {
1460
- scope.$parent.$watch($parse(attrs[key]), function(value){
1461
- scope[key] = value;
1461
+ var getAttribute = $parse(attrs[key]);
1462
+ scope.$parent.$watch(getAttribute, function(value){
1463
+ scope.watchData[key] = value;
1462
1464
  });
1463
- datepickerEl.attr(cameltoDash(key), key);
1465
+ datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
1466
+
1467
+ // Propagate changes from datepicker to outside
1468
+ if ( key === 'datepickerMode' ) {
1469
+ var setAttribute = getAttribute.assign;
1470
+ scope.$watch('watchData.' + key, function(value, oldvalue) {
1471
+ if ( value !== oldvalue ) {
1472
+ setAttribute(scope.$parent, value);
1473
+ }
1474
+ });
1475
+ }
1464
1476
  }
1465
1477
  });
1466
1478
  if (attrs.dateDisabled) {
@@ -1571,6 +1583,9 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1571
1583
  };
1572
1584
 
1573
1585
  var $popup = $compile(popupEl)(scope);
1586
+ // Prevent jQuery cache memory leak (template is now redundant after linking)
1587
+ popupEl.remove();
1588
+
1574
1589
  if ( appendToBody ) {
1575
1590
  $document.find('body').append($popup);
1576
1591
  } else {
@@ -1632,7 +1647,8 @@ angular.module('ui.bootstrap.dropdown', [])
1632
1647
  };
1633
1648
 
1634
1649
  var closeDropdown = function( evt ) {
1635
- if (evt && evt.isDefaultPrevented()) {
1650
+ var toggleElement = openScope.getToggleElement();
1651
+ if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {
1636
1652
  return;
1637
1653
  }
1638
1654
 
@@ -1679,6 +1695,10 @@ angular.module('ui.bootstrap.dropdown', [])
1679
1695
  return scope.isOpen;
1680
1696
  };
1681
1697
 
1698
+ scope.getToggleElement = function() {
1699
+ return self.toggleElement;
1700
+ };
1701
+
1682
1702
  scope.focusToggleElement = function() {
1683
1703
  if ( self.toggleElement ) {
1684
1704
  self.toggleElement[0].focus();
@@ -1712,7 +1732,6 @@ angular.module('ui.bootstrap.dropdown', [])
1712
1732
 
1713
1733
  .directive('dropdown', function() {
1714
1734
  return {
1715
- restrict: 'CA',
1716
1735
  controller: 'DropdownController',
1717
1736
  link: function(scope, element, attrs, dropdownCtrl) {
1718
1737
  dropdownCtrl.init( element );
@@ -1722,7 +1741,6 @@ angular.module('ui.bootstrap.dropdown', [])
1722
1741
 
1723
1742
  .directive('dropdownToggle', function() {
1724
1743
  return {
1725
- restrict: 'CA',
1726
1744
  require: '?^dropdown',
1727
1745
  link: function(scope, element, attrs, dropdownCtrl) {
1728
1746
  if ( !dropdownCtrl ) {
@@ -1820,7 +1838,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1820
1838
  restrict: 'EA',
1821
1839
  replace: true,
1822
1840
  templateUrl: 'template/modal/backdrop.html',
1823
- link: function (scope) {
1841
+ link: function (scope, element, attrs) {
1842
+ scope.backdropClass = attrs.backdropClass || '';
1824
1843
 
1825
1844
  scope.animate = false;
1826
1845
 
@@ -1851,8 +1870,18 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1851
1870
  $timeout(function () {
1852
1871
  // trigger CSS transitions
1853
1872
  scope.animate = true;
1854
- // focus a freshly-opened modal
1855
- element[0].focus();
1873
+
1874
+ /**
1875
+ * Auto-focusing of a freshly-opened modal element causes any child elements
1876
+ * with the autofocus attribute to loose focus. This is an issue on touch
1877
+ * based devices which will show and then hide the onscreen keyboard.
1878
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
1879
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
1880
+ * the modal element if the modal does not contain an autofocus element.
1881
+ */
1882
+ if (!element[0].querySelectorAll('[autofocus]').length) {
1883
+ element[0].focus();
1884
+ }
1856
1885
  });
1857
1886
 
1858
1887
  scope.close = function (evt) {
@@ -1867,6 +1896,17 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1867
1896
  };
1868
1897
  }])
1869
1898
 
1899
+ .directive('modalTransclude', function () {
1900
+ return {
1901
+ link: function($scope, $element, $attrs, controller, $transclude) {
1902
+ $transclude($scope.$parent, function(clone) {
1903
+ $element.empty();
1904
+ $element.append(clone);
1905
+ });
1906
+ }
1907
+ };
1908
+ })
1909
+
1870
1910
  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
1871
1911
  function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1872
1912
 
@@ -1938,7 +1978,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1938
1978
  });
1939
1979
  } else {
1940
1980
  // Ensure this call is async
1941
- $timeout(afterAnimating, 0);
1981
+ $timeout(afterAnimating);
1942
1982
  }
1943
1983
 
1944
1984
  function afterAnimating() {
@@ -1983,7 +2023,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1983
2023
  if (currBackdropIndex >= 0 && !backdropDomEl) {
1984
2024
  backdropScope = $rootScope.$new(true);
1985
2025
  backdropScope.index = currBackdropIndex;
1986
- backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
2026
+ var angularBackgroundDomEl = angular.element('<div modal-backdrop></div>');
2027
+ angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
2028
+ backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
1987
2029
  body.append(backdropDomEl);
1988
2030
  }
1989
2031
 
@@ -2003,17 +2045,17 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2003
2045
  };
2004
2046
 
2005
2047
  $modalStack.close = function (modalInstance, result) {
2006
- var modalWindow = openedWindows.get(modalInstance).value;
2048
+ var modalWindow = openedWindows.get(modalInstance);
2007
2049
  if (modalWindow) {
2008
- modalWindow.deferred.resolve(result);
2050
+ modalWindow.value.deferred.resolve(result);
2009
2051
  removeModalWindow(modalInstance);
2010
2052
  }
2011
2053
  };
2012
2054
 
2013
2055
  $modalStack.dismiss = function (modalInstance, reason) {
2014
- var modalWindow = openedWindows.get(modalInstance).value;
2056
+ var modalWindow = openedWindows.get(modalInstance);
2015
2057
  if (modalWindow) {
2016
- modalWindow.deferred.reject(reason);
2058
+ modalWindow.value.deferred.reject(reason);
2017
2059
  removeModalWindow(modalInstance);
2018
2060
  }
2019
2061
  };
@@ -2047,14 +2089,15 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2047
2089
 
2048
2090
  function getTemplatePromise(options) {
2049
2091
  return options.template ? $q.when(options.template) :
2050
- $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
2051
- return result.data;
2092
+ $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl,
2093
+ {cache: $templateCache}).then(function (result) {
2094
+ return result.data;
2052
2095
  });
2053
2096
  }
2054
2097
 
2055
2098
  function getResolvePromises(resolves) {
2056
2099
  var promisesArr = [];
2057
- angular.forEach(resolves, function (value, key) {
2100
+ angular.forEach(resolves, function (value) {
2058
2101
  if (angular.isFunction(value) || angular.isArray(value)) {
2059
2102
  promisesArr.push($q.when($injector.invoke(value)));
2060
2103
  }
@@ -2110,6 +2153,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2110
2153
  });
2111
2154
 
2112
2155
  ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
2156
+ if (modalOptions.controllerAs) {
2157
+ modalScope[modalOptions.controllerAs] = ctrlInstance;
2158
+ }
2113
2159
  }
2114
2160
 
2115
2161
  $modalStack.open(modalInstance, {
@@ -2118,6 +2164,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2118
2164
  content: tplAndVars[0],
2119
2165
  backdrop: modalOptions.backdrop,
2120
2166
  keyboard: modalOptions.keyboard,
2167
+ backdropClass: modalOptions.backdropClass,
2121
2168
  windowClass: modalOptions.windowClass,
2122
2169
  windowTemplateUrl: modalOptions.windowTemplateUrl,
2123
2170
  size: modalOptions.size
@@ -3428,7 +3475,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3428
3475
  .factory('typeaheadParser', ['$parse', function ($parse) {
3429
3476
 
3430
3477
  // 00000111000000000000022200000000000000003333333333333330000000000044000
3431
- var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;
3478
+ var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
3432
3479
 
3433
3480
  return {
3434
3481
  parse:function (input) {
@@ -3594,6 +3641,18 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3594
3641
  //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
3595
3642
  var timeoutPromise;
3596
3643
 
3644
+ var scheduleSearchWithTimeout = function(inputValue) {
3645
+ timeoutPromise = $timeout(function () {
3646
+ getMatchesAsync(inputValue);
3647
+ }, waitTime);
3648
+ };
3649
+
3650
+ var cancelPreviousTimeout = function() {
3651
+ if (timeoutPromise) {
3652
+ $timeout.cancel(timeoutPromise);
3653
+ }
3654
+ };
3655
+
3597
3656
  //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
3598
3657
  //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
3599
3658
  modelCtrl.$parsers.unshift(function (inputValue) {
@@ -3602,17 +3661,14 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3602
3661
 
3603
3662
  if (inputValue && inputValue.length >= minSearch) {
3604
3663
  if (waitTime > 0) {
3605
- if (timeoutPromise) {
3606
- $timeout.cancel(timeoutPromise);//cancel previous timeout
3607
- }
3608
- timeoutPromise = $timeout(function () {
3609
- getMatchesAsync(inputValue);
3610
- }, waitTime);
3664
+ cancelPreviousTimeout();
3665
+ scheduleSearchWithTimeout(inputValue);
3611
3666
  } else {
3612
3667
  getMatchesAsync(inputValue);
3613
3668
  }
3614
3669
  } else {
3615
3670
  isLoadingSetter(originalScope, false);
3671
+ cancelPreviousTimeout();
3616
3672
  resetMatches();
3617
3673
  }
3618
3674
 
@@ -3820,7 +3876,7 @@ angular.module("template/accordion/accordion.html", []).run(["$templateCache", f
3820
3876
 
3821
3877
  angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
3822
3878
  $templateCache.put("template/alert/alert.html",
3823
- "<div class=\"alert\" ng-class=\"{'alert-{{type || 'warning'}}': true, 'alert-dismissable': closeable}\" role=\"alert\">\n" +
3879
+ "<div class=\"alert\" ng-class=\"['alert-' + (type || 'warning'), closeable ? 'alert-dismissable' : null]\" role=\"alert\">\n" +
3824
3880
  " <button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close()\">\n" +
3825
3881
  " <span aria-hidden=\"true\">&times;</span>\n" +
3826
3882
  " <span class=\"sr-only\">Close</span>\n" +
@@ -3949,7 +4005,7 @@ angular.module("template/datepicker/year.html", []).run(["$templateCache", funct
3949
4005
 
3950
4006
  angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
3951
4007
  $templateCache.put("template/modal/backdrop.html",
3952
- "<div class=\"modal-backdrop fade\"\n" +
4008
+ "<div class=\"modal-backdrop fade {{ backdropClass }}\"\n" +
3953
4009
  " ng-class=\"{in: animate}\"\n" +
3954
4010
  " ng-style=\"{'z-index': 1040 + (index && 1 || 0) + index*10}\"\n" +
3955
4011
  "></div>\n" +
@@ -3959,7 +4015,7 @@ angular.module("template/modal/backdrop.html", []).run(["$templateCache", functi
3959
4015
  angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
3960
4016
  $templateCache.put("template/modal/window.html",
3961
4017
  "<div tabindex=\"-1\" role=\"dialog\" class=\"modal fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
3962
- " <div class=\"modal-dialog\" ng-class=\"{'modal-sm': size == 'sm', 'modal-lg': size == 'lg'}\"><div class=\"modal-content\" ng-transclude></div></div>\n" +
4018
+ " <div class=\"modal-dialog\" ng-class=\"{'modal-sm': size == 'sm', 'modal-lg': size == 'lg'}\"><div class=\"modal-content\" modal-transclude></div></div>\n" +
3963
4019
  "</div>");
3964
4020
  }]);
3965
4021
 
@@ -4047,16 +4103,8 @@ angular.module("template/tabs/tab.html", []).run(["$templateCache", function($te
4047
4103
  "");
4048
4104
  }]);
4049
4105
 
4050
- angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
4051
- $templateCache.put("template/tabs/tabset-titles.html",
4052
- "<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n" +
4053
- "</ul>\n" +
4054
- "");
4055
- }]);
4056
-
4057
4106
  angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
4058
4107
  $templateCache.put("template/tabs/tabset.html",
4059
- "\n" +
4060
4108
  "<div>\n" +
4061
4109
  " <ul class=\"nav nav-{{type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
4062
4110
  " <div class=\"tab-content\">\n" +
@@ -4108,9 +4156,10 @@ angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCac
4108
4156
 
4109
4157
  angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
4110
4158
  $templateCache.put("template/typeahead/typeahead-popup.html",
4111
- "<ul class=\"dropdown-menu\" ng-if=\"isOpen()\" ng-style=\"{top: position.top+'px', left: position.left+'px'}\" style=\"display: block;\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
4159
+ "<ul class=\"dropdown-menu\" ng-show=\"isOpen()\" ng-style=\"{top: position.top+'px', left: position.left+'px'}\" style=\"display: block;\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
4112
4160
  " <li ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index)\" role=\"option\" id=\"{{match.id}}\">\n" +
4113
4161
  " <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
4114
4162
  " </li>\n" +
4115
- "</ul>");
4163
+ "</ul>\n" +
4164
+ "");
4116
4165
  }]);
@@ -2,7 +2,7 @@
2
2
  * angular-ui-bootstrap
3
3
  * http://angular-ui.github.io/bootstrap/
4
4
 
5
- * Version: 0.11.0 - 2014-05-01
5
+ * Version: 0.11.1 - 2014-09-26
6
6
  * License: MIT
7
7
  */
8
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.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","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"]);
@@ -746,7 +746,7 @@ angular.module('ui.bootstrap.dateparser', [])
746
746
  }
747
747
  };
748
748
 
749
- this.createParser = function(format) {
749
+ function createParser(format) {
750
750
  var map = [], regex = format.split('');
751
751
 
752
752
  angular.forEach(formatCodeToRegex, function(data, code) {
@@ -771,17 +771,17 @@ angular.module('ui.bootstrap.dateparser', [])
771
771
  regex: new RegExp('^' + regex.join('') + '$'),
772
772
  map: orderByFilter(map, 'index')
773
773
  };
774
- };
774
+ }
775
775
 
776
776
  this.parse = function(input, format) {
777
- if ( !angular.isString(input) ) {
777
+ if ( !angular.isString(input) || !format ) {
778
778
  return input;
779
779
  }
780
780
 
781
781
  format = $locale.DATETIME_FORMATS[format] || format;
782
782
 
783
783
  if ( !this.parsers[format] ) {
784
- this.parsers[format] = this.createParser(format);
784
+ this.parsers[format] = createParser(format);
785
785
  }
786
786
 
787
787
  var parser = this.parsers[format],
@@ -1007,7 +1007,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1007
1007
  self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];
1008
1008
  });
1009
1009
 
1010
- // Watchable attributes
1010
+ // Watchable date attributes
1011
1011
  angular.forEach(['minDate', 'maxDate'], function( key ) {
1012
1012
  if ( $attrs[key] ) {
1013
1013
  $scope.$parent.$watch($parse($attrs[key]), function(value) {
@@ -1454,12 +1454,24 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1454
1454
  });
1455
1455
  }
1456
1456
 
1457
- angular.forEach(['minDate', 'maxDate'], function( key ) {
1457
+ scope.watchData = {};
1458
+ angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) {
1458
1459
  if ( attrs[key] ) {
1459
- scope.$parent.$watch($parse(attrs[key]), function(value){
1460
- scope[key] = value;
1460
+ var getAttribute = $parse(attrs[key]);
1461
+ scope.$parent.$watch(getAttribute, function(value){
1462
+ scope.watchData[key] = value;
1461
1463
  });
1462
- datepickerEl.attr(cameltoDash(key), key);
1464
+ datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
1465
+
1466
+ // Propagate changes from datepicker to outside
1467
+ if ( key === 'datepickerMode' ) {
1468
+ var setAttribute = getAttribute.assign;
1469
+ scope.$watch('watchData.' + key, function(value, oldvalue) {
1470
+ if ( value !== oldvalue ) {
1471
+ setAttribute(scope.$parent, value);
1472
+ }
1473
+ });
1474
+ }
1463
1475
  }
1464
1476
  });
1465
1477
  if (attrs.dateDisabled) {
@@ -1570,6 +1582,9 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1570
1582
  };
1571
1583
 
1572
1584
  var $popup = $compile(popupEl)(scope);
1585
+ // Prevent jQuery cache memory leak (template is now redundant after linking)
1586
+ popupEl.remove();
1587
+
1573
1588
  if ( appendToBody ) {
1574
1589
  $document.find('body').append($popup);
1575
1590
  } else {
@@ -1631,7 +1646,8 @@ angular.module('ui.bootstrap.dropdown', [])
1631
1646
  };
1632
1647
 
1633
1648
  var closeDropdown = function( evt ) {
1634
- if (evt && evt.isDefaultPrevented()) {
1649
+ var toggleElement = openScope.getToggleElement();
1650
+ if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {
1635
1651
  return;
1636
1652
  }
1637
1653
 
@@ -1678,6 +1694,10 @@ angular.module('ui.bootstrap.dropdown', [])
1678
1694
  return scope.isOpen;
1679
1695
  };
1680
1696
 
1697
+ scope.getToggleElement = function() {
1698
+ return self.toggleElement;
1699
+ };
1700
+
1681
1701
  scope.focusToggleElement = function() {
1682
1702
  if ( self.toggleElement ) {
1683
1703
  self.toggleElement[0].focus();
@@ -1711,7 +1731,6 @@ angular.module('ui.bootstrap.dropdown', [])
1711
1731
 
1712
1732
  .directive('dropdown', function() {
1713
1733
  return {
1714
- restrict: 'CA',
1715
1734
  controller: 'DropdownController',
1716
1735
  link: function(scope, element, attrs, dropdownCtrl) {
1717
1736
  dropdownCtrl.init( element );
@@ -1721,7 +1740,6 @@ angular.module('ui.bootstrap.dropdown', [])
1721
1740
 
1722
1741
  .directive('dropdownToggle', function() {
1723
1742
  return {
1724
- restrict: 'CA',
1725
1743
  require: '?^dropdown',
1726
1744
  link: function(scope, element, attrs, dropdownCtrl) {
1727
1745
  if ( !dropdownCtrl ) {
@@ -1819,7 +1837,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1819
1837
  restrict: 'EA',
1820
1838
  replace: true,
1821
1839
  templateUrl: 'template/modal/backdrop.html',
1822
- link: function (scope) {
1840
+ link: function (scope, element, attrs) {
1841
+ scope.backdropClass = attrs.backdropClass || '';
1823
1842
 
1824
1843
  scope.animate = false;
1825
1844
 
@@ -1850,8 +1869,18 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1850
1869
  $timeout(function () {
1851
1870
  // trigger CSS transitions
1852
1871
  scope.animate = true;
1853
- // focus a freshly-opened modal
1854
- element[0].focus();
1872
+
1873
+ /**
1874
+ * Auto-focusing of a freshly-opened modal element causes any child elements
1875
+ * with the autofocus attribute to loose focus. This is an issue on touch
1876
+ * based devices which will show and then hide the onscreen keyboard.
1877
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
1878
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
1879
+ * the modal element if the modal does not contain an autofocus element.
1880
+ */
1881
+ if (!element[0].querySelectorAll('[autofocus]').length) {
1882
+ element[0].focus();
1883
+ }
1855
1884
  });
1856
1885
 
1857
1886
  scope.close = function (evt) {
@@ -1866,6 +1895,17 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1866
1895
  };
1867
1896
  }])
1868
1897
 
1898
+ .directive('modalTransclude', function () {
1899
+ return {
1900
+ link: function($scope, $element, $attrs, controller, $transclude) {
1901
+ $transclude($scope.$parent, function(clone) {
1902
+ $element.empty();
1903
+ $element.append(clone);
1904
+ });
1905
+ }
1906
+ };
1907
+ })
1908
+
1869
1909
  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
1870
1910
  function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1871
1911
 
@@ -1937,7 +1977,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1937
1977
  });
1938
1978
  } else {
1939
1979
  // Ensure this call is async
1940
- $timeout(afterAnimating, 0);
1980
+ $timeout(afterAnimating);
1941
1981
  }
1942
1982
 
1943
1983
  function afterAnimating() {
@@ -1982,7 +2022,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1982
2022
  if (currBackdropIndex >= 0 && !backdropDomEl) {
1983
2023
  backdropScope = $rootScope.$new(true);
1984
2024
  backdropScope.index = currBackdropIndex;
1985
- backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
2025
+ var angularBackgroundDomEl = angular.element('<div modal-backdrop></div>');
2026
+ angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
2027
+ backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
1986
2028
  body.append(backdropDomEl);
1987
2029
  }
1988
2030
 
@@ -2002,17 +2044,17 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2002
2044
  };
2003
2045
 
2004
2046
  $modalStack.close = function (modalInstance, result) {
2005
- var modalWindow = openedWindows.get(modalInstance).value;
2047
+ var modalWindow = openedWindows.get(modalInstance);
2006
2048
  if (modalWindow) {
2007
- modalWindow.deferred.resolve(result);
2049
+ modalWindow.value.deferred.resolve(result);
2008
2050
  removeModalWindow(modalInstance);
2009
2051
  }
2010
2052
  };
2011
2053
 
2012
2054
  $modalStack.dismiss = function (modalInstance, reason) {
2013
- var modalWindow = openedWindows.get(modalInstance).value;
2055
+ var modalWindow = openedWindows.get(modalInstance);
2014
2056
  if (modalWindow) {
2015
- modalWindow.deferred.reject(reason);
2057
+ modalWindow.value.deferred.reject(reason);
2016
2058
  removeModalWindow(modalInstance);
2017
2059
  }
2018
2060
  };
@@ -2046,14 +2088,15 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2046
2088
 
2047
2089
  function getTemplatePromise(options) {
2048
2090
  return options.template ? $q.when(options.template) :
2049
- $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
2050
- return result.data;
2091
+ $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl,
2092
+ {cache: $templateCache}).then(function (result) {
2093
+ return result.data;
2051
2094
  });
2052
2095
  }
2053
2096
 
2054
2097
  function getResolvePromises(resolves) {
2055
2098
  var promisesArr = [];
2056
- angular.forEach(resolves, function (value, key) {
2099
+ angular.forEach(resolves, function (value) {
2057
2100
  if (angular.isFunction(value) || angular.isArray(value)) {
2058
2101
  promisesArr.push($q.when($injector.invoke(value)));
2059
2102
  }
@@ -2109,6 +2152,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2109
2152
  });
2110
2153
 
2111
2154
  ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
2155
+ if (modalOptions.controllerAs) {
2156
+ modalScope[modalOptions.controllerAs] = ctrlInstance;
2157
+ }
2112
2158
  }
2113
2159
 
2114
2160
  $modalStack.open(modalInstance, {
@@ -2117,6 +2163,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2117
2163
  content: tplAndVars[0],
2118
2164
  backdrop: modalOptions.backdrop,
2119
2165
  keyboard: modalOptions.keyboard,
2166
+ backdropClass: modalOptions.backdropClass,
2120
2167
  windowClass: modalOptions.windowClass,
2121
2168
  windowTemplateUrl: modalOptions.windowTemplateUrl,
2122
2169
  size: modalOptions.size
@@ -3427,7 +3474,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3427
3474
  .factory('typeaheadParser', ['$parse', function ($parse) {
3428
3475
 
3429
3476
  // 00000111000000000000022200000000000000003333333333333330000000000044000
3430
- var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;
3477
+ var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
3431
3478
 
3432
3479
  return {
3433
3480
  parse:function (input) {
@@ -3593,6 +3640,18 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3593
3640
  //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
3594
3641
  var timeoutPromise;
3595
3642
 
3643
+ var scheduleSearchWithTimeout = function(inputValue) {
3644
+ timeoutPromise = $timeout(function () {
3645
+ getMatchesAsync(inputValue);
3646
+ }, waitTime);
3647
+ };
3648
+
3649
+ var cancelPreviousTimeout = function() {
3650
+ if (timeoutPromise) {
3651
+ $timeout.cancel(timeoutPromise);
3652
+ }
3653
+ };
3654
+
3596
3655
  //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
3597
3656
  //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
3598
3657
  modelCtrl.$parsers.unshift(function (inputValue) {
@@ -3601,17 +3660,14 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3601
3660
 
3602
3661
  if (inputValue && inputValue.length >= minSearch) {
3603
3662
  if (waitTime > 0) {
3604
- if (timeoutPromise) {
3605
- $timeout.cancel(timeoutPromise);//cancel previous timeout
3606
- }
3607
- timeoutPromise = $timeout(function () {
3608
- getMatchesAsync(inputValue);
3609
- }, waitTime);
3663
+ cancelPreviousTimeout();
3664
+ scheduleSearchWithTimeout(inputValue);
3610
3665
  } else {
3611
3666
  getMatchesAsync(inputValue);
3612
3667
  }
3613
3668
  } else {
3614
3669
  isLoadingSetter(originalScope, false);
3670
+ cancelPreviousTimeout();
3615
3671
  resetMatches();
3616
3672
  }
3617
3673
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: angular-ui-bootstrap-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Constantin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-09 00:00:00.000000000 Z
11
+ date: 2014-09-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Injects Angular.js UI Bootstrap directives into your asset pipeline.
14
14
  email: chris@chrisconstantin.net
@@ -16,12 +16,12 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
- - lib/angular-ui-bootstrap-rails/version.rb
19
+ - MIT-LICENSE
20
+ - README.md
20
21
  - lib/angular-ui-bootstrap-rails.rb
22
+ - lib/angular-ui-bootstrap-rails/version.rb
21
23
  - vendor/assets/javascripts/angular-ui-bootstrap-tpls.js
22
24
  - vendor/assets/javascripts/angular-ui-bootstrap.js
23
- - MIT-LICENSE
24
- - README.md
25
25
  homepage: https://github.com/cconstantin/angular-ui-bootstrap-rails/
26
26
  licenses:
27
27
  - MIT
@@ -32,17 +32,17 @@ require_paths:
32
32
  - lib
33
33
  required_ruby_version: !ruby/object:Gem::Requirement
34
34
  requirements:
35
- - - '>='
35
+ - - ">="
36
36
  - !ruby/object:Gem::Version
37
37
  version: '0'
38
38
  required_rubygems_version: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - '>='
40
+ - - ">="
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0'
43
43
  requirements: []
44
44
  rubyforge_project:
45
- rubygems_version: 2.0.14
45
+ rubygems_version: 2.2.2
46
46
  signing_key:
47
47
  specification_version: 4
48
48
  summary: Angular.js UI Bootstrap on Rails