rails-angular-strap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +21 -0
  4. data/lib/rails-angular-strap.rb +11 -0
  5. data/lib/rails-angular-strap/engine.rb +4 -0
  6. data/lib/rails-angular-strap/version.rb +4 -0
  7. data/vendor/assets/javascripts/angular-strap.js +2 -0
  8. data/vendor/assets/javascripts/angular-strap.min.js +2 -0
  9. data/vendor/assets/javascripts/angular-strap/angular-strap.js +5014 -0
  10. data/vendor/assets/javascripts/angular-strap/angular-strap.min.js +11 -0
  11. data/vendor/assets/javascripts/angular-strap/angular-strap.tpl.js +89 -0
  12. data/vendor/assets/javascripts/angular-strap/angular-strap.tpl.min.js +8 -0
  13. data/vendor/assets/javascripts/angular-strap/modules/affix.js +249 -0
  14. data/vendor/assets/javascripts/angular-strap/modules/affix.min.js +9 -0
  15. data/vendor/assets/javascripts/angular-strap/modules/affix.min.js.map +1 -0
  16. data/vendor/assets/javascripts/angular-strap/modules/alert.js +120 -0
  17. data/vendor/assets/javascripts/angular-strap/modules/alert.min.js +9 -0
  18. data/vendor/assets/javascripts/angular-strap/modules/alert.min.js.map +1 -0
  19. data/vendor/assets/javascripts/angular-strap/modules/alert.tpl.js +14 -0
  20. data/vendor/assets/javascripts/angular-strap/modules/alert.tpl.min.js +8 -0
  21. data/vendor/assets/javascripts/angular-strap/modules/aside.js +96 -0
  22. data/vendor/assets/javascripts/angular-strap/modules/aside.min.js +9 -0
  23. data/vendor/assets/javascripts/angular-strap/modules/aside.min.js.map +1 -0
  24. data/vendor/assets/javascripts/angular-strap/modules/aside.tpl.js +14 -0
  25. data/vendor/assets/javascripts/angular-strap/modules/aside.tpl.min.js +8 -0
  26. data/vendor/assets/javascripts/angular-strap/modules/button.js +177 -0
  27. data/vendor/assets/javascripts/angular-strap/modules/button.min.js +9 -0
  28. data/vendor/assets/javascripts/angular-strap/modules/button.min.js.map +1 -0
  29. data/vendor/assets/javascripts/angular-strap/modules/collapse.js +273 -0
  30. data/vendor/assets/javascripts/angular-strap/modules/collapse.min.js +9 -0
  31. data/vendor/assets/javascripts/angular-strap/modules/collapse.min.js.map +1 -0
  32. data/vendor/assets/javascripts/angular-strap/modules/date-formatter.js +61 -0
  33. data/vendor/assets/javascripts/angular-strap/modules/date-formatter.min.js +9 -0
  34. data/vendor/assets/javascripts/angular-strap/modules/date-formatter.min.js.map +1 -0
  35. data/vendor/assets/javascripts/angular-strap/modules/date-parser.js +273 -0
  36. data/vendor/assets/javascripts/angular-strap/modules/date-parser.min.js +9 -0
  37. data/vendor/assets/javascripts/angular-strap/modules/date-parser.min.js.map +1 -0
  38. data/vendor/assets/javascripts/angular-strap/modules/datepicker.js +640 -0
  39. data/vendor/assets/javascripts/angular-strap/modules/datepicker.min.js +9 -0
  40. data/vendor/assets/javascripts/angular-strap/modules/datepicker.min.js.map +1 -0
  41. data/vendor/assets/javascripts/angular-strap/modules/datepicker.tpl.js +14 -0
  42. data/vendor/assets/javascripts/angular-strap/modules/datepicker.tpl.min.js +8 -0
  43. data/vendor/assets/javascripts/angular-strap/modules/debounce.js +62 -0
  44. data/vendor/assets/javascripts/angular-strap/modules/debounce.min.js +9 -0
  45. data/vendor/assets/javascripts/angular-strap/modules/debounce.min.js.map +1 -0
  46. data/vendor/assets/javascripts/angular-strap/modules/dimensions.js +156 -0
  47. data/vendor/assets/javascripts/angular-strap/modules/dimensions.min.js +9 -0
  48. data/vendor/assets/javascripts/angular-strap/modules/dimensions.min.js.map +1 -0
  49. data/vendor/assets/javascripts/angular-strap/modules/dropdown.js +149 -0
  50. data/vendor/assets/javascripts/angular-strap/modules/dropdown.min.js +9 -0
  51. data/vendor/assets/javascripts/angular-strap/modules/dropdown.min.js.map +1 -0
  52. data/vendor/assets/javascripts/angular-strap/modules/dropdown.tpl.js +14 -0
  53. data/vendor/assets/javascripts/angular-strap/modules/dropdown.tpl.min.js +8 -0
  54. data/vendor/assets/javascripts/angular-strap/modules/modal.js +349 -0
  55. data/vendor/assets/javascripts/angular-strap/modules/modal.min.js +9 -0
  56. data/vendor/assets/javascripts/angular-strap/modules/modal.min.js.map +1 -0
  57. data/vendor/assets/javascripts/angular-strap/modules/modal.tpl.js +14 -0
  58. data/vendor/assets/javascripts/angular-strap/modules/modal.tpl.min.js +8 -0
  59. data/vendor/assets/javascripts/angular-strap/modules/navbar.js +72 -0
  60. data/vendor/assets/javascripts/angular-strap/modules/navbar.min.js +9 -0
  61. data/vendor/assets/javascripts/angular-strap/modules/navbar.min.js.map +1 -0
  62. data/vendor/assets/javascripts/angular-strap/modules/parse-options.js +76 -0
  63. data/vendor/assets/javascripts/angular-strap/modules/parse-options.min.js +9 -0
  64. data/vendor/assets/javascripts/angular-strap/modules/parse-options.min.js.map +1 -0
  65. data/vendor/assets/javascripts/angular-strap/modules/popover.js +112 -0
  66. data/vendor/assets/javascripts/angular-strap/modules/popover.min.js +9 -0
  67. data/vendor/assets/javascripts/angular-strap/modules/popover.min.js.map +1 -0
  68. data/vendor/assets/javascripts/angular-strap/modules/popover.tpl.js +14 -0
  69. data/vendor/assets/javascripts/angular-strap/modules/popover.tpl.min.js +8 -0
  70. data/vendor/assets/javascripts/angular-strap/modules/raf.js +61 -0
  71. data/vendor/assets/javascripts/angular-strap/modules/raf.min.js +9 -0
  72. data/vendor/assets/javascripts/angular-strap/modules/raf.min.js.map +1 -0
  73. data/vendor/assets/javascripts/angular-strap/modules/scrollspy.js +261 -0
  74. data/vendor/assets/javascripts/angular-strap/modules/scrollspy.min.js +9 -0
  75. data/vendor/assets/javascripts/angular-strap/modules/scrollspy.min.js.map +1 -0
  76. data/vendor/assets/javascripts/angular-strap/modules/select.js +325 -0
  77. data/vendor/assets/javascripts/angular-strap/modules/select.min.js +9 -0
  78. data/vendor/assets/javascripts/angular-strap/modules/select.min.js.map +1 -0
  79. data/vendor/assets/javascripts/angular-strap/modules/select.tpl.js +14 -0
  80. data/vendor/assets/javascripts/angular-strap/modules/select.tpl.min.js +8 -0
  81. data/vendor/assets/javascripts/angular-strap/modules/tab.js +186 -0
  82. data/vendor/assets/javascripts/angular-strap/modules/tab.min.js +9 -0
  83. data/vendor/assets/javascripts/angular-strap/modules/tab.min.js.map +1 -0
  84. data/vendor/assets/javascripts/angular-strap/modules/tab.tpl.js +14 -0
  85. data/vendor/assets/javascripts/angular-strap/modules/tab.tpl.min.js +8 -0
  86. data/vendor/assets/javascripts/angular-strap/modules/timepicker.js +485 -0
  87. data/vendor/assets/javascripts/angular-strap/modules/timepicker.min.js +9 -0
  88. data/vendor/assets/javascripts/angular-strap/modules/timepicker.min.js.map +1 -0
  89. data/vendor/assets/javascripts/angular-strap/modules/timepicker.tpl.js +14 -0
  90. data/vendor/assets/javascripts/angular-strap/modules/timepicker.tpl.min.js +8 -0
  91. data/vendor/assets/javascripts/angular-strap/modules/tooltip.js +690 -0
  92. data/vendor/assets/javascripts/angular-strap/modules/tooltip.min.js +9 -0
  93. data/vendor/assets/javascripts/angular-strap/modules/tooltip.min.js.map +1 -0
  94. data/vendor/assets/javascripts/angular-strap/modules/tooltip.tpl.js +14 -0
  95. data/vendor/assets/javascripts/angular-strap/modules/tooltip.tpl.min.js +8 -0
  96. data/vendor/assets/javascripts/angular-strap/modules/typeahead.js +266 -0
  97. data/vendor/assets/javascripts/angular-strap/modules/typeahead.min.js +9 -0
  98. data/vendor/assets/javascripts/angular-strap/modules/typeahead.min.js.map +1 -0
  99. data/vendor/assets/javascripts/angular-strap/modules/typeahead.tpl.js +14 -0
  100. data/vendor/assets/javascripts/angular-strap/modules/typeahead.tpl.min.js +8 -0
  101. metadata +143 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ "use strict";angular.module("mgcrea.ngStrap.collapse",[]).provider("$collapse",function(){var e=this.defaults={animation:"am-collapse",disallowToggle:!1,activeClass:"in",startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,a,n){function i(e){for(var t=o.$targets.$active,a=0;a<t.length;a++)e<t[a]&&(t[a]=t[a]-1),t[a]===o.$targets.length&&(t[a]=o.$targets.length-1)}function s(e){var t=o.$targets.$active;return-1===t.indexOf(e)?!1:!0}function r(e){var t=o.$targets.$active.indexOf(e);-1!==t&&o.$targets.$active.splice(t,1)}function l(e){o.$options.allowMultiple||o.$targets.$active.splice(0,1),-1===o.$targets.$active.indexOf(e)&&o.$targets.$active.push(e)}var o=this;o.$options=angular.copy(e),angular.forEach(["animation","disallowToggle","activeClass","startCollapsed","allowMultiple"],function(e){angular.isDefined(n[e])&&(o.$options[e]=n[e])}),o.$toggles=[],o.$targets=[],o.$viewChangeListeners=[],o.$registerToggle=function(e){o.$toggles.push(e)},o.$registerTarget=function(e){o.$targets.push(e)},o.$unregisterToggle=function(e){var t=o.$toggles.indexOf(e);o.$toggles.splice(t,1)},o.$unregisterTarget=function(e){var t=o.$targets.indexOf(e);o.$targets.splice(t,1),o.$options.allowMultiple&&r(e),i(t),o.$viewChangeListeners.forEach(function(e){e()})},o.$targets.$active=o.$options.startCollapsed?[]:[0],o.$setActive=t.$setActive=function(e){angular.isArray(e)?o.$targets.$active=angular.copy(e):o.$options.disallowToggle?l(e):s(e)?r(e):l(e),o.$viewChangeListeners.forEach(function(e){e()})},o.$activeIndexes=function(){return o.$options.allowMultiple?o.$targets.$active:1===o.$targets.$active.length?o.$targets.$active[0]:-1}};this.$get=function(){var a={};return a.defaults=e,a.controller=t,a}}).directive("bsCollapse",["$window","$animate","$collapse",function(e,t,a){a.defaults;return{require:["?ngModel","bsCollapse"],controller:["$scope","$element","$attrs",a.controller],link:function(e,t,a,n){var i=n[0],s=n[1];i&&(s.$viewChangeListeners.push(function(){i.$setViewValue(s.$activeIndexes())}),i.$formatters.push(function(e){if(angular.isArray(e))s.$setActive(e);else{var t=s.$activeIndexes();angular.isArray(t)?-1===t.indexOf(1*e)&&s.$setActive(1*e):t!==1*e&&s.$setActive(1*e)}return e}))}}}]).directive("bsCollapseToggle",function(){return{require:["^?ngModel","^bsCollapse"],link:function(e,t,a,n){var i=(n[0],n[1]);t.attr("data-toggle","collapse"),i.$registerToggle(t),e.$on("$destroy",function(){i.$unregisterToggle(t)}),t.on("click",function(){var n=a.bsCollapseToggle||i.$toggles.indexOf(t);i.$setActive(1*n),e.$apply()})}}}).directive("bsCollapseTarget",["$animate",function(e){return{require:["^?ngModel","^bsCollapse"],link:function(t,a,n,i){function s(){var t=r.$targets.indexOf(a),n=r.$activeIndexes(),i="removeClass";angular.isArray(n)?-1!==n.indexOf(t)&&(i="addClass"):t===n&&(i="addClass"),e[i](a,r.$options.activeClass)}var r=(i[0],i[1]);a.addClass("collapse"),r.$options.animation&&a.addClass(r.$options.animation),r.$registerTarget(a),t.$on("$destroy",function(){r.$unregisterTarget(a)}),r.$viewChangeListeners.push(function(){s()}),s()}}}]);
9
+ //# sourceMappingURL=collapse.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["collapse/collapse.js"],"names":[],"mappings":"qBASM,OAAA,uCAEA,YAAe,gCAGjB,UAAI,cACF,gBAAW,qCAGX,eAAK,uDA2ED,yBAAI,EAAA,EAAA,EAAA,EAA0B,OAAS,IACrC,EAAA,EAAwB,kBAMxB,EAAc,KAAK,EAAS,SAAA,SAChC,EAAO,GAAY,EAAQ,SAAA,OAAgB,WAKvC,GAAW,MACb,GAAc,EAAA,SAAe,sCAIjC,QAAS,GAAa,GACpB,GAAI,GAAM,EAAA,SAAS,QAAe,QAAA,WAEhC,EAAK,SAAS,QAAQ,OAAO,EAAG,WAI3B,GAAS,4DAMG,KAAlB,EAAO,SAAA,QAAW,QAAA,IACjB,EAAA,SAAY,QAAA,KAAA,yCAnGhB,QAAK,SAAA,YAAuB,iBAAA,cAAA,iBAAA,iBAAA,SAAA,iEAK5B,EAAK,sCAIL,EAAK,gBAAA,SAAoB,GACvB,EAAI,SAAQ,KAAK,MAEjB,gBAAqB,SAAO,8IAU1B,GAAA,EAAe,SAAA,QAAA,oDAOf,EAAA,QAMJ,EAAK,qBAAoB,QAAA,SAAa,GACpC,SAKE,SAAS,QAAS,EAAA,SAAe,mBAAS,gBACrC,EAAA,WAAA,SAAA,GACL,QAAA,QAAa,sCAGV,EAAA,SAAA,qCAOH,qBAAsB,QAAA,SAAe,sCAMvC,MAAI,GAAA,SAAgB,cAAc,EAAA,SAAA,QACD,IAAjC,EAAI,SAAW,QAAI,OAAc,EAAQ,SAAK,QAAA,GAAA,kCAiDlD,OAFD,GAAU,SAAA,iBAEL,eAKI,cAAS,UAAgB,WAAS,YAAO,SAAa,EAAA,EAAA,GAEtD,EAAc,yBAGf,WAAa,+FAIZ,GAAY,EAAc,gBAMd,qBAAqB,KAAA,mDAK5B,YAAA,KAAA,SAAA,2BAKG,WAAc,yCAKX,QAAA,wBAIX,EAAO,WAAA,EAAA,yDAiBP,mBAAiB,2BAGb,YAAK,sCAGb,OAAe,EAAA,WAIb,KAAA,cAAe,YAGjB,EAAW,gBAAoB,KAG7B,IAAM,WAAA,yJAeJ,oBAAc,WAAY,SAAA,gHA4BnB,EAAkB,iBACzB,EAAS,qDAGX,EAAS,YAGX,IAAe,IACb,EAAA,2CA7BF,GACE,IADgB,EAAS,GACR,EAAA,iDAOnB,EAAU,SAAA,EAAuB,SAAA,WAIjC,EAAS,gBAAS,KAGZ,IAAA,WAAS,WACb,EAAY,kBAAiB,4CAoBlC","file":"collapse.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = angular.copy(value);\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+
10
+ angular.module('mgcrea.ngStrap.helpers.dateFormatter', [])
11
+
12
+ .service('$dateFormatter', ["$locale", "dateFilter", function($locale, dateFilter) {
13
+
14
+ // The unused `lang` arguments are on purpose. The default implementation does not
15
+ // use them and it always uses the locale loaded into the `$locale` service.
16
+ // Custom implementations might use it, thus allowing different directives to
17
+ // have different languages.
18
+
19
+ this.getDefaultLocale = function() {
20
+ return $locale.id;
21
+ };
22
+
23
+ // Format is either a data format name, e.g. "shortTime" or "fullDate", or a date format
24
+ // Return either the corresponding date format or the given date format.
25
+ this.getDatetimeFormat = function(format, lang) {
26
+ return $locale.DATETIME_FORMATS[format] || format;
27
+ };
28
+
29
+ this.weekdaysShort = function(lang) {
30
+ return $locale.DATETIME_FORMATS.SHORTDAY;
31
+ };
32
+
33
+ function splitTimeFormat(format) {
34
+ return /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);
35
+ }
36
+
37
+ // h:mm a => h
38
+ this.hoursFormat = function(timeFormat) {
39
+ return splitTimeFormat(timeFormat)[0];
40
+ };
41
+
42
+ // h:mm a => mm
43
+ this.minutesFormat = function(timeFormat) {
44
+ return splitTimeFormat(timeFormat)[2];
45
+ };
46
+
47
+ // h:mm a => :
48
+ this.timeSeparator = function(timeFormat) {
49
+ return splitTimeFormat(timeFormat)[1];
50
+ };
51
+
52
+ // h:mm a => true, H.mm => false
53
+ this.showAM = function(timeFormat) {
54
+ return !!splitTimeFormat(timeFormat)[3];
55
+ };
56
+
57
+ this.formatDate = function(date, format, lang){
58
+ return dateFilter(date, format);
59
+ };
60
+
61
+ }]);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ "use strict";angular.module("mgcrea.ngStrap.helpers.dateFormatter",[]).service("$dateFormatter",["$locale","dateFilter",function(t,e){function r(t){return/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(t).slice(1)}this.getDefaultLocale=function(){return t.id},this.getDatetimeFormat=function(e){return t.DATETIME_FORMATS[e]||e},this.weekdaysShort=function(){return t.DATETIME_FORMATS.SHORTDAY},this.hoursFormat=function(t){return r(t)[0]},this.minutesFormat=function(t){return r(t)[2]},this.timeSeparator=function(t){return r(t)[1]},this.showAM=function(t){return!!r(t)[3]},this.formatDate=function(t,r){return e(t,r)}}]);
9
+ //# sourceMappingURL=date-formatter.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["helpers/date-formatter.js"],"names":[],"mappings":"+EAWS,kBAAmB,UAAW,aAAA,SAAA,EAAA,yEAOjC,iBAAe,2DAOjB,MAAS,GAAA,iBAAwB,IAAA,wOA4BhC,QAAA,EAAA,GAAA","file":"date-formatter.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[3];\n };\n\n this.formatDate = function(date, format, lang){\n return dateFilter(date, format);\n };\n\n });\n"],"sourceRoot":"/source/"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+
10
+ angular.module('mgcrea.ngStrap.helpers.dateParser', [])
11
+
12
+ .provider('$dateParser', ["$localeProvider", function($localeProvider) {
13
+
14
+ // define a custom ParseDate object to use instead of native Date
15
+ // to avoid date values wrapping when setting date component values
16
+ function ParseDate() {
17
+ this.year = 1970;
18
+ this.month = 0;
19
+ this.day = 1;
20
+ this.hours = 0;
21
+ this.minutes = 0;
22
+ this.seconds = 0;
23
+ this.milliseconds = 0;
24
+ }
25
+
26
+ ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };
27
+ ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };
28
+ ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };
29
+ ParseDate.prototype.setHours = function(value) { this.hours = value; };
30
+ ParseDate.prototype.getHours = function() { return this.hours; };
31
+ ParseDate.prototype.setDate = function(value) { this.day = value; };
32
+ ParseDate.prototype.setMonth = function(value) { this.month = value; };
33
+ ParseDate.prototype.setFullYear = function(value) { this.year = value; };
34
+ ParseDate.prototype.fromDate = function(value) {
35
+ this.year = value.getFullYear();
36
+ this.month = value.getMonth();
37
+ this.day = value.getDate();
38
+ this.hours = value.getHours();
39
+ this.minutes = value.getMinutes();
40
+ this.seconds = value.getSeconds();
41
+ this.milliseconds = value.getMilliseconds();
42
+ return this;
43
+ };
44
+
45
+ ParseDate.prototype.toDate = function() {
46
+ return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);
47
+ };
48
+
49
+ var proto = ParseDate.prototype;
50
+
51
+ function noop() {
52
+ }
53
+
54
+ function isNumeric(n) {
55
+ return !isNaN(parseFloat(n)) && isFinite(n);
56
+ }
57
+
58
+ function indexOfCaseInsensitive(array, value) {
59
+ var len = array.length, str=value.toString().toLowerCase();
60
+ for (var i=0; i<len; i++) {
61
+ if (array[i].toLowerCase() === str) { return i; }
62
+ }
63
+ return -1; // Return -1 per the "Array.indexOf()" method.
64
+ }
65
+
66
+ var defaults = this.defaults = {
67
+ format: 'shortDate',
68
+ strict: false
69
+ };
70
+
71
+ this.$get = ["$locale", "dateFilter", function($locale, dateFilter) {
72
+
73
+ var DateParserFactory = function(config) {
74
+
75
+ var options = angular.extend({}, defaults, config);
76
+
77
+ var $dateParser = {};
78
+
79
+ var regExpMap = {
80
+ 'sss' : '[0-9]{3}',
81
+ 'ss' : '[0-5][0-9]',
82
+ 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',
83
+ 'mm' : '[0-5][0-9]',
84
+ 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',
85
+ 'HH' : '[01][0-9]|2[0-3]',
86
+ 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',
87
+ 'hh' : '[0][1-9]|[1][012]',
88
+ 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',
89
+ 'a' : 'AM|PM',
90
+ 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),
91
+ 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
92
+ 'dd' : '0[1-9]|[12][0-9]|3[01]',
93
+ 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',
94
+ 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),
95
+ 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
96
+ 'MM' : '0[1-9]|1[012]',
97
+ 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',
98
+ 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',
99
+ 'yy' : '[0-9]{2}',
100
+ 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',
101
+ };
102
+
103
+ var setFnMap = {
104
+ 'sss' : proto.setMilliseconds,
105
+ 'ss' : proto.setSeconds,
106
+ 's' : proto.setSeconds,
107
+ 'mm' : proto.setMinutes,
108
+ 'm' : proto.setMinutes,
109
+ 'HH' : proto.setHours,
110
+ 'H' : proto.setHours,
111
+ 'hh' : proto.setHours,
112
+ 'h' : proto.setHours,
113
+ 'EEEE' : noop,
114
+ 'EEE' : noop,
115
+ 'dd' : proto.setDate,
116
+ 'd' : proto.setDate,
117
+ 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },
118
+ 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },
119
+ 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },
120
+ 'MM' : function(value) { return this.setMonth(1 * value - 1); },
121
+ 'M' : function(value) { return this.setMonth(1 * value - 1); },
122
+ 'yyyy' : proto.setFullYear,
123
+ 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },
124
+ 'y' : proto.setFullYear
125
+ };
126
+
127
+ var regex, setMap;
128
+
129
+ $dateParser.init = function() {
130
+ $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;
131
+ regex = regExpForFormat($dateParser.$format);
132
+ setMap = setMapForFormat($dateParser.$format);
133
+ };
134
+
135
+ $dateParser.isValid = function(date) {
136
+ if(angular.isDate(date)) return !isNaN(date.getTime());
137
+ return regex.test(date);
138
+ };
139
+
140
+ $dateParser.parse = function(value, baseDate, format) {
141
+ // check for date format special names
142
+ if(format) format = $locale.DATETIME_FORMATS[format] || format;
143
+ if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);
144
+ var formatRegex = format ? regExpForFormat(format) : regex;
145
+ var formatSetMap = format ? setMapForFormat(format) : setMap;
146
+ var matches = formatRegex.exec(value);
147
+ if(!matches) return false;
148
+ // use custom ParseDate object to set parsed values
149
+ var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));
150
+ for(var i = 0; i < matches.length - 1; i++) {
151
+ formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);
152
+ }
153
+ // convert back to native Date object
154
+ var newDate = date.toDate();
155
+
156
+ // check new native Date object for day values overflow
157
+ if (parseInt(date.day, 10) !== newDate.getDate()) {
158
+ return false;
159
+ }
160
+
161
+ return newDate;
162
+ };
163
+
164
+ $dateParser.getDateForAttribute = function(key, value) {
165
+ var date;
166
+
167
+ if(value === 'today') {
168
+ var today = new Date();
169
+ date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));
170
+ } else if(angular.isString(value) && value.match(/^".+"$/)) { // Support {{ dateObj }}
171
+ date = new Date(value.substr(1, value.length - 2));
172
+ } else if(isNumeric(value)) {
173
+ date = new Date(parseInt(value, 10));
174
+ } else if (angular.isString(value) && 0 === value.length) { // Reset date
175
+ date = key === 'minDate' ? -Infinity : +Infinity;
176
+ } else {
177
+ date = new Date(value);
178
+ }
179
+
180
+ return date;
181
+ };
182
+
183
+ $dateParser.getTimeForAttribute = function(key, value) {
184
+ var time;
185
+
186
+ if(value === 'now') {
187
+ time = new Date().setFullYear(1970, 0, 1);
188
+ } else if(angular.isString(value) && value.match(/^".+"$/)) {
189
+ time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);
190
+ } else if(isNumeric(value)) {
191
+ time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);
192
+ } else if (angular.isString(value) && 0 === value.length) { // Reset time
193
+ time = key === 'minTime' ? -Infinity : +Infinity;
194
+ } else {
195
+ time = $dateParser.parse(value, new Date(1970, 0, 1, 0));
196
+ }
197
+
198
+ return time;
199
+ };
200
+
201
+ /* Handle switch to/from daylight saving.
202
+ * Hours may be non-zero on daylight saving cut-over:
203
+ * > 12 when midnight changeover, but then cannot generate
204
+ * midnight datetime, so jump to 1AM, otherwise reset.
205
+ * @param date (Date) the date to check
206
+ * @return (Date) the corrected date
207
+ *
208
+ * __ copied from jquery ui datepicker __
209
+ */
210
+ $dateParser.daylightSavingAdjust = function(date) {
211
+ if (!date) {
212
+ return null;
213
+ }
214
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
215
+ return date;
216
+ };
217
+
218
+ // Private functions
219
+
220
+ function setMapForFormat(format) {
221
+ var keys = Object.keys(setFnMap), i;
222
+ var map = [], sortedMap = [];
223
+ // Map to setFn
224
+ var clonedFormat = format;
225
+ for(i = 0; i < keys.length; i++) {
226
+ if(format.split(keys[i]).length > 1) {
227
+ var index = clonedFormat.search(keys[i]);
228
+ format = format.split(keys[i]).join('');
229
+ if(setFnMap[keys[i]]) {
230
+ map[index] = setFnMap[keys[i]];
231
+ }
232
+ }
233
+ }
234
+ // Sort result map
235
+ angular.forEach(map, function(v) {
236
+ // conditional required since angular.forEach broke around v1.2.21
237
+ // related pr: https://github.com/angular/angular.js/pull/8525
238
+ if(v) sortedMap.push(v);
239
+ });
240
+ return sortedMap;
241
+ }
242
+
243
+ function escapeReservedSymbols(text) {
244
+ return text.replace(/\//g, '[\\/]').replace('/-/g', '[-]').replace(/\./g, '[.]').replace(/\\s/g, '[\\s]');
245
+ }
246
+
247
+ function regExpForFormat(format) {
248
+ var keys = Object.keys(regExpMap), i;
249
+
250
+ var re = format;
251
+ // Abstract replaces to avoid collisions
252
+ for(i = 0; i < keys.length; i++) {
253
+ re = re.split(keys[i]).join('${' + i + '}');
254
+ }
255
+ // Replace abstracted values
256
+ for(i = 0; i < keys.length; i++) {
257
+ re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');
258
+ }
259
+ format = escapeReservedSymbols(format);
260
+
261
+ return new RegExp('^' + re + '$', ['i']);
262
+ }
263
+
264
+ $dateParser.init();
265
+ return $dateParser;
266
+
267
+ };
268
+
269
+ return DateParserFactory;
270
+
271
+ }];
272
+
273
+ }]);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ "use strict";angular.module("mgcrea.ngStrap.helpers.dateParser",[]).provider("$dateParser",["$localeProvider",function(){function t(){this.year=1970,this.month=0,this.day=1,this.hours=0,this.minutes=0,this.seconds=0,this.milliseconds=0}function e(){}function s(t){return!isNaN(parseFloat(t))&&isFinite(t)}function n(t,e){for(var s=t.length,n=e.toString().toLowerCase(),r=0;s>r;r++)if(t[r].toLowerCase()===n)return r;return-1}t.prototype.setMilliseconds=function(t){this.milliseconds=t},t.prototype.setSeconds=function(t){this.seconds=t},t.prototype.setMinutes=function(t){this.minutes=t},t.prototype.setHours=function(t){this.hours=t},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(t){this.day=t},t.prototype.setMonth=function(t){this.month=t},t.prototype.setFullYear=function(t){this.year=t},t.prototype.fromDate=function(t){return this.year=t.getFullYear(),this.month=t.getMonth(),this.day=t.getDate(),this.hours=t.getHours(),this.minutes=t.getMinutes(),this.seconds=t.getSeconds(),this.milliseconds=t.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var r=t.prototype,i=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale","dateFilter",function(o,a){var u=function(u){function h(t){var e,s=Object.keys(d),n=[],r=[],i=t;for(e=0;e<s.length;e++)if(t.split(s[e]).length>1){var o=i.search(s[e]);t=t.split(s[e]).join(""),d[s[e]]&&(n[o]=d[s[e]])}return angular.forEach(n,function(t){t&&r.push(t)}),r}function l(t){return t.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function c(t){var e,s=Object.keys(m),n=t;for(e=0;e<s.length;e++)n=n.split(s[e]).join("${"+e+"}");for(e=0;e<s.length;e++)n=n.split("${"+e+"}").join("("+m[s[e]]+")");return t=l(t),new RegExp("^"+n+"$",["i"])}var M,f,g=angular.extend({},i,u),p={},m={sss:"[0-9]{3}",ss:"[0-5][0-9]",s:g.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",mm:"[0-5][0-9]",m:g.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",HH:"[01][0-9]|2[0-3]",H:g.strict?"1?[0-9]|2[0-3]":"[01]?[0-9]|2[0-3]",hh:"[0][1-9]|[1][012]",h:g.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",a:"AM|PM",EEEE:o.DATETIME_FORMATS.DAY.join("|"),EEE:o.DATETIME_FORMATS.SHORTDAY.join("|"),dd:"0[1-9]|[12][0-9]|3[01]",d:g.strict?"[1-9]|[1-2][0-9]|3[01]":"0?[1-9]|[1-2][0-9]|3[01]",MMMM:o.DATETIME_FORMATS.MONTH.join("|"),MMM:o.DATETIME_FORMATS.SHORTMONTH.join("|"),MM:"0[1-9]|1[012]",M:g.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",yyyy:"[1]{1}[0-9]{3}|[2]{1}[0-9]{3}",yy:"[0-9]{2}",y:g.strict?"-?(0|[1-9][0-9]{0,3})":"-?0*[0-9]{1,4}"},d={sss:r.setMilliseconds,ss:r.setSeconds,s:r.setSeconds,mm:r.setMinutes,m:r.setMinutes,HH:r.setHours,H:r.setHours,hh:r.setHours,h:r.setHours,EEEE:e,EEE:e,dd:r.setDate,d:r.setDate,a:function(t){var e=this.getHours()%12;return this.setHours(t.match(/pm/i)?e+12:e)},MMMM:function(t){return this.setMonth(n(o.DATETIME_FORMATS.MONTH,t))},MMM:function(t){return this.setMonth(n(o.DATETIME_FORMATS.SHORTMONTH,t))},MM:function(t){return this.setMonth(1*t-1)},M:function(t){return this.setMonth(1*t-1)},yyyy:r.setFullYear,yy:function(t){return this.setFullYear(2e3+1*t)},y:r.setFullYear};return p.init=function(){p.$format=o.DATETIME_FORMATS[g.format]||g.format,M=c(p.$format),f=h(p.$format)},p.isValid=function(t){return angular.isDate(t)?!isNaN(t.getTime()):M.test(t)},p.parse=function(e,s,n){n&&(n=o.DATETIME_FORMATS[n]||n),angular.isDate(e)&&(e=a(e,n||p.$format));var r=n?c(n):M,i=n?h(n):f,u=r.exec(e);if(!u)return!1;for(var l=(new t).fromDate(s&&!isNaN(s.getTime())?s:new Date(1970,0,1,0)),g=0;g<u.length-1;g++)i[g]&&i[g].call(l,u[g+1]);var m=l.toDate();return parseInt(l.day,10)!==m.getDate()?!1:m},p.getDateForAttribute=function(t,e){var n;if("today"===e){var r=new Date;n=new Date(r.getFullYear(),r.getMonth(),r.getDate()+("maxDate"===t?1:0),0,0,0,"minDate"===t?0:-1)}else n=angular.isString(e)&&e.match(/^".+"$/)?new Date(e.substr(1,e.length-2)):s(e)?new Date(parseInt(e,10)):angular.isString(e)&&0===e.length?"minDate"===t?-1/0:+1/0:new Date(e);return n},p.getTimeForAttribute=function(t,e){var n;return n="now"===e?(new Date).setFullYear(1970,0,1):angular.isString(e)&&e.match(/^".+"$/)?new Date(e.substr(1,e.length-2)).setFullYear(1970,0,1):s(e)?new Date(parseInt(e,10)).setFullYear(1970,0,1):angular.isString(e)&&0===e.length?"minTime"===t?-1/0:+1/0:p.parse(e,new Date(1970,0,1,0))},p.daylightSavingAdjust=function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},p.init(),p};return u}]}]);
9
+ //# sourceMappingURL=date-parser.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["helpers/date-parser.js"],"names":[],"mappings":"qBASI,OAAK,iDAEA,eAAM,kBAAA,mBAIN,iCAGP,KAAA,IAAU,EACV,KAAA,MAAU,EACV,KAAA,QAAU,EACV,KAAA,QAAU,EACV,KAAA,aAAoB,EA4BpB,QAAS,cAGD,GAAS,4DAMf,IAAA,GADE,GAAA,EAAW,OAAK,EAAA,EAAW,WAAA,cACrB,EAAA,EAAA,EAAA,EAAA,IACR,GAAA,EAAQ,GAAA,gBAAA,EAAA,MAAA,YAnCV,EAAU,UAAU,gBAAc,SAAS,GAAS,KAAK,aAAO,GAChE,EAAU,UAAU,WAAW,SAAS,GAAO,KAAA,QAAA,KACxC,UAAa,WAAA,SAAA,GAAA,KAAA,QAAA,KACb,UAAQ,SAAM,SAAA,GAAA,KAAA,MAAA,KACd,UAAY,SAAA,WAAA,MAAA,MAAA,SACZ,UAAQ,QAAM,SAAA,GAAA,KAAA,IAAA,KACd,UAAU,SAAM,SAAA,GAAA,KAAA,MAAA,KAChB,UAAU,YAAM,SAAA,GAAA,KAAA,KAAA,KAChB,UAAA,SAAqB,SAAA,GAQ5B,MAPE,MAAA,KAAO,EAAA,2DAGT,KAAA,MAAU,EAAU,WAClB,KAAA,QAAW,EAAU,+EAGnB,6JAwBF,EAAI,KAAA,qCAEE,sDAKF,GAAU,SAAA,WAmJN,GAAY,MACe,GAA3B,EAAA,OAAS,KAAO,GAChB,KAAG,+EAMP,GAAQ,EAAQ,MAAK,EAAS,IAAG,KAAA,4BAYnC,oDAAS,UAGH,GAAK,2IAOP,EAAK,CAEP,KAAA,EAAA,EAAS,EAAA,EAAA,OAAA,4DAKX,EAAA,EAAY,MAAA,KAAA,EAAA,KAAA,KAAA,IAAA,EAAA,EAAA,IAAA,uDAtLV,EAAU,QAAQ,UAAS,EAAA,GAE3B,KAEA,GACA,IAAU,WACV,GAAU,aACV,EAAU,EAAA,OAAA,cAAA,mBACV,GAAU,aACV,EAAU,EAAQ,OAAA,cAAiB,mBACnC,GAAU,mBACV,EAAU,EAAQ,OAAS,iBAAA,oBAC3B,GAAU,oBACV,EAAU,EAAQ,OAAA,eAAiB,iBACnC,EAAU,QACV,KAAU,EAAQ,iBAAS,IAAA,KAAiB,KAC5C,IAAU,EAAA,iBAAA,SAAA,KAAA,KACV,GAAU,yBACV,EAAU,EAAQ,OAAS,yBAA0B,+GAGvD,GAAI,gBACF,EAAU,EAAM,OAAA,eAAA,iBAChB,KAAU,gCACV,GAAU,WACV,EAAU,EAAM,OAAA,wBAAA,kBAGhB,GACA,IAAU,EAAM,gBAChB,GAAU,EAAM,WAChB,EAAU,EAAA,WACV,GAAU,EAAA,WACV,EAAU,EAAM,WAChB,GAAU,EAAM,SAChB,EAAU,EAAA,SACV,GAAU,EAAA,SACV,EAAU,EAAA,SACV,KAAU,EACV,IAAU,EACV,GAAU,EAAM,QAChB,EAAU,EAAA,QACV,EAAU,SAAM,GAAA,GAAA,GAAA,KAAA,WAAA,EAAA,OAAA,MAAA,SAAA,EAAA,MAAA,OAAA,EAAA,GAAA,oJAGlB,GAAW,SAAA,GAAA,MAAA,MAAA,SAAA,EAAA,EAAA,+CAEX,KAAY,EAAA,YACV,GAAA,SAAY,GAAU,MAAQ,MAAA,YAAiB,IAAQ,EAAA,IACvD,EAAQ,EAAA,sBAKL,KAAQ,WACX,EAAO,QAAW,EAAA,iBAAA,EAAA,SAAA,EAAA,wCAKf,QAAiB,SAAQ,GAC5B,MAAG,SAAQ,OAAO,IAAQ,MAAQ,EAAA,WAC9B,EAAA,KAAc,MAGd,MAAS,SAAO,EAAA,EAAA,GAEpB,IAAW,EAAA,EAAa,iBAAe,IAAiB,GACxD,QAAQ,OAAO,KAAI,EAAQ,EAAiB,EAAA,GAAA,EAAA,aAC1C,GAAa,EAAM,EAAqB,GAAM,wBAGhD,KAAI,EAAA,OAAe,CAGnB,KAAI,sEAAA,EAAA,EAAS,EAAK,EAAK,OAAQ,EAAQ,IACrC,EAAO,IAAA,EAAA,GAAA,KAAA,EAAA,EAAA,EAAA,GAGT,IAAA,GAAO,EAAA,QAGT,OAAA,UAAY,EAAA,IAAA,MAAA,EAAsB,WAC5B,EAGE,KAGG,oBAAsB,SAAS,EAAA,YAG7B,YAAQ,CACjB,GAAA,GAAO,GAAQ,QACV,GAAA,MAAA,EAAA,cAAA,EAAA,WAAA,EAAA,WAAA,YAAA,EAAA,EAAA,GAAA,EAAA,EAAA,EAAA,YAAA,EAAA,EAAA,WACE,QAAS,SAAA,IAAA,EAAA,MAAA,gDAGX,GAAA,MAAA,SAAA,EAAA,+DAIH,GAAA,MAAA,SAGF,MAGQ,oBAAkB,SAAA,EAAA,MAC1B,YAEO,QAAP,GACK,GAAA,OAAA,YAAA,KAAA,EAAA,GACE,QAAA,SAAkB,IAAO,EAAS,MAAM,sEAG1C,GAAA,MAAA,SAAA,EAAA,KAAA,YAAA,KAAA,EAAA,2IAuBP,EAAI,SAAO,EAAO,WAAK,GAAW,EAAA,WAAA,EAAA,GAC9B","file":"date-parser.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i<len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function($locale, dateFilter) {\n\n var DateParserFactory = function(config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function(value) { return this.setMonth(1 * value - 1); },\n 'M' : function(value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : proto.setFullYear\n };\n\n var regex, setMap;\n\n $dateParser.init = function() {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function(date) {\n if(angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function(value, baseDate, format) {\n // check for date format special names\n if(format) format = $locale.DATETIME_FORMATS[format] || format;\n if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if(!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for(var i = 0; i < matches.length - 1; i++) {\n formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function(key, value) {\n var date;\n\n if(value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if(isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && 0 === value.length) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function(key, value) {\n var time;\n\n if(value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if(isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && 0 === value.length) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n"],"sourceRoot":"/source/"}
@@ -0,0 +1,640 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.1.6 - 2015-01-11
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+
10
+ angular.module('mgcrea.ngStrap.datepicker', [
11
+ 'mgcrea.ngStrap.helpers.dateParser',
12
+ 'mgcrea.ngStrap.helpers.dateFormatter',
13
+ 'mgcrea.ngStrap.tooltip'])
14
+
15
+ .provider('$datepicker', function() {
16
+
17
+ var defaults = this.defaults = {
18
+ animation: 'am-fade',
19
+ prefixClass: 'datepicker',
20
+ placement: 'bottom-left',
21
+ template: 'datepicker/datepicker.tpl.html',
22
+ trigger: 'focus',
23
+ container: false,
24
+ keyboard: true,
25
+ html: false,
26
+ delay: 0,
27
+ // lang: $locale.id,
28
+ useNative: false,
29
+ dateType: 'date',
30
+ dateFormat: 'shortDate',
31
+ modelDateFormat: null,
32
+ dayFormat: 'dd',
33
+ monthFormat: 'MMM',
34
+ yearFormat: 'yyyy',
35
+ monthTitleFormat: 'MMMM yyyy',
36
+ yearTitleFormat: 'yyyy',
37
+ strictFormat: false,
38
+ autoclose: false,
39
+ minDate: -Infinity,
40
+ maxDate: +Infinity,
41
+ startView: 0,
42
+ minView: 0,
43
+ startWeek: 0,
44
+ daysOfWeekDisabled: '',
45
+ iconLeft: 'glyphicon glyphicon-chevron-left',
46
+ iconRight: 'glyphicon glyphicon-chevron-right'
47
+ };
48
+
49
+ this.$get = ["$window", "$document", "$rootScope", "$sce", "$dateFormatter", "datepickerViews", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {
50
+
51
+ var bodyEl = angular.element($window.document.body);
52
+ var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
53
+ var isTouch = ('createTouch' in $window.document) && isNative;
54
+ if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();
55
+
56
+ function DatepickerFactory(element, controller, config) {
57
+
58
+ var $datepicker = $tooltip(element, angular.extend({}, defaults, config));
59
+ var parentScope = config.scope;
60
+ var options = $datepicker.$options;
61
+ var scope = $datepicker.$scope;
62
+ if(options.startView) options.startView -= options.minView;
63
+
64
+ // View vars
65
+
66
+ var pickerViews = datepickerViews($datepicker);
67
+ $datepicker.$views = pickerViews.views;
68
+ var viewDate = pickerViews.viewDate;
69
+ scope.$mode = options.startView;
70
+ scope.$iconLeft = options.iconLeft;
71
+ scope.$iconRight = options.iconRight;
72
+ var $picker = $datepicker.$views[scope.$mode];
73
+
74
+ // Scope methods
75
+
76
+ scope.$select = function(date) {
77
+ $datepicker.select(date);
78
+ };
79
+ scope.$selectPane = function(value) {
80
+ $datepicker.$selectPane(value);
81
+ };
82
+ scope.$toggleMode = function() {
83
+ $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);
84
+ };
85
+
86
+ // Public methods
87
+
88
+ $datepicker.update = function(date) {
89
+ // console.warn('$datepicker.update() newValue=%o', date);
90
+ if(angular.isDate(date) && !isNaN(date.getTime())) {
91
+ $datepicker.$date = date;
92
+ $picker.update.call($picker, date);
93
+ }
94
+ // Build only if pristine
95
+ $datepicker.$build(true);
96
+ };
97
+
98
+ $datepicker.updateDisabledDates = function(dateRanges) {
99
+ options.disabledDateRanges = dateRanges;
100
+ for(var i = 0, l = scope.rows.length; i < l; i++) {
101
+ angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);
102
+ }
103
+ };
104
+
105
+ $datepicker.select = function(date, keep) {
106
+ // console.warn('$datepicker.select', date, scope.$mode);
107
+ if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);
108
+ if(!scope.$mode || keep) {
109
+ controller.$setViewValue(angular.copy(date));
110
+ controller.$render();
111
+ if(options.autoclose && !keep) {
112
+ $timeout(function() { $datepicker.hide(true); });
113
+ }
114
+ } else {
115
+ angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});
116
+ $datepicker.setMode(scope.$mode - 1);
117
+ $datepicker.$build();
118
+ }
119
+ };
120
+
121
+ $datepicker.setMode = function(mode) {
122
+ // console.warn('$datepicker.setMode', mode);
123
+ scope.$mode = mode;
124
+ $picker = $datepicker.$views[scope.$mode];
125
+ $datepicker.$build();
126
+ };
127
+
128
+ // Protected methods
129
+
130
+ $datepicker.$build = function(pristine) {
131
+ // console.warn('$datepicker.$build() viewDate=%o', viewDate);
132
+ if(pristine === true && $picker.built) return;
133
+ if(pristine === false && !$picker.built) return;
134
+ $picker.build.call($picker);
135
+ };
136
+
137
+ $datepicker.$updateSelected = function() {
138
+ for(var i = 0, l = scope.rows.length; i < l; i++) {
139
+ angular.forEach(scope.rows[i], updateSelected);
140
+ }
141
+ };
142
+
143
+ $datepicker.$isSelected = function(date) {
144
+ return $picker.isSelected(date);
145
+ };
146
+
147
+ $datepicker.$setDisabledEl = function(el) {
148
+ el.disabled = $picker.isDisabled(el.date);
149
+ };
150
+
151
+ $datepicker.$selectPane = function(value) {
152
+ var steps = $picker.steps;
153
+ // set targetDate to first day of month to avoid problems with
154
+ // date values rollover. This assumes the viewDate does not
155
+ // depend on the day of the month
156
+ var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));
157
+ angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});
158
+ $datepicker.$build();
159
+ };
160
+
161
+ $datepicker.$onMouseDown = function(evt) {
162
+ // Prevent blur on mousedown on .dropdown-menu
163
+ evt.preventDefault();
164
+ evt.stopPropagation();
165
+ // Emulate click for mobile devices
166
+ if(isTouch) {
167
+ var targetEl = angular.element(evt.target);
168
+ if(targetEl[0].nodeName.toLowerCase() !== 'button') {
169
+ targetEl = targetEl.parent();
170
+ }
171
+ targetEl.triggerHandler('click');
172
+ }
173
+ };
174
+
175
+ $datepicker.$onKeyDown = function(evt) {
176
+ if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;
177
+ evt.preventDefault();
178
+ evt.stopPropagation();
179
+
180
+ if(evt.keyCode === 13) {
181
+ if(!scope.$mode) {
182
+ return $datepicker.hide(true);
183
+ } else {
184
+ return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });
185
+ }
186
+ }
187
+
188
+ // Navigate with keyboard
189
+ $picker.onKeyDown(evt);
190
+ parentScope.$digest();
191
+ };
192
+
193
+ // Private
194
+
195
+ function updateSelected(el) {
196
+ el.selected = $datepicker.$isSelected(el.date);
197
+ }
198
+
199
+ function focusElement() {
200
+ element[0].focus();
201
+ }
202
+
203
+ // Overrides
204
+
205
+ var _init = $datepicker.init;
206
+ $datepicker.init = function() {
207
+ if(isNative && options.useNative) {
208
+ element.prop('type', 'date');
209
+ element.css('-webkit-appearance', 'textfield');
210
+ return;
211
+ } else if(isTouch) {
212
+ element.prop('type', 'text');
213
+ element.attr('readonly', 'true');
214
+ element.on('click', focusElement);
215
+ }
216
+ _init();
217
+ };
218
+
219
+ var _destroy = $datepicker.destroy;
220
+ $datepicker.destroy = function() {
221
+ if(isNative && options.useNative) {
222
+ element.off('click', focusElement);
223
+ }
224
+ _destroy();
225
+ };
226
+
227
+ var _show = $datepicker.show;
228
+ $datepicker.show = function() {
229
+ _show();
230
+ // use timeout to hookup the events to prevent
231
+ // event bubbling from being processed imediately.
232
+ $timeout(function() {
233
+ // if $datepicker is no longer showing, don't setup events
234
+ if(!$datepicker.$isShown) return;
235
+ $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
236
+ if(options.keyboard) {
237
+ element.on('keydown', $datepicker.$onKeyDown);
238
+ }
239
+ }, 0, false);
240
+ };
241
+
242
+ var _hide = $datepicker.hide;
243
+ $datepicker.hide = function(blur) {
244
+ if(!$datepicker.$isShown) return;
245
+ $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
246
+ if(options.keyboard) {
247
+ element.off('keydown', $datepicker.$onKeyDown);
248
+ }
249
+ _hide(blur);
250
+ };
251
+
252
+ return $datepicker;
253
+
254
+ }
255
+
256
+ DatepickerFactory.defaults = defaults;
257
+ return DatepickerFactory;
258
+
259
+ }];
260
+
261
+ })
262
+
263
+ .directive('bsDatepicker', ["$window", "$parse", "$q", "$dateFormatter", "$dateParser", "$datepicker", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {
264
+
265
+ var defaults = $datepicker.defaults;
266
+ var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
267
+
268
+ return {
269
+ restrict: 'EAC',
270
+ require: 'ngModel',
271
+ link: function postLink(scope, element, attr, controller) {
272
+
273
+ // Directive options
274
+ var options = {scope: scope, controller: controller};
275
+ angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id'], function(key) {
276
+ if(angular.isDefined(attr[key])) options[key] = attr[key];
277
+ });
278
+
279
+ // Visibility binding support
280
+ attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {
281
+ if(!datepicker || !angular.isDefined(newValue)) return;
282
+ if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);
283
+ newValue === true ? datepicker.show() : datepicker.hide();
284
+ });
285
+
286
+ // Initialize datepicker
287
+ var datepicker = $datepicker(element, controller, options);
288
+ options = datepicker.$options;
289
+ // Set expected iOS format
290
+ if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';
291
+
292
+ var lang = options.lang;
293
+
294
+ var formatDate = function(date, format) {
295
+ return $dateFormatter.formatDate(date, format, lang);
296
+ };
297
+
298
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
299
+
300
+ // Observe attributes for changes
301
+ angular.forEach(['minDate', 'maxDate'], function(key) {
302
+ // console.warn('attr.$observe(%s)', key, attr[key]);
303
+ angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {
304
+ // console.warn('attr.$observe(%s)=%o', key, newValue);
305
+ datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);
306
+ // Build only if dirty
307
+ !isNaN(datepicker.$options[key]) && datepicker.$build(false);
308
+ validateAgainstMinMaxDate(controller.$dateValue);
309
+ });
310
+ });
311
+
312
+ // Watch model for changes
313
+ scope.$watch(attr.ngModel, function(newValue, oldValue) {
314
+ datepicker.update(controller.$dateValue);
315
+ }, true);
316
+
317
+ // Normalize undefined/null/empty array,
318
+ // so that we don't treat changing from undefined->null as a change.
319
+ function normalizeDateRanges(ranges) {
320
+ if (!ranges || !ranges.length) return null;
321
+ return ranges;
322
+ }
323
+
324
+ if (angular.isDefined(attr.disabledDates)) {
325
+ scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {
326
+ disabledRanges = normalizeDateRanges(disabledRanges);
327
+ previousValue = normalizeDateRanges(previousValue);
328
+
329
+ if (disabledRanges) {
330
+ datepicker.updateDisabledDates(disabledRanges);
331
+ }
332
+ });
333
+ }
334
+
335
+ function validateAgainstMinMaxDate(parsedDate) {
336
+ if (!angular.isDate(parsedDate)) return;
337
+ var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;
338
+ var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;
339
+ var isValid = isMinValid && isMaxValid;
340
+ controller.$setValidity('date', isValid);
341
+ controller.$setValidity('min', isMinValid);
342
+ controller.$setValidity('max', isMaxValid);
343
+ // Only update the model when we have a valid date
344
+ if(isValid) controller.$dateValue = parsedDate;
345
+ }
346
+
347
+ // viewValue -> $parsers -> modelValue
348
+ controller.$parsers.unshift(function(viewValue) {
349
+ // console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue);
350
+ // Null values should correctly reset the model value & validity
351
+ if(!viewValue) {
352
+ controller.$setValidity('date', true);
353
+ // BREAKING CHANGE:
354
+ // return null (not undefined) when input value is empty, so angularjs 1.3
355
+ // ngModelController can go ahead and run validators, like ngRequired
356
+ return null;
357
+ }
358
+ var parsedDate = dateParser.parse(viewValue, controller.$dateValue);
359
+ if(!parsedDate || isNaN(parsedDate.getTime())) {
360
+ controller.$setValidity('date', false);
361
+ // return undefined, causes ngModelController to
362
+ // invalidate model value
363
+ return;
364
+ } else {
365
+ validateAgainstMinMaxDate(parsedDate);
366
+ }
367
+ if(options.dateType === 'string') {
368
+ return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);
369
+ } else if(options.dateType === 'number') {
370
+ return controller.$dateValue.getTime();
371
+ } else if(options.dateType === 'unix') {
372
+ return controller.$dateValue.getTime() / 1000;
373
+ } else if(options.dateType === 'iso') {
374
+ return controller.$dateValue.toISOString();
375
+ } else {
376
+ return new Date(controller.$dateValue);
377
+ }
378
+ });
379
+
380
+ // modelValue -> $formatters -> viewValue
381
+ controller.$formatters.push(function(modelValue) {
382
+ // console.warn('$formatter("%s"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);
383
+ var date;
384
+ if(angular.isUndefined(modelValue) || modelValue === null) {
385
+ date = NaN;
386
+ } else if(angular.isDate(modelValue)) {
387
+ date = modelValue;
388
+ } else if(options.dateType === 'string') {
389
+ date = dateParser.parse(modelValue, null, options.modelDateFormat);
390
+ } else if(options.dateType === 'unix') {
391
+ date = new Date(modelValue * 1000);
392
+ } else {
393
+ date = new Date(modelValue);
394
+ }
395
+ // Setup default value?
396
+ // if(isNaN(date.getTime())) {
397
+ // var today = new Date();
398
+ // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);
399
+ // }
400
+ controller.$dateValue = date;
401
+ return getDateFormattedString();
402
+ });
403
+
404
+ // viewValue -> element
405
+ controller.$render = function() {
406
+ // console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);
407
+ element.val(getDateFormattedString());
408
+ };
409
+
410
+ function getDateFormattedString() {
411
+ return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);
412
+ }
413
+
414
+ // Garbage collection
415
+ scope.$on('$destroy', function() {
416
+ if(datepicker) datepicker.destroy();
417
+ options = null;
418
+ datepicker = null;
419
+ });
420
+
421
+ }
422
+ };
423
+
424
+ }])
425
+
426
+ .provider('datepickerViews', function() {
427
+
428
+ var defaults = this.defaults = {
429
+ dayFormat: 'dd',
430
+ daySplit: 7
431
+ };
432
+
433
+ // Split array into smaller arrays
434
+ function split(arr, size) {
435
+ var arrays = [];
436
+ while(arr.length > 0) {
437
+ arrays.push(arr.splice(0, size));
438
+ }
439
+ return arrays;
440
+ }
441
+
442
+ // Modulus operator
443
+ function mod(n, m) {
444
+ return ((n % m) + m) % m;
445
+ }
446
+
447
+ this.$get = ["$dateFormatter", "$dateParser", "$sce", function($dateFormatter, $dateParser, $sce) {
448
+
449
+ return function(picker) {
450
+
451
+ var scope = picker.$scope;
452
+ var options = picker.$options;
453
+
454
+ var lang = options.lang;
455
+ var formatDate = function(date, format) {
456
+ return $dateFormatter.formatDate(date, format, lang);
457
+ };
458
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
459
+
460
+ var weekDaysMin = $dateFormatter.weekdaysShort(lang);
461
+ var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));
462
+ var weekDaysLabelsHtml = $sce.trustAsHtml('<th class="dow text-center">' + weekDaysLabels.join('</th><th class="dow text-center">') + '</th>');
463
+
464
+ var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());
465
+ var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};
466
+ var timezoneOffset = startDate.getTimezoneOffset() * 6e4;
467
+
468
+ var views = [{
469
+ format: options.dayFormat,
470
+ split: 7,
471
+ steps: { month: 1 },
472
+ update: function(date, force) {
473
+ if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {
474
+ angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});
475
+ picker.$build();
476
+ } else if(date.getDate() !== viewDate.date) {
477
+ viewDate.date = picker.$date.getDate();
478
+ picker.$updateSelected();
479
+ }
480
+ },
481
+ build: function() {
482
+ var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();
483
+ var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();
484
+ var today = new Date().toDateString();
485
+ // Handle daylight time switch
486
+ if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);
487
+ var days = [], day;
488
+ for(var i = 0; i < 42; i++) { // < 7 * 6
489
+ day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));
490
+ days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});
491
+ }
492
+ scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);
493
+ scope.showLabels = true;
494
+ scope.labels = weekDaysLabelsHtml;
495
+ scope.rows = split(days, this.split);
496
+ this.built = true;
497
+ },
498
+ isSelected: function(date) {
499
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();
500
+ },
501
+ isDisabled: function(date) {
502
+ var time = date.getTime();
503
+
504
+ // Disabled because of min/max date.
505
+ if (time < options.minDate || time > options.maxDate) return true;
506
+
507
+ // Disabled due to being a disabled day of the week
508
+ if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;
509
+
510
+ // Disabled because of disabled date range.
511
+ if (options.disabledDateRanges) {
512
+ for (var i = 0; i < options.disabledDateRanges.length; i++) {
513
+ if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {
514
+ return true;
515
+ }
516
+ }
517
+ }
518
+
519
+ return false;
520
+ },
521
+ onKeyDown: function(evt) {
522
+ if (!picker.$date) {
523
+ return;
524
+ }
525
+ var actualTime = picker.$date.getTime();
526
+ var newDate;
527
+
528
+ if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);
529
+ else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);
530
+ else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);
531
+ else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);
532
+
533
+ if (!this.isDisabled(newDate)) picker.select(newDate, true);
534
+ }
535
+ }, {
536
+ name: 'month',
537
+ format: options.monthFormat,
538
+ split: 4,
539
+ steps: { year: 1 },
540
+ update: function(date, force) {
541
+ if(!this.built || date.getFullYear() !== viewDate.year) {
542
+ angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});
543
+ picker.$build();
544
+ } else if(date.getMonth() !== viewDate.month) {
545
+ angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});
546
+ picker.$updateSelected();
547
+ }
548
+ },
549
+ build: function() {
550
+ var firstMonth = new Date(viewDate.year, 0, 1);
551
+ var months = [], month;
552
+ for (var i = 0; i < 12; i++) {
553
+ month = new Date(viewDate.year, i, 1);
554
+ months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});
555
+ }
556
+ scope.title = formatDate(month, options.yearTitleFormat);
557
+ scope.showLabels = false;
558
+ scope.rows = split(months, this.split);
559
+ this.built = true;
560
+ },
561
+ isSelected: function(date) {
562
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();
563
+ },
564
+ isDisabled: function(date) {
565
+ var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);
566
+ return lastDate < options.minDate || date.getTime() > options.maxDate;
567
+ },
568
+ onKeyDown: function(evt) {
569
+ if (!picker.$date) {
570
+ return;
571
+ }
572
+ var actualMonth = picker.$date.getMonth();
573
+ var newDate = new Date(picker.$date);
574
+
575
+ if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);
576
+ else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);
577
+ else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);
578
+ else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);
579
+
580
+ if (!this.isDisabled(newDate)) picker.select(newDate, true);
581
+ }
582
+ }, {
583
+ name: 'year',
584
+ format: options.yearFormat,
585
+ split: 4,
586
+ steps: { year: 12 },
587
+ update: function(date, force) {
588
+ if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {
589
+ angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});
590
+ picker.$build();
591
+ } else if(date.getFullYear() !== viewDate.year) {
592
+ angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});
593
+ picker.$updateSelected();
594
+ }
595
+ },
596
+ build: function() {
597
+ var firstYear = viewDate.year - viewDate.year % (this.split * 3);
598
+ var years = [], year;
599
+ for (var i = 0; i < 12; i++) {
600
+ year = new Date(firstYear + i, 0, 1);
601
+ years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});
602
+ }
603
+ scope.title = years[0].label + '-' + years[years.length - 1].label;
604
+ scope.showLabels = false;
605
+ scope.rows = split(years, this.split);
606
+ this.built = true;
607
+ },
608
+ isSelected: function(date) {
609
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear();
610
+ },
611
+ isDisabled: function(date) {
612
+ var lastDate = +new Date(date.getFullYear() + 1, 0, 0);
613
+ return lastDate < options.minDate || date.getTime() > options.maxDate;
614
+ },
615
+ onKeyDown: function(evt) {
616
+ if (!picker.$date) {
617
+ return;
618
+ }
619
+ var actualYear = picker.$date.getFullYear(),
620
+ newDate = new Date(picker.$date);
621
+
622
+ if(evt.keyCode === 37) newDate.setYear(actualYear - 1);
623
+ else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);
624
+ else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);
625
+ else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);
626
+
627
+ if (!this.isDisabled(newDate)) picker.select(newDate, true);
628
+ }
629
+ }];
630
+
631
+ return {
632
+ views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,
633
+ viewDate: viewDate
634
+ };
635
+
636
+ };
637
+
638
+ }];
639
+
640
+ });