sw2at-ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/Gemfile +21 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +51 -0
  7. data/VERSION +1 -0
  8. data/app/assets/images/swat/loading-green.gif +0 -0
  9. data/app/assets/javascripts/swat/.bowerrc +3 -0
  10. data/app/assets/javascripts/swat/app/app.coffee +38 -0
  11. data/app/assets/javascripts/swat/app/controllers/revision.coffee +25 -0
  12. data/app/assets/javascripts/swat/app/controllers/revisions.coffee +10 -0
  13. data/app/assets/javascripts/swat/app/controllers/root.coffee +8 -0
  14. data/app/assets/javascripts/swat/app/factories/response.coffee +9 -0
  15. data/app/assets/javascripts/swat/app/factories/revision_model.coffee +20 -0
  16. data/app/assets/javascripts/swat/app/services/revision.coffee +16 -0
  17. data/app/assets/javascripts/swat/app/services/test_case.coffee +8 -0
  18. data/app/assets/javascripts/swat/application.coffee +5 -0
  19. data/app/assets/javascripts/swat/bower.json +16 -0
  20. data/app/assets/javascripts/swat/bower_components/angular/angular-csp.css +21 -0
  21. data/app/assets/javascripts/swat/bower_components/angular/angular.js +28133 -0
  22. data/app/assets/javascripts/swat/bower_components/angular/angular.min.js +289 -0
  23. data/app/assets/javascripts/swat/bower_components/angular/index.js +2 -0
  24. data/app/assets/javascripts/swat/bower_components/angular-animate/angular-animate.js +2137 -0
  25. data/app/assets/javascripts/swat/bower_components/angular-animate/angular-animate.min.js +33 -0
  26. data/app/assets/javascripts/swat/bower_components/angular-aria/angular-aria.js +339 -0
  27. data/app/assets/javascripts/swat/bower_components/angular-aria/angular-aria.min.js +12 -0
  28. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-csp.css +6 -0
  29. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-tpls.js +4840 -0
  30. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js +10 -0
  31. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap.js +4461 -0
  32. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap.min.js +9 -0
  33. data/app/assets/javascripts/swat/bower_components/angular-material/LICENSE.txt +21 -0
  34. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.css +6228 -0
  35. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.js +8602 -0
  36. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.min.css +6 -0
  37. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.min.js +277 -0
  38. data/app/assets/javascripts/swat/bower_components/angular-material/default-theme.css +394 -0
  39. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop-default-theme.css +8 -0
  40. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop.css +54 -0
  41. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop.js +40 -0
  42. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet-default-theme.css +15 -0
  43. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet.css +161 -0
  44. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet.js +263 -0
  45. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button-default-theme.css +49 -0
  46. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button.css +134 -0
  47. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button.js +101 -0
  48. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card-default-theme.css +10 -0
  49. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card.css +26 -0
  50. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card.js +60 -0
  51. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox-default-theme.css +38 -0
  52. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox.css +78 -0
  53. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox.js +135 -0
  54. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content-default-theme.css +8 -0
  55. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content.css +24 -0
  56. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content.js +87 -0
  57. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/core.css +2736 -0
  58. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/core.js +3090 -0
  59. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/default-theme.js +1 -0
  60. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog-default-theme.css +11 -0
  61. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog.css +75 -0
  62. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog.js +500 -0
  63. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider-default-theme.css +8 -0
  64. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider.css +12 -0
  65. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider.js +50 -0
  66. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/icon/icon.css +24 -0
  67. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/icon/icon.js +52 -0
  68. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input-default-theme.css +39 -0
  69. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input.css +113 -0
  70. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input.js +355 -0
  71. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/list/list.css +56 -0
  72. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/list/list.js +96 -0
  73. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/menu/menu.css +6 -0
  74. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/menu/menu.js +29 -0
  75. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular-default-theme.css +35 -0
  76. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular.css +1395 -0
  77. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular.js +129 -0
  78. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear-default-theme.css +26 -0
  79. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear.css +366 -0
  80. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear.js +130 -0
  81. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton-default-theme.css +39 -0
  82. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton.css +66 -0
  83. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton.js +302 -0
  84. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav-default-theme.css +8 -0
  85. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav.css +86 -0
  86. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav.js +320 -0
  87. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider-default-theme.css +55 -0
  88. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider.css +210 -0
  89. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider.js +391 -0
  90. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sticky/sticky.css +20 -0
  91. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sticky/sticky.js +314 -0
  92. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader-default-theme.css +15 -0
  93. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader.css +62 -0
  94. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader.js +89 -0
  95. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/swipe/swipe.js +79 -0
  96. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch-default-theme.css +29 -0
  97. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch.css +81 -0
  98. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch.js +171 -0
  99. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs-default-theme.css +34 -0
  100. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs.css +171 -0
  101. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs.js +1009 -0
  102. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField-default-theme.css +29 -0
  103. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField.css +72 -0
  104. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField.js +145 -0
  105. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast-default-theme.css +17 -0
  106. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast.css +110 -0
  107. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast.js +236 -0
  108. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar-default-theme.css +17 -0
  109. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar.css +69 -0
  110. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar.js +161 -0
  111. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip-default-theme.css +10 -0
  112. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip.css +133 -0
  113. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip.js +199 -0
  114. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/whiteframe/whiteframe.css +20 -0
  115. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/whiteframe/whiteframe.js +17 -0
  116. data/app/assets/javascripts/swat/bower_components/angular-material/modules/css/angular-material-layout.css +2582 -0
  117. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop-default-theme.css +8 -0
  118. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop-default-theme.min.css +6 -0
  119. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.css +54 -0
  120. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.js +38 -0
  121. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.min.css +6 -0
  122. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.min.js +7 -0
  123. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/bower.json +7 -0
  124. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet-default-theme.css +15 -0
  125. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet-default-theme.min.css +6 -0
  126. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.css +188 -0
  127. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.js +293 -0
  128. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.min.css +6 -0
  129. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.min.js +7 -0
  130. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bower.json +8 -0
  131. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/bower.json +7 -0
  132. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button-default-theme.css +42 -0
  133. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button-default-theme.min.css +6 -0
  134. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.css +132 -0
  135. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.js +94 -0
  136. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.min.css +6 -0
  137. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.min.js +7 -0
  138. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/bower.json +7 -0
  139. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card-default-theme.css +10 -0
  140. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card-default-theme.min.css +6 -0
  141. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.css +31 -0
  142. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.js +58 -0
  143. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.min.css +6 -0
  144. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.min.js +7 -0
  145. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/bower.json +7 -0
  146. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox-default-theme.css +38 -0
  147. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox-default-theme.min.css +6 -0
  148. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.css +79 -0
  149. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.js +133 -0
  150. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.min.css +6 -0
  151. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.min.js +7 -0
  152. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/bower.json +7 -0
  153. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content-default-theme.css +8 -0
  154. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content-default-theme.min.css +6 -0
  155. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.css +24 -0
  156. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.js +60 -0
  157. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.min.css +6 -0
  158. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.min.js +7 -0
  159. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/bower.json +7 -0
  160. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.css +3067 -0
  161. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.js +2780 -0
  162. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.min.css +6 -0
  163. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.min.js +7 -0
  164. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/default-theme.js +1 -0
  165. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/bower.json +8 -0
  166. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog-default-theme.css +11 -0
  167. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog-default-theme.min.css +6 -0
  168. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.css +88 -0
  169. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.js +495 -0
  170. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.min.css +6 -0
  171. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.min.js +7 -0
  172. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/bower.json +7 -0
  173. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider-default-theme.css +8 -0
  174. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider-default-theme.min.css +6 -0
  175. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.css +12 -0
  176. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.js +48 -0
  177. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.min.css +6 -0
  178. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.min.js +7 -0
  179. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/bower.json +7 -0
  180. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.css +24 -0
  181. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.js +50 -0
  182. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.min.css +6 -0
  183. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.min.js +7 -0
  184. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/bower.json +7 -0
  185. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input-default-theme.css +40 -0
  186. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input-default-theme.min.css +6 -0
  187. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.css +102 -0
  188. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.js +333 -0
  189. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.min.css +6 -0
  190. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.min.js +7 -0
  191. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/bower.json +7 -0
  192. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.css +61 -0
  193. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.js +94 -0
  194. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.min.css +6 -0
  195. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.min.js +7 -0
  196. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/bower.json +5 -0
  197. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.css +6 -0
  198. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.js +27 -0
  199. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.min.css +6 -0
  200. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.min.js +7 -0
  201. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/bower.json +7 -0
  202. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular-default-theme.css +35 -0
  203. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular-default-theme.min.css +6 -0
  204. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.css +1445 -0
  205. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.js +127 -0
  206. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.min.css +6 -0
  207. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.min.js +7 -0
  208. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/bower.json +7 -0
  209. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear-default-theme.css +28 -0
  210. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear-default-theme.min.css +6 -0
  211. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.css +368 -0
  212. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.js +128 -0
  213. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.min.css +6 -0
  214. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.min.js +7 -0
  215. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/bower.json +7 -0
  216. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton-default-theme.css +39 -0
  217. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton-default-theme.min.css +6 -0
  218. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.css +67 -0
  219. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.js +296 -0
  220. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.min.css +6 -0
  221. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.min.js +7 -0
  222. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/bower.json +8 -0
  223. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav-default-theme.css +8 -0
  224. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav-default-theme.min.css +6 -0
  225. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.css +90 -0
  226. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.js +302 -0
  227. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.min.css +6 -0
  228. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.min.js +7 -0
  229. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/bower.json +7 -0
  230. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider-default-theme.css +55 -0
  231. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider-default-theme.min.css +6 -0
  232. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.css +218 -0
  233. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.js +411 -0
  234. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.min.css +6 -0
  235. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.min.js +7 -0
  236. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/bower.json +8 -0
  237. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.css +20 -0
  238. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.js +309 -0
  239. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.min.css +6 -0
  240. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.min.js +7 -0
  241. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/bower.json +8 -0
  242. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader-default-theme.css +15 -0
  243. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader-default-theme.min.css +6 -0
  244. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.css +61 -0
  245. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.js +86 -0
  246. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.min.css +6 -0
  247. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.min.js +7 -0
  248. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/bower.json +5 -0
  249. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/swipe.js +213 -0
  250. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/swipe.min.js +7 -0
  251. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/bower.json +8 -0
  252. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch-default-theme.css +29 -0
  253. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch-default-theme.min.css +6 -0
  254. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.css +77 -0
  255. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.js +144 -0
  256. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.min.css +6 -0
  257. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.min.js +7 -0
  258. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/bower.json +7 -0
  259. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs-default-theme.css +34 -0
  260. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs-default-theme.min.css +6 -0
  261. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.css +181 -0
  262. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.js +992 -0
  263. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.min.css +6 -0
  264. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.min.js +7 -0
  265. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/bower.json +7 -0
  266. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField-default-theme.css +29 -0
  267. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField-default-theme.min.css +6 -0
  268. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.css +76 -0
  269. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.js +143 -0
  270. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.min.css +6 -0
  271. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.min.js +7 -0
  272. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/bower.json +9 -0
  273. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast-default-theme.css +17 -0
  274. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast-default-theme.min.css +6 -0
  275. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.css +115 -0
  276. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.js +235 -0
  277. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.min.css +6 -0
  278. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.min.js +7 -0
  279. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/bower.json +8 -0
  280. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar-default-theme.css +17 -0
  281. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar-default-theme.min.css +6 -0
  282. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.css +78 -0
  283. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.js +158 -0
  284. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.min.css +6 -0
  285. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.min.js +7 -0
  286. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/bower.json +7 -0
  287. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip-default-theme.css +10 -0
  288. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip-default-theme.min.css +6 -0
  289. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.css +136 -0
  290. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.js +197 -0
  291. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.min.css +6 -0
  292. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.min.js +7 -0
  293. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/bower.json +5 -0
  294. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.css +20 -0
  295. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.js +15 -0
  296. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.min.css +6 -0
  297. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.min.js +7 -0
  298. data/app/assets/javascripts/swat/bower_components/angular-resource/angular-resource.js +668 -0
  299. data/app/assets/javascripts/swat/bower_components/angular-resource/angular-resource.min.js +13 -0
  300. data/app/assets/javascripts/swat/bower_components/angular-resource/index.js +2 -0
  301. data/app/assets/javascripts/swat/bower_components/angular-route/angular-route.js +991 -0
  302. data/app/assets/javascripts/swat/bower_components/angular-route/angular-route.min.js +15 -0
  303. data/app/assets/javascripts/swat/bower_components/angular-route/index.js +2 -0
  304. data/app/assets/javascripts/swat/bower_components/angular-ui-router/LICENSE.txt +21 -0
  305. data/app/assets/javascripts/swat/bower_components/angular-ui-router/api/angular-ui-router.d.ts +126 -0
  306. data/app/assets/javascripts/swat/bower_components/angular-ui-router/release/angular-ui-router.js +4370 -0
  307. data/app/assets/javascripts/swat/bower_components/angular-ui-router/release/angular-ui-router.min.js +7 -0
  308. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/common.js +292 -0
  309. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/resolve.js +252 -0
  310. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/state.js +1465 -0
  311. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/stateDirectives.js +285 -0
  312. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/stateFilters.js +39 -0
  313. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/templateFactory.js +110 -0
  314. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/urlMatcherFactory.js +1050 -0
  315. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/urlRouter.js +427 -0
  316. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/view.js +71 -0
  317. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/viewDirective.js +303 -0
  318. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/viewScroll.js +52 -0
  319. data/app/assets/javascripts/swat/bower_components/lodash/lodash.js +12235 -0
  320. data/app/assets/javascripts/swat/bower_components/lodash/lodash.min.js +98 -0
  321. data/app/assets/javascripts/swat/bower_components/ng-clip/.editorconfig +10 -0
  322. data/app/assets/javascripts/swat/bower_components/ng-clip/.gitignore +3 -0
  323. data/app/assets/javascripts/swat/bower_components/ng-clip/Gruntfile.js +96 -0
  324. data/app/assets/javascripts/swat/bower_components/ng-clip/dest/ng-clip.min.js +2 -0
  325. data/app/assets/javascripts/swat/bower_components/ng-clip/example/bootstrap-tooltip.html +49 -0
  326. data/app/assets/javascripts/swat/bower_components/ng-clip/example/index.html +68 -0
  327. data/app/assets/javascripts/swat/bower_components/ng-clip/example/ng-repeat.html +44 -0
  328. data/app/assets/javascripts/swat/bower_components/ng-clip/npm-debug.log +145 -0
  329. data/app/assets/javascripts/swat/bower_components/ng-clip/src/ngClip.js +84 -0
  330. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/.jshintrc +70 -0
  331. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.Core.js +2017 -0
  332. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.Core.min.js +10 -0
  333. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.js +2581 -0
  334. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.min.js +10 -0
  335. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.swf +0 -0
  336. data/app/assets/javascripts/swat/bower_components.coffee +12 -0
  337. data/app/assets/stylesheets/swat/application.sass +59 -0
  338. data/app/assets/stylesheets/swat/default-theme.css +394 -0
  339. data/app/assets/stylesheets/swat/font-awesome.css +1801 -0
  340. data/app/assets/stylesheets/swat/fonts/FontAwesome.otf +0 -0
  341. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.eot +0 -0
  342. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.svg +565 -0
  343. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.ttf +0 -0
  344. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.woff +0 -0
  345. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.woff2 +0 -0
  346. data/app/assets/stylesheets/swat/swat_theme.sass +177 -0
  347. data/app/controllers/swat/api/revisions_controller.rb +27 -0
  348. data/app/controllers/swat/api/test_cases_controller.rb +20 -0
  349. data/app/controllers/swat/application_controller.rb +4 -0
  350. data/app/controllers/swat/info/states_controller.rb +12 -0
  351. data/app/controllers/swat/pages/base_pages_controller.rb +7 -0
  352. data/app/controllers/swat/pages/revisions_controller.rb +8 -0
  353. data/app/controllers/swat/revisions_controller.rb +4 -0
  354. data/app/helpers/swat/application_helper.rb +4 -0
  355. data/app/models/concerns/root_revision_ext.rb +14 -0
  356. data/app/models/full_revision.rb +88 -0
  357. data/app/models/revision.rb +84 -0
  358. data/app/models/revision_status_calculator.rb +98 -0
  359. data/app/models/test_case.rb +25 -0
  360. data/app/views/layouts/swat/application.slim +36 -0
  361. data/app/views/layouts/swat/page.slim +2 -0
  362. data/app/views/swat/application/index.slim +0 -0
  363. data/app/views/swat/pages/revisions/index.slim +25 -0
  364. data/app/views/swat/pages/revisions/show.slim +43 -0
  365. data/app/views/swat/shared/_footer.slim +5 -0
  366. data/app/views/swat/shared/_header.slim +9 -0
  367. data/bin/rails +12 -0
  368. data/config/routes.rb +38 -0
  369. data/fixtures/firebase_collection.rb +97 -0
  370. data/lib/sw2at-ui.rb +19 -0
  371. data/lib/swat/engine.rb +5 -0
  372. data/lib/swat/ui/config.rb +28 -0
  373. data/lib/swat/ui/rspec_commands.rb +191 -0
  374. data/lib/swat/ui/rspec_setup.rb +42 -0
  375. data/lib/swat/ui/stats_collector.rb +90 -0
  376. data/lib/swat/ui/version.rb +5 -0
  377. data/lib/tasks/swat_tasks.rake +36 -0
  378. data/spec/lib/commands_spec.rb +88 -0
  379. data/spec/models/calculator_spec.rb +130 -0
  380. data/spec/models/full_revision_spec.rb +263 -0
  381. data/spec/models/revision_spec.rb +59 -0
  382. data/spec/models/testcase_spec.rb +94 -0
  383. data/spec/spec_helper.rb +45 -0
  384. data/sw2at-ui.gemspec +465 -0
  385. data/test/helper.rb +34 -0
  386. data/test/test_sw2at-ui.rb +7 -0
  387. metadata +628 -0
@@ -0,0 +1,3090 @@
1
+ /*!
2
+ * Angular Material Design
3
+ * https://github.com/angular/material
4
+ * @license MIT
5
+ * v0.7.1
6
+ */
7
+ goog.provide('ng.material.core');
8
+
9
+ (function() {
10
+ 'use strict';
11
+
12
+ /**
13
+ * Initialization function that validates environment
14
+ * requirements.
15
+ */
16
+ angular
17
+ .module('material.core', ['material.core.theming'])
18
+ .config(MdCoreConfigure);
19
+
20
+
21
+ function MdCoreConfigure($provide, $mdThemingProvider) {
22
+ $provide.decorator('$$rAF', ["$delegate", rAFDecorator]);
23
+
24
+ $mdThemingProvider.theme('default')
25
+ .primaryPalette('indigo')
26
+ .accentPalette('pink')
27
+ .warnPalette('red')
28
+ .backgroundPalette('grey');
29
+ }
30
+ MdCoreConfigure.$inject = ["$provide", "$mdThemingProvider"];
31
+
32
+ function rAFDecorator( $delegate ) {
33
+ /**
34
+ * Use this to throttle events that come in often.
35
+ * The throttled function will always use the *last* invocation before the
36
+ * coming frame.
37
+ *
38
+ * For example, window resize events that fire many times a second:
39
+ * If we set to use an raf-throttled callback on window resize, then
40
+ * our callback will only be fired once per frame, with the last resize
41
+ * event that happened before that frame.
42
+ *
43
+ * @param {function} callback function to debounce
44
+ */
45
+ $delegate.throttle = function(cb) {
46
+ var queueArgs, alreadyQueued, queueCb, context;
47
+ return function debounced() {
48
+ queueArgs = arguments;
49
+ context = this;
50
+ queueCb = cb;
51
+ if (!alreadyQueued) {
52
+ alreadyQueued = true;
53
+ $delegate(function() {
54
+ queueCb.apply(context, queueArgs);
55
+ alreadyQueued = false;
56
+ });
57
+ }
58
+ };
59
+ };
60
+ return $delegate;
61
+ }
62
+
63
+ })();
64
+
65
+ (function() {
66
+ 'use strict';
67
+
68
+ angular.module('material.core')
69
+ .factory('$mdConstant', MdConstantFactory);
70
+
71
+ function MdConstantFactory($$rAF, $sniffer) {
72
+
73
+ var webkit = /webkit/i.test($sniffer.vendorPrefix);
74
+ function vendorProperty(name) {
75
+ return webkit ? ('webkit' + name.charAt(0).toUpperCase() + name.substring(1)) : name;
76
+ }
77
+
78
+ return {
79
+ KEY_CODE: {
80
+ ENTER: 13,
81
+ ESCAPE: 27,
82
+ SPACE: 32,
83
+ LEFT_ARROW : 37,
84
+ UP_ARROW : 38,
85
+ RIGHT_ARROW : 39,
86
+ DOWN_ARROW : 40
87
+ },
88
+ CSS: {
89
+ /* Constants */
90
+ TRANSITIONEND: 'transitionend' + (webkit ? ' webkitTransitionEnd' : ''),
91
+ ANIMATIONEND: 'animationend' + (webkit ? ' webkitAnimationEnd' : ''),
92
+
93
+ TRANSFORM: vendorProperty('transform'),
94
+ TRANSITION: vendorProperty('transition'),
95
+ TRANSITION_DURATION: vendorProperty('transitionDuration'),
96
+ ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'),
97
+ ANIMATION_DURATION: vendorProperty('animationDuration'),
98
+ ANIMATION_NAME: vendorProperty('animationName'),
99
+ ANIMATION_TIMING: vendorProperty('animationTimingFunction'),
100
+ ANIMATION_DIRECTION: vendorProperty('animationDirection')
101
+ },
102
+ MEDIA: {
103
+ 'sm': '(max-width: 600px)',
104
+ 'gt-sm': '(min-width: 600px)',
105
+ 'md': '(min-width: 600px) and (max-width: 960px)',
106
+ 'gt-md': '(min-width: 960px)',
107
+ 'lg': '(min-width: 960px) and (max-width: 1200px)',
108
+ 'gt-lg': '(min-width: 1200px)'
109
+ }
110
+ };
111
+ }
112
+ MdConstantFactory.$inject = ["$$rAF", "$sniffer"];
113
+
114
+ })();
115
+
116
+ (function(){
117
+
118
+ angular
119
+ .module('material.core')
120
+ .config( ["$provide", function($provide){
121
+ $provide.decorator('$mdUtil', ['$delegate', function ($delegate){
122
+ /**
123
+ * Inject the iterator facade to easily support iteration and accessors
124
+ * @see iterator below
125
+ */
126
+ $delegate.iterator = Iterator;
127
+
128
+ return $delegate;
129
+ }
130
+ ]);
131
+ }]);
132
+
133
+ /**
134
+ * iterator is a list facade to easily support iteration and accessors
135
+ *
136
+ * @param items Array list which this iterator will enumerate
137
+ * @param reloop Boolean enables iterator to consider the list as an endless reloop
138
+ */
139
+ function Iterator(items, reloop) {
140
+ var trueFn = function() { return true; };
141
+
142
+ reloop = !!reloop;
143
+ var _items = items || [ ];
144
+
145
+ // Published API
146
+ return {
147
+ items: getItems,
148
+ count: count,
149
+
150
+ inRange: inRange,
151
+ contains: contains,
152
+ indexOf: indexOf,
153
+ itemAt: itemAt,
154
+
155
+ findBy: findBy,
156
+
157
+ add: add,
158
+ remove: remove,
159
+
160
+ first: first,
161
+ last: last,
162
+ next: angular.bind(null, findSubsequentItem, false),
163
+ previous: angular.bind(null, findSubsequentItem, true),
164
+
165
+ hasPrevious: hasPrevious,
166
+ hasNext: hasNext
167
+
168
+ };
169
+
170
+ /**
171
+ * Publish copy of the enumerable set
172
+ * @returns {Array|*}
173
+ */
174
+ function getItems() {
175
+ return [].concat(_items);
176
+ }
177
+
178
+ /**
179
+ * Determine length of the list
180
+ * @returns {Array.length|*|number}
181
+ */
182
+ function count() {
183
+ return _items.length;
184
+ }
185
+
186
+ /**
187
+ * Is the index specified valid
188
+ * @param index
189
+ * @returns {Array.length|*|number|boolean}
190
+ */
191
+ function inRange(index) {
192
+ return _items.length && ( index > -1 ) && (index < _items.length );
193
+ }
194
+
195
+ /**
196
+ * Can the iterator proceed to the next item in the list; relative to
197
+ * the specified item.
198
+ *
199
+ * @param item
200
+ * @returns {Array.length|*|number|boolean}
201
+ */
202
+ function hasNext(item) {
203
+ return item ? inRange(indexOf(item) + 1) : false;
204
+ }
205
+
206
+ /**
207
+ * Can the iterator proceed to the previous item in the list; relative to
208
+ * the specified item.
209
+ *
210
+ * @param item
211
+ * @returns {Array.length|*|number|boolean}
212
+ */
213
+ function hasPrevious(item) {
214
+ return item ? inRange(indexOf(item) - 1) : false;
215
+ }
216
+
217
+ /**
218
+ * Get item at specified index/position
219
+ * @param index
220
+ * @returns {*}
221
+ */
222
+ function itemAt(index) {
223
+ return inRange(index) ? _items[index] : null;
224
+ }
225
+
226
+ /**
227
+ * Find all elements matching the key/value pair
228
+ * otherwise return null
229
+ *
230
+ * @param val
231
+ * @param key
232
+ *
233
+ * @return array
234
+ */
235
+ function findBy(key, val) {
236
+ return _items.filter(function(item) {
237
+ return item[key] === val;
238
+ });
239
+ }
240
+
241
+ /**
242
+ * Add item to list
243
+ * @param item
244
+ * @param index
245
+ * @returns {*}
246
+ */
247
+ function add(item, index) {
248
+ if ( !item ) return -1;
249
+
250
+ if (!angular.isNumber(index)) {
251
+ index = _items.length;
252
+ }
253
+
254
+ _items.splice(index, 0, item);
255
+
256
+ return indexOf(item);
257
+ }
258
+
259
+ /**
260
+ * Remove item from list...
261
+ * @param item
262
+ */
263
+ function remove(item) {
264
+ if ( contains(item) ){
265
+ _items.splice(indexOf(item), 1);
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Get the zero-based index of the target item
271
+ * @param item
272
+ * @returns {*}
273
+ */
274
+ function indexOf(item) {
275
+ return _items.indexOf(item);
276
+ }
277
+
278
+ /**
279
+ * Boolean existence check
280
+ * @param item
281
+ * @returns {boolean}
282
+ */
283
+ function contains(item) {
284
+ return item && (indexOf(item) > -1);
285
+ }
286
+
287
+ /**
288
+ * Return first item in the list
289
+ * @returns {*}
290
+ */
291
+ function first() {
292
+ return _items.length ? _items[0] : null;
293
+ }
294
+
295
+ /**
296
+ * Return last item in the list...
297
+ * @returns {*}
298
+ */
299
+ function last() {
300
+ return _items.length ? _items[_items.length - 1] : null;
301
+ }
302
+
303
+ /**
304
+ * Find the next item. If reloop is true and at the end of the list, it will
305
+ * go back to the first item. If given ,the `validate` callback will be used
306
+ * determine whether the next item is valid. If not valid, it will try to find the
307
+ * next item again.
308
+ * @param item
309
+ * @param {optional} validate Validate function
310
+ * @param {optional} limit Recursion limit
311
+ * @returns {*}
312
+ */
313
+ function findSubsequentItem(backwards, item, validate, limit) {
314
+ validate = validate || trueFn;
315
+
316
+ var curIndex = indexOf(item);
317
+ if (!inRange(curIndex)) {
318
+ return null;
319
+ }
320
+
321
+ var nextIndex = curIndex + (backwards ? -1 : 1);
322
+ var foundItem = null;
323
+ if (inRange(nextIndex)) {
324
+ foundItem = _items[nextIndex];
325
+ } else if (reloop) {
326
+ foundItem = backwards ? last() : first();
327
+ nextIndex = indexOf(foundItem);
328
+ }
329
+
330
+ if ((foundItem === null) || (nextIndex === limit)) {
331
+ return null;
332
+ }
333
+
334
+ if (angular.isUndefined(limit)) {
335
+ limit = nextIndex;
336
+ }
337
+
338
+ return validate(foundItem) ? foundItem : findSubsequentItem(backwards, foundItem, validate, limit);
339
+ }
340
+ }
341
+
342
+ })();
343
+
344
+ angular.module('material.core')
345
+ .factory('$mdMedia', mdMediaFactory);
346
+
347
+ /**
348
+ * Exposes a function on the '$mdMedia' service which will return true or false,
349
+ * whether the given media query matches. Re-evaluates on resize. Allows presets
350
+ * for 'sm', 'md', 'lg'.
351
+ *
352
+ * @example $mdMedia('sm') == true if device-width <= sm
353
+ * @example $mdMedia('(min-width: 1200px)') == true if device-width >= 1200px
354
+ * @example $mdMedia('max-width: 300px') == true if device-width <= 300px (sanitizes input, adding parens)
355
+ */
356
+ function mdMediaFactory($mdConstant, $rootScope, $window) {
357
+ var queries = {};
358
+ var results = {};
359
+
360
+ return $mdMedia;
361
+
362
+ function $mdMedia(query) {
363
+ var validated = queries[query];
364
+ if (angular.isUndefined(validated)) {
365
+ validated = queries[query] = validate(query);
366
+ }
367
+
368
+ var result = results[validated];
369
+ if (angular.isUndefined(result)) {
370
+ result = add(validated);
371
+ }
372
+
373
+ return result;
374
+ }
375
+
376
+ function validate(query) {
377
+ return $mdConstant.MEDIA[query] ||
378
+ ((query.charAt(0) !== '(') ? ('(' + query + ')') : query);
379
+ }
380
+
381
+ function add(query) {
382
+ var result = $window.matchMedia(query);
383
+ result.addListener(onQueryChange);
384
+ return (results[result.media] = !!result.matches);
385
+ }
386
+
387
+ function onQueryChange() {
388
+ var query = this;
389
+ $rootScope.$evalAsync(function() {
390
+ results[query.media] = !!query.matches;
391
+ });
392
+ }
393
+
394
+ }
395
+ mdMediaFactory.$inject = ["$mdConstant", "$rootScope", "$window"];
396
+
397
+ (function() {
398
+ 'use strict';
399
+
400
+ /*
401
+ * This var has to be outside the angular factory, otherwise when
402
+ * there are multiple material apps on the same page, each app
403
+ * will create its own instance of this array and the app's IDs
404
+ * will not be unique.
405
+ */
406
+ var nextUniqueId = ['0','0','0'];
407
+
408
+ angular.module('material.core')
409
+ .factory('$mdUtil', ["$document", "$timeout", function($document, $timeout) {
410
+ var Util;
411
+
412
+ return Util = {
413
+ now: window.performance ? angular.bind(window.performance, window.performance.now) : Date.now,
414
+
415
+ elementRect: function(element, offsetParent) {
416
+ var node = element[0];
417
+ offsetParent = offsetParent || node.offsetParent || document.body;
418
+ offsetParent = offsetParent[0] || offsetParent;
419
+ var nodeRect = node.getBoundingClientRect();
420
+ var parentRect = offsetParent.getBoundingClientRect();
421
+ return {
422
+ left: nodeRect.left - parentRect.left + offsetParent.scrollLeft,
423
+ top: nodeRect.top - parentRect.top + offsetParent.scrollTop,
424
+ width: nodeRect.width,
425
+ height: nodeRect.height
426
+ };
427
+ },
428
+
429
+ fakeNgModel: function() {
430
+ return {
431
+ $fake: true,
432
+ $setViewValue: function(value) {
433
+ this.$viewValue = value;
434
+ this.$render(value);
435
+ this.$viewChangeListeners.forEach(function(cb) { cb(); });
436
+ },
437
+ $isEmpty: function(value) {
438
+ return (''+value).length === 0;
439
+ },
440
+ $parsers: [],
441
+ $formatters: [],
442
+ $viewChangeListeners: [],
443
+ $render: angular.noop
444
+ };
445
+ },
446
+
447
+ // Returns a function, that, as long as it continues to be invoked, will not
448
+ // be triggered. The function will be called after it stops being called for
449
+ // N milliseconds.
450
+ // @param wait Integer value of msecs to delay (since last debounce reset); default value 10 msecs
451
+ // @param invokeApply should the $timeout trigger $digest() dirty checking
452
+ debounce: function (func, wait, scope, invokeApply) {
453
+ var timer;
454
+
455
+ return function debounced() {
456
+ var context = scope,
457
+ args = Array.prototype.slice.call(arguments);
458
+
459
+ $timeout.cancel(timer);
460
+ timer = $timeout(function() {
461
+
462
+ timer = undefined;
463
+ func.apply(context, args);
464
+
465
+ }, wait || 10, invokeApply );
466
+ };
467
+ },
468
+
469
+ // Returns a function that can only be triggered every `delay` milliseconds.
470
+ // In other words, the function will not be called unless it has been more
471
+ // than `delay` milliseconds since the last call.
472
+ throttle: function throttle(func, delay) {
473
+ var recent;
474
+ return function throttled() {
475
+ var context = this;
476
+ var args = arguments;
477
+ var now = Util.now();
478
+
479
+ if (!recent || (now - recent > delay)) {
480
+ func.apply(context, args);
481
+ recent = now;
482
+ }
483
+ };
484
+ },
485
+
486
+ /**
487
+ * nextUid, from angular.js.
488
+ * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
489
+ * characters such as '012ABC'. The reason why we are not using simply a number counter is that
490
+ * the number string gets longer over time, and it can also overflow, where as the nextId
491
+ * will grow much slower, it is a string, and it will never overflow.
492
+ *
493
+ * @returns an unique alpha-numeric string
494
+ */
495
+ nextUid: function() {
496
+ var index = nextUniqueId.length;
497
+ var digit;
498
+
499
+ while(index) {
500
+ index--;
501
+ digit = nextUniqueId[index].charCodeAt(0);
502
+ if (digit == 57 /*'9'*/) {
503
+ nextUniqueId[index] = 'A';
504
+ return nextUniqueId.join('');
505
+ }
506
+ if (digit == 90 /*'Z'*/) {
507
+ nextUniqueId[index] = '0';
508
+ } else {
509
+ nextUniqueId[index] = String.fromCharCode(digit + 1);
510
+ return nextUniqueId.join('');
511
+ }
512
+ }
513
+ nextUniqueId.unshift('0');
514
+ return nextUniqueId.join('');
515
+ },
516
+
517
+ // Stop watchers and events from firing on a scope without destroying it,
518
+ // by disconnecting it from its parent and its siblings' linked lists.
519
+ disconnectScope: function disconnectScope(scope) {
520
+ if (!scope) return;
521
+
522
+ // we can't destroy the root scope or a scope that has been already destroyed
523
+ if (scope.$root === scope) return;
524
+ if (scope.$$destroyed ) return;
525
+
526
+ var parent = scope.$parent;
527
+ scope.$$disconnected = true;
528
+
529
+ // See Scope.$destroy
530
+ if (parent.$$childHead === scope) parent.$$childHead = scope.$$nextSibling;
531
+ if (parent.$$childTail === scope) parent.$$childTail = scope.$$prevSibling;
532
+ if (scope.$$prevSibling) scope.$$prevSibling.$$nextSibling = scope.$$nextSibling;
533
+ if (scope.$$nextSibling) scope.$$nextSibling.$$prevSibling = scope.$$prevSibling;
534
+
535
+ scope.$$nextSibling = scope.$$prevSibling = null;
536
+
537
+ },
538
+
539
+ // Undo the effects of disconnectScope above.
540
+ reconnectScope: function reconnectScope(scope) {
541
+ if (!scope) return;
542
+
543
+ // we can't disconnect the root node or scope already disconnected
544
+ if (scope.$root === scope) return;
545
+ if (!scope.$$disconnected) return;
546
+
547
+ var child = scope;
548
+
549
+ var parent = child.$parent;
550
+ child.$$disconnected = false;
551
+ // See Scope.$new for this logic...
552
+ child.$$prevSibling = parent.$$childTail;
553
+ if (parent.$$childHead) {
554
+ parent.$$childTail.$$nextSibling = child;
555
+ parent.$$childTail = child;
556
+ } else {
557
+ parent.$$childHead = parent.$$childTail = child;
558
+ }
559
+ },
560
+ /*
561
+ * getClosest replicates jQuery.closest() to walk up the DOM tree until it finds a matching nodeName
562
+ *
563
+ * @param el Element to start walking the DOM from
564
+ * @param tagName Tag name to find closest to el, such as 'form'
565
+ */
566
+ getClosest: function getClosest(el, tagName) {
567
+ tagName = tagName.toUpperCase();
568
+ do {
569
+ if (el.nodeName === tagName) {
570
+ return el;
571
+ }
572
+ } while (el = el.parentNode);
573
+ return null;
574
+ }
575
+ };
576
+
577
+ }]);
578
+
579
+ /*
580
+ * Since removing jQuery from the demos, some code that uses `element.focus()` is broken.
581
+ *
582
+ * We need to add `element.focus()`, because it's testable unlike `element[0].focus`.
583
+ *
584
+ * TODO(ajoslin): This should be added in a better place later.
585
+ */
586
+
587
+ angular.element.prototype.focus = angular.element.prototype.focus || function() {
588
+ if (this.length) {
589
+ this[0].focus();
590
+ }
591
+ return this;
592
+ };
593
+ angular.element.prototype.blur = angular.element.prototype.blur || function() {
594
+ if (this.length) {
595
+ this[0].blur();
596
+ }
597
+ return this;
598
+ };
599
+
600
+ })();
601
+
602
+ (function() {
603
+ 'use strict';
604
+
605
+ angular.module('material.core')
606
+ .service('$mdAria', AriaService);
607
+
608
+ function AriaService($$rAF, $log, $window) {
609
+
610
+ return {
611
+ expect: expect,
612
+ expectAsync: expectAsync,
613
+ expectWithText: expectWithText
614
+ };
615
+
616
+ /**
617
+ * Check if expected attribute has been specified on the target element or child
618
+ * @param element
619
+ * @param attrName
620
+ * @param {optional} defaultValue What to set the attr to if no value is found
621
+ */
622
+ function expect(element, attrName, defaultValue) {
623
+ var node = element[0];
624
+
625
+ if (!node.hasAttribute(attrName) && !childHasAttribute(node, attrName)) {
626
+
627
+ defaultValue = angular.isString(defaultValue) && defaultValue.trim() || '';
628
+ if (defaultValue.length) {
629
+ element.attr(attrName, defaultValue);
630
+ } else {
631
+ $log.warn('ARIA: Attribute "', attrName, '", required for accessibility, is missing on node:', node);
632
+ }
633
+
634
+ }
635
+ }
636
+
637
+ function expectAsync(element, attrName, defaultValueGetter) {
638
+ // Problem: when retrieving the element's contents synchronously to find the label,
639
+ // the text may not be defined yet in the case of a binding.
640
+ // There is a higher chance that a binding will be defined if we wait one frame.
641
+ $$rAF(function() {
642
+ expect(element, attrName, defaultValueGetter());
643
+ });
644
+ }
645
+
646
+ function expectWithText(element, attrName) {
647
+ expectAsync(element, attrName, function() {
648
+ return element.text().trim();
649
+ });
650
+ }
651
+
652
+ function childHasAttribute(node, attrName) {
653
+ var hasChildren = node.hasChildNodes(),
654
+ hasAttr = false;
655
+
656
+ function isHidden(el) {
657
+ var style = el.currentStyle ? el.currentStyle : $window.getComputedStyle(el);
658
+ return (style.display === 'none');
659
+ }
660
+
661
+ if(hasChildren) {
662
+ var children = node.childNodes;
663
+ for(var i=0; i<children.length; i++){
664
+ var child = children[i];
665
+ if(child.nodeType === 1 && child.hasAttribute(attrName)) {
666
+ if(!isHidden(child)){
667
+ hasAttr = true;
668
+ }
669
+ }
670
+ }
671
+ }
672
+ return hasAttr;
673
+ }
674
+ }
675
+ AriaService.$inject = ["$$rAF", "$log", "$window"];
676
+ })();
677
+
678
+ (function() {
679
+ 'use strict';
680
+
681
+ angular.module('material.core')
682
+ .service('$mdCompiler', mdCompilerService);
683
+
684
+ function mdCompilerService($q, $http, $injector, $compile, $controller, $templateCache) {
685
+ /* jshint validthis: true */
686
+
687
+ /*
688
+ * @ngdoc service
689
+ * @name $mdCompiler
690
+ * @module material.core
691
+ * @description
692
+ * The $mdCompiler service is an abstraction of angular's compiler, that allows the developer
693
+ * to easily compile an element with a templateUrl, controller, and locals.
694
+ *
695
+ * @usage
696
+ * <hljs lang="js">
697
+ * $mdCompiler.compile({
698
+ * templateUrl: 'modal.html',
699
+ * controller: 'ModalCtrl',
700
+ * locals: {
701
+ * modal: myModalInstance;
702
+ * }
703
+ * }).then(function(compileData) {
704
+ * compileData.element; // modal.html's template in an element
705
+ * compileData.link(myScope); //attach controller & scope to element
706
+ * });
707
+ * </hljs>
708
+ */
709
+
710
+ /*
711
+ * @ngdoc method
712
+ * @name $mdCompiler#compile
713
+ * @description A helper to compile an HTML template/templateUrl with a given controller,
714
+ * locals, and scope.
715
+ * @param {object} options An options object, with the following properties:
716
+ *
717
+ * - `controller` - `{(string=|function()=}` Controller fn that should be associated with
718
+ * newly created scope or the name of a registered controller if passed as a string.
719
+ * - `controllerAs` - `{string=}` A controller alias name. If present the controller will be
720
+ * published to scope under the `controllerAs` name.
721
+ * - `template` - `{string=}` An html template as a string.
722
+ * - `templateUrl` - `{string=}` A path to an html template.
723
+ * - `transformTemplate` - `{function(template)=}` A function which transforms the template after
724
+ * it is loaded. It will be given the template string as a parameter, and should
725
+ * return a a new string representing the transformed template.
726
+ * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
727
+ * be injected into the controller. If any of these dependencies are promises, the compiler
728
+ * will wait for them all to be resolved, or if one is rejected before the controller is
729
+ * instantiated `compile()` will fail..
730
+ * * `key` - `{string}`: a name of a dependency to be injected into the controller.
731
+ * * `factory` - `{string|function}`: If `string` then it is an alias for a service.
732
+ * Otherwise if function, then it is injected and the return value is treated as the
733
+ * dependency. If the result is a promise, it is resolved before its value is
734
+ * injected into the controller.
735
+ *
736
+ * @returns {object=} promise A promise, which will be resolved with a `compileData` object.
737
+ * `compileData` has the following properties:
738
+ *
739
+ * - `element` - `{element}`: an uncompiled element matching the provided template.
740
+ * - `link` - `{function(scope)}`: A link function, which, when called, will compile
741
+ * the element and instantiate the provided controller (if given).
742
+ * - `locals` - `{object}`: The locals which will be passed into the controller once `link` is
743
+ * called. If `bindToController` is true, they will be coppied to the ctrl instead
744
+ * - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in
745
+ */
746
+ this.compile = function(options) {
747
+ var templateUrl = options.templateUrl;
748
+ var template = options.template || '';
749
+ var controller = options.controller;
750
+ var controllerAs = options.controllerAs;
751
+ var resolve = options.resolve || {};
752
+ var locals = options.locals || {};
753
+ var transformTemplate = options.transformTemplate || angular.identity;
754
+ var bindToController = options.bindToController;
755
+
756
+ // Take resolve values and invoke them.
757
+ // Resolves can either be a string (value: 'MyRegisteredAngularConst'),
758
+ // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})
759
+ angular.forEach(resolve, function(value, key) {
760
+ if (angular.isString(value)) {
761
+ resolve[key] = $injector.get(value);
762
+ } else {
763
+ resolve[key] = $injector.invoke(value);
764
+ }
765
+ });
766
+ //Add the locals, which are just straight values to inject
767
+ //eg locals: { three: 3 }, will inject three into the controller
768
+ angular.extend(resolve, locals);
769
+
770
+ if (templateUrl) {
771
+ resolve.$template = $http.get(templateUrl, {cache: $templateCache})
772
+ .then(function(response) {
773
+ return response.data;
774
+ });
775
+ } else {
776
+ resolve.$template = $q.when(template);
777
+ }
778
+
779
+ // Wait for all the resolves to finish if they are promises
780
+ return $q.all(resolve).then(function(locals) {
781
+
782
+ var template = transformTemplate(locals.$template);
783
+ var element = angular.element('<div>').html(template.trim()).contents();
784
+ var linkFn = $compile(element);
785
+
786
+ //Return a linking function that can be used later when the element is ready
787
+ return {
788
+ locals: locals,
789
+ element: element,
790
+ link: function link(scope) {
791
+ locals.$scope = scope;
792
+
793
+ //Instantiate controller if it exists, because we have scope
794
+ if (controller) {
795
+ var ctrl = $controller(controller, locals);
796
+ if (bindToController) {
797
+ angular.extend(ctrl, locals);
798
+ }
799
+ //See angular-route source for this logic
800
+ element.data('$ngControllerController', ctrl);
801
+ element.children().data('$ngControllerController', ctrl);
802
+
803
+ if (controllerAs) {
804
+ scope[controllerAs] = ctrl;
805
+ }
806
+ }
807
+
808
+ return linkFn(scope);
809
+ }
810
+ };
811
+ });
812
+
813
+ };
814
+ }
815
+ mdCompilerService.$inject = ["$q", "$http", "$injector", "$compile", "$controller", "$templateCache"];
816
+ })();
817
+
818
+ (function() {
819
+ 'use strict';
820
+
821
+ /*
822
+ * TODO: Add support for multiple fingers on the `pointer` object (enables pinch gesture)
823
+ */
824
+
825
+ var START_EVENTS = 'mousedown touchstart pointerdown';
826
+ var MOVE_EVENTS = 'mousemove touchmove pointermove';
827
+ var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
828
+ var HANDLERS;
829
+
830
+ document.contains || (document.contains = function(node) {
831
+ return document.body.contains(node);
832
+ });
833
+
834
+ // TODO add windows phone to this
835
+ var userAgent = navigator.userAgent || navigator.vendor || window.opera;
836
+ var isIos = userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i);
837
+ var isAndroid = userAgent.match(/Android/i);
838
+ var shouldHijackClicks = isIos || isAndroid;
839
+
840
+ if (shouldHijackClicks) {
841
+ document.addEventListener('click', function(ev) {
842
+ // Space/enter on a button, and submit events, can send clicks
843
+ var isKeyClick = ev.clientX === 0 && ev.clientY === 0;
844
+ if (isKeyClick || ev.$material) return;
845
+
846
+ // Prevent clicks unless they're sent by material
847
+ ev.preventDefault();
848
+ ev.stopPropagation();
849
+ }, true);
850
+ }
851
+
852
+ angular.element(document)
853
+ .on(START_EVENTS, gestureStart)
854
+ .on(MOVE_EVENTS, gestureMove)
855
+ .on(END_EVENTS, gestureEnd)
856
+ // For testing
857
+ .on('$$mdGestureReset', function() {
858
+ lastPointer = pointer = null;
859
+ });
860
+
861
+ // The state of the current and previous 'pointer' (user's hand)
862
+ var pointer, lastPointer;
863
+
864
+ function runHandlers(handlerEvent, event) {
865
+ var handler;
866
+ for (var handlerName in HANDLERS) {
867
+ handler = HANDLERS[handlerName];
868
+ if (handlerEvent === 'start') {
869
+ // Run cancel to reset any handlers' state
870
+ handler.cancel();
871
+ }
872
+ handler[handlerEvent](event, pointer);
873
+ }
874
+ }
875
+
876
+ function gestureStart(ev) {
877
+ // If we're already touched down, abort
878
+ if (pointer) return;
879
+
880
+ var now = +Date.now();
881
+
882
+ // iOS & old android bug: after a touch event, a click event is sent 350 ms later.
883
+ // If <400ms have passed, don't allow an event of a different type than the previous event
884
+ if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) {
885
+ return;
886
+ }
887
+
888
+ pointer = makeStartPointer(ev);
889
+
890
+ runHandlers('start', ev);
891
+ }
892
+
893
+ function gestureMove(ev) {
894
+ if (!pointer || !typesMatch(ev, pointer)) return;
895
+
896
+ updatePointerState(ev, pointer);
897
+ runHandlers('move', ev);
898
+ }
899
+
900
+ function gestureEnd(ev) {
901
+ if (!pointer || !typesMatch(ev, pointer)) return;
902
+
903
+ updatePointerState(ev, pointer);
904
+ pointer.endTime = +Date.now();
905
+
906
+ runHandlers('end', ev);
907
+
908
+ lastPointer = pointer;
909
+ pointer = null;
910
+ }
911
+
912
+ /******** Helpers *********/
913
+ function typesMatch(ev, pointer) {
914
+ return ev && pointer && ev.type.charAt(0) === pointer.type;
915
+ }
916
+
917
+ function getEventPoint(ev) {
918
+ ev = ev.originalEvent || ev; // support jQuery events
919
+ return (ev.touches && ev.touches[0]) ||
920
+ (ev.changedTouches && ev.changedTouches[0]) ||
921
+ ev;
922
+ }
923
+
924
+ function updatePointerState(ev, pointer) {
925
+ var point = getEventPoint(ev);
926
+ var x = pointer.x = point.pageX;
927
+ var y = pointer.y = point.pageY;
928
+
929
+ pointer.distanceX = x - pointer.startX;
930
+ pointer.distanceY = y - pointer.startY;
931
+ pointer.distance = Math.sqrt(
932
+ pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY
933
+ );
934
+
935
+ pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : '';
936
+ pointer.directionY = pointer.distanceY > 0 ? 'up' : pointer.distanceY < 0 ? 'down' : '';
937
+
938
+ pointer.duration = +Date.now() - pointer.startTime;
939
+ pointer.velocityX = pointer.distanceX / pointer.duration;
940
+ pointer.velocityY = pointer.distanceY / pointer.duration;
941
+ }
942
+
943
+
944
+ function makeStartPointer(ev) {
945
+ var point = getEventPoint(ev);
946
+ var startPointer = {
947
+ startTime: +Date.now(),
948
+ target: ev.target,
949
+ // 'p' for pointer, 'm' for mouse, 't' for touch
950
+ type: ev.type.charAt(0)
951
+ };
952
+ startPointer.startX = startPointer.x = point.pageX;
953
+ startPointer.startY = startPointer.y = point.pageY;
954
+ return startPointer;
955
+ }
956
+
957
+ angular.module('material.core')
958
+ .run(["$mdGesture", function($mdGesture) {}]) // make sure $mdGesture is always instantiated
959
+ .factory('$mdGesture', ["$$MdGestureHandler", "$$rAF", "$timeout", function($$MdGestureHandler, $$rAF, $timeout) {
960
+ HANDLERS = {};
961
+
962
+ if (shouldHijackClicks) {
963
+ addHandler('click', {
964
+ options: {
965
+ maxDistance: 6
966
+ },
967
+ onEnd: function(ev, pointer) {
968
+ if (pointer.distance < this.state.options.maxDistance) {
969
+ this.dispatchEvent(ev, 'click', null, ev);
970
+ }
971
+ }
972
+ });
973
+ }
974
+
975
+ addHandler('press', {
976
+ onStart: function(ev, pointer) {
977
+ this.dispatchEvent(ev, '$md.pressdown');
978
+ },
979
+ onEnd: function(ev, pointer) {
980
+ this.dispatchEvent(ev, '$md.pressup');
981
+ }
982
+ });
983
+
984
+
985
+ addHandler('hold', {
986
+ options: {
987
+ // If the user keeps his finger within the same <maxDistance> area for
988
+ // <delay> ms, dispatch a hold event.
989
+ maxDistance: 6,
990
+ delay: 500,
991
+ },
992
+ onCancel: function() {
993
+ $timeout.cancel(this.state.timeout);
994
+ },
995
+ onStart: function(ev, pointer) {
996
+ // For hold, require a parent to be registered with $mdGesture.register()
997
+ // Because we prevent scroll events, this is necessary.
998
+ if (!this.state.registeredParent) return this.cancel();
999
+
1000
+ this.state.pos = {x: pointer.x, y: pointer.y};
1001
+ this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() {
1002
+ this.dispatchEvent(ev, '$md.hold');
1003
+ this.cancel(); //we're done!
1004
+ }), this.state.options.delay, false);
1005
+ },
1006
+ onMove: function(ev, pointer) {
1007
+ // Don't scroll while waiting for hold
1008
+ ev.preventDefault();
1009
+ var dx = this.state.pos.x - pointer.x;
1010
+ var dy = this.state.pos.y - pointer.y;
1011
+ if (Math.sqrt(dx*dx + dy*dy) > this.options.maxDistance) {
1012
+ this.cancel();
1013
+ }
1014
+ },
1015
+ onEnd: function(ev, pointer) {
1016
+ this.onCancel();
1017
+ },
1018
+ });
1019
+
1020
+ addHandler('drag', {
1021
+ options: {
1022
+ minDistance: 6,
1023
+ horizontal: true,
1024
+ },
1025
+ onStart: function(ev) {
1026
+ // For drag, require a parent to be registered with $mdGesture.register()
1027
+ if (!this.state.registeredParent) this.cancel();
1028
+ },
1029
+ onMove: function(ev, pointer) {
1030
+ var shouldStartDrag, shouldCancel;
1031
+ // Don't allow touch events to scroll while we're dragging or
1032
+ // deciding if this touchmove is a proper drag
1033
+ ev.preventDefault();
1034
+
1035
+ if (!this.state.dragPointer) {
1036
+ if (this.state.options.horizontal) {
1037
+ shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance;
1038
+ shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * 1.5;
1039
+ } else {
1040
+ shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance;
1041
+ shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * 1.5;
1042
+ }
1043
+
1044
+ if (shouldStartDrag) {
1045
+ // Create a new pointer, starting at this point where the drag started.
1046
+ this.state.dragPointer = makeStartPointer(ev);
1047
+ updatePointerState(ev, this.state.dragPointer);
1048
+ this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer);
1049
+
1050
+ } else if (shouldCancel) {
1051
+ this.cancel();
1052
+ }
1053
+ } else {
1054
+ this.dispatchDragMove(ev);
1055
+ }
1056
+ },
1057
+ // Only dispatch these every frame; any more is unnecessray
1058
+ dispatchDragMove: $$rAF.throttle(function(ev) {
1059
+ // Make sure the drag didn't stop while waiting for the next frame
1060
+ if (this.state.isRunning) {
1061
+ updatePointerState(ev, this.state.dragPointer);
1062
+ this.dispatchEvent(ev, '$md.drag', this.state.dragPointer);
1063
+ }
1064
+ }),
1065
+ onEnd: function(ev, pointer) {
1066
+ if (this.state.dragPointer) {
1067
+ updatePointerState(ev, this.state.dragPointer);
1068
+ this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer);
1069
+ }
1070
+ }
1071
+ });
1072
+
1073
+ addHandler('swipe', {
1074
+ options: {
1075
+ minVelocity: 0.65,
1076
+ minDistance: 10,
1077
+ },
1078
+ onEnd: function(ev, pointer) {
1079
+ if (Math.abs(pointer.velocityX) > this.state.options.minVelocity &&
1080
+ Math.abs(pointer.distanceX) > this.state.options.minDistance) {
1081
+ var eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight';
1082
+ this.dispatchEvent(ev, eventType);
1083
+ }
1084
+ }
1085
+ });
1086
+
1087
+ var self;
1088
+ return self = {
1089
+ handler: addHandler,
1090
+ register: register
1091
+ };
1092
+
1093
+ function addHandler(name, definition) {
1094
+ var handler = new $$MdGestureHandler(name);
1095
+ angular.extend(handler, definition);
1096
+ HANDLERS[name] = handler;
1097
+ return self;
1098
+ }
1099
+
1100
+ function register(element, handlerName, options) {
1101
+ var handler = HANDLERS[ handlerName.replace(/^\$md./, '') ];
1102
+ if (!handler) {
1103
+ throw new Error('Failed to register element with handler ' + handlerName + '. ' +
1104
+ 'Available handlers: ' + Object.keys(HANDLERS).join(', '));
1105
+ }
1106
+ return handler.registerElement(element, options);
1107
+ }
1108
+ }])
1109
+ .factory('$$MdGestureHandler', ["$$rAF", function($$rAF) {
1110
+
1111
+ function GestureHandler(name) {
1112
+ this.name = name;
1113
+ this.state = {};
1114
+ }
1115
+ GestureHandler.prototype = {
1116
+ onStart: angular.noop,
1117
+ onMove: angular.noop,
1118
+ onEnd: angular.noop,
1119
+ onCancel: angular.noop,
1120
+ options: {},
1121
+
1122
+ dispatchEvent: dispatchEvent,
1123
+
1124
+ start: function(ev, pointer) {
1125
+ if (this.state.isRunning) return;
1126
+ var parentTarget = this.getNearestParent(ev.target);
1127
+ var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};
1128
+
1129
+ this.state = {
1130
+ isRunning: true,
1131
+ options: angular.extend({}, this.options, parentTargetOptions),
1132
+ registeredParent: parentTarget
1133
+ };
1134
+ this.onStart(ev, pointer);
1135
+ },
1136
+ move: function(ev, pointer) {
1137
+ if (!this.state.isRunning) return;
1138
+ this.onMove(ev, pointer);
1139
+ },
1140
+ end: function(ev, pointer) {
1141
+ if (!this.state.isRunning) return;
1142
+ this.onEnd(ev, pointer);
1143
+ this.state.isRunning = false;
1144
+ },
1145
+ cancel: function(ev, pointer) {
1146
+ this.onCancel(ev, pointer);
1147
+ this.state = {};
1148
+ },
1149
+
1150
+ // Find and return the nearest parent element that has been registered via
1151
+ // $mdGesture.register(element, 'handlerName').
1152
+ getNearestParent: function(node) {
1153
+ var current = node;
1154
+ while (current) {
1155
+ if ( (current.$mdGesture || {})[this.name] ) {
1156
+ return current;
1157
+ }
1158
+ current = current.parentNode;
1159
+ }
1160
+ },
1161
+
1162
+ registerElement: function(element, options) {
1163
+ var self = this;
1164
+ element[0].$mdGesture = element[0].$mdGesture || {};
1165
+ element[0].$mdGesture[this.name] = options || {};
1166
+ element.on('$destroy', onDestroy);
1167
+
1168
+ return onDestroy;
1169
+
1170
+ function onDestroy() {
1171
+ delete element[0].$mdGesture[self.name];
1172
+ element.off('$destroy', onDestroy);
1173
+ }
1174
+ },
1175
+ };
1176
+
1177
+ var customEventOptions = {
1178
+ bubbles: true,
1179
+ cancelable: true
1180
+ };
1181
+ /*
1182
+ * NOTE: dispatchEvent is very performance sensitive.
1183
+ */
1184
+ function dispatchEvent(srcEvent, eventType, eventPointer, /*original DOMEvent */ev) {
1185
+ eventPointer = eventPointer || pointer;
1186
+ var eventObj;
1187
+
1188
+ if (eventType === 'click') {
1189
+ eventObj = document.createEvent('MouseEvents');
1190
+ eventObj.initMouseEvent(
1191
+ 'click', true, true, window, ev.detail,
1192
+ ev.screenX, ev.screenY, ev.clientX, ev.clientY,
1193
+ ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey,
1194
+ ev.button, ev.relatedTarget || null
1195
+ );
1196
+
1197
+ } else {
1198
+ eventObj = document.createEvent('CustomEvent');
1199
+ eventObj.initCustomEvent(eventType, true, true, {});
1200
+ }
1201
+ eventObj.$material = true;
1202
+ eventObj.pointer = eventPointer;
1203
+ eventObj.srcEvent = srcEvent;
1204
+ eventPointer.target.dispatchEvent(eventObj);
1205
+ }
1206
+
1207
+ return GestureHandler;
1208
+ }]);
1209
+
1210
+ })();
1211
+
1212
+ (function() {
1213
+ 'use strict';
1214
+
1215
+ angular.module('material.core')
1216
+ .provider('$$interimElement', InterimElementProvider);
1217
+
1218
+ /*
1219
+ * @ngdoc service
1220
+ * @name $$interimElement
1221
+ * @module material.core
1222
+ *
1223
+ * @description
1224
+ *
1225
+ * Factory that contructs `$$interimElement.$service` services.
1226
+ * Used internally in material design for elements that appear on screen temporarily.
1227
+ * The service provides a promise-like API for interacting with the temporary
1228
+ * elements.
1229
+ *
1230
+ * ```js
1231
+ * app.service('$mdToast', function($$interimElement) {
1232
+ * var $mdToast = $$interimElement(toastDefaultOptions);
1233
+ * return $mdToast;
1234
+ * });
1235
+ * ```
1236
+ * @param {object=} defaultOptions Options used by default for the `show` method on the service.
1237
+ *
1238
+ * @returns {$$interimElement.$service}
1239
+ *
1240
+ */
1241
+
1242
+ function InterimElementProvider() {
1243
+ createInterimElementProvider.$get = InterimElementFactory;
1244
+ InterimElementFactory.$inject = ["$document", "$q", "$rootScope", "$timeout", "$rootElement", "$animate", "$interpolate", "$mdCompiler", "$mdTheming"];
1245
+ return createInterimElementProvider;
1246
+
1247
+ /**
1248
+ * Returns a new provider which allows configuration of a new interimElement
1249
+ * service. Allows configuration of default options & methods for options,
1250
+ * as well as configuration of 'preset' methods (eg dialog.basic(): basic is a preset method)
1251
+ */
1252
+ function createInterimElementProvider(interimFactoryName) {
1253
+ var EXPOSED_METHODS = ['onHide', 'onShow', 'onRemove'];
1254
+ var providerConfig = {
1255
+ presets: {}
1256
+ };
1257
+ var provider = {
1258
+ setDefaults: setDefaults,
1259
+ addPreset: addPreset,
1260
+ $get: factory
1261
+ };
1262
+
1263
+ /**
1264
+ * all interim elements will come with the 'build' preset
1265
+ */
1266
+ provider.addPreset('build', {
1267
+ methods: ['controller', 'controllerAs', 'resolve',
1268
+ 'template', 'templateUrl', 'themable', 'transformTemplate', 'parent']
1269
+ });
1270
+
1271
+ factory.$inject = ["$$interimElement", "$animate", "$injector"];
1272
+ return provider;
1273
+
1274
+ /**
1275
+ * Save the configured defaults to be used when the factory is instantiated
1276
+ */
1277
+ function setDefaults(definition) {
1278
+ providerConfig.optionsFactory = definition.options;
1279
+ providerConfig.methods = (definition.methods || []).concat(EXPOSED_METHODS);
1280
+ return provider;
1281
+ }
1282
+
1283
+ /**
1284
+ * Save the configured preset to be used when the factory is instantiated
1285
+ */
1286
+ function addPreset(name, definition) {
1287
+ definition = definition || {};
1288
+ definition.methods = definition.methods || [];
1289
+ definition.options = definition.options || function() { return {}; };
1290
+
1291
+ if (/^cancel|hide|show$/.test(name)) {
1292
+ throw new Error("Preset '" + name + "' in " + interimFactoryName + " is reserved!");
1293
+ }
1294
+ if (definition.methods.indexOf('_options') > -1) {
1295
+ throw new Error("Method '_options' in " + interimFactoryName + " is reserved!");
1296
+ }
1297
+ providerConfig.presets[name] = {
1298
+ methods: definition.methods.concat(EXPOSED_METHODS),
1299
+ optionsFactory: definition.options,
1300
+ argOption: definition.argOption
1301
+ };
1302
+ return provider;
1303
+ }
1304
+
1305
+ /**
1306
+ * Create a factory that has the given methods & defaults implementing interimElement
1307
+ */
1308
+ /* @ngInject */
1309
+ function factory($$interimElement, $animate, $injector) {
1310
+ var defaultMethods;
1311
+ var defaultOptions;
1312
+ var interimElementService = $$interimElement();
1313
+
1314
+ /*
1315
+ * publicService is what the developer will be using.
1316
+ * It has methods hide(), cancel(), show(), build(), and any other
1317
+ * presets which were set during the config phase.
1318
+ */
1319
+ var publicService = {
1320
+ hide: interimElementService.hide,
1321
+ cancel: interimElementService.cancel,
1322
+ show: showInterimElement
1323
+ };
1324
+
1325
+ defaultMethods = providerConfig.methods || [];
1326
+ // This must be invoked after the publicService is initialized
1327
+ defaultOptions = invokeFactory(providerConfig.optionsFactory, {});
1328
+
1329
+ angular.forEach(providerConfig.presets, function(definition, name) {
1330
+ var presetDefaults = invokeFactory(definition.optionsFactory, {});
1331
+ var presetMethods = (definition.methods || []).concat(defaultMethods);
1332
+
1333
+ // Every interimElement built with a preset has a field called `$type`,
1334
+ // which matches the name of the preset.
1335
+ // Eg in preset 'confirm', options.$type === 'confirm'
1336
+ angular.extend(presetDefaults, { $type: name });
1337
+
1338
+ // This creates a preset class which has setter methods for every
1339
+ // method given in the `.addPreset()` function, as well as every
1340
+ // method given in the `.setDefaults()` function.
1341
+ //
1342
+ // @example
1343
+ // .setDefaults({
1344
+ // methods: ['hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent'],
1345
+ // options: dialogDefaultOptions
1346
+ // })
1347
+ // .addPreset('alert', {
1348
+ // methods: ['title', 'ok'],
1349
+ // options: alertDialogOptions
1350
+ // })
1351
+ //
1352
+ // Set values will be passed to the options when interimElemnt.show() is called.
1353
+ function Preset(opts) {
1354
+ this._options = angular.extend({}, presetDefaults, opts);
1355
+ }
1356
+ angular.forEach(presetMethods, function(name) {
1357
+ Preset.prototype[name] = function(value) {
1358
+ this._options[name] = value;
1359
+ return this;
1360
+ };
1361
+ });
1362
+
1363
+ // Create shortcut method for one-linear methods
1364
+ if (definition.argOption) {
1365
+ var methodName = 'show' + name.charAt(0).toUpperCase() + name.slice(1);
1366
+ publicService[methodName] = function(arg) {
1367
+ var config = publicService[name](arg);
1368
+ return publicService.show(config);
1369
+ };
1370
+ }
1371
+
1372
+ // eg $mdDialog.alert() will return a new alert preset
1373
+ publicService[name] = function(arg) {
1374
+ // If argOption is supplied, eg `argOption: 'content'`, then we assume
1375
+ // if the argument is not an options object then it is the `argOption` option.
1376
+ //
1377
+ // @example `$mdToast.simple('hello')` // sets options.content to hello
1378
+ // // because argOption === 'content'
1379
+ if (arguments.length && definition.argOption && !angular.isObject(arg) &&
1380
+ !angular.isArray(arg)) {
1381
+ return (new Preset())[definition.argOption](arg);
1382
+ } else {
1383
+ return new Preset(arg);
1384
+ }
1385
+
1386
+ };
1387
+ });
1388
+
1389
+ return publicService;
1390
+
1391
+ function showInterimElement(opts) {
1392
+ // opts is either a preset which stores its options on an _options field,
1393
+ // or just an object made up of options
1394
+ if (opts && opts._options) opts = opts._options;
1395
+ return interimElementService.show(
1396
+ angular.extend({}, defaultOptions, opts)
1397
+ );
1398
+ }
1399
+
1400
+ /**
1401
+ * Helper to call $injector.invoke with a local of the factory name for
1402
+ * this provider.
1403
+ * If an $mdDialog is providing options for a dialog and tries to inject
1404
+ * $mdDialog, a circular dependency error will happen.
1405
+ * We get around that by manually injecting $mdDialog as a local.
1406
+ */
1407
+ function invokeFactory(factory, defaultVal) {
1408
+ var locals = {};
1409
+ locals[interimFactoryName] = publicService;
1410
+ return $injector.invoke(factory || function() { return defaultVal; }, {}, locals);
1411
+ }
1412
+
1413
+ }
1414
+
1415
+ }
1416
+
1417
+ /* @ngInject */
1418
+ function InterimElementFactory($document, $q, $rootScope, $timeout, $rootElement, $animate,
1419
+ $interpolate, $mdCompiler, $mdTheming ) {
1420
+ var startSymbol = $interpolate.startSymbol(),
1421
+ endSymbol = $interpolate.endSymbol(),
1422
+ usesStandardSymbols = ((startSymbol === '{{') && (endSymbol === '}}')),
1423
+ processTemplate = usesStandardSymbols ? angular.identity : replaceInterpolationSymbols;
1424
+
1425
+ return function createInterimElementService() {
1426
+ /*
1427
+ * @ngdoc service
1428
+ * @name $$interimElement.$service
1429
+ *
1430
+ * @description
1431
+ * A service used to control inserting and removing an element into the DOM.
1432
+ *
1433
+ */
1434
+ var stack = [];
1435
+ var service;
1436
+ return service = {
1437
+ show: show,
1438
+ hide: hide,
1439
+ cancel: cancel
1440
+ };
1441
+
1442
+ /*
1443
+ * @ngdoc method
1444
+ * @name $$interimElement.$service#show
1445
+ * @kind function
1446
+ *
1447
+ * @description
1448
+ * Adds the `$interimElement` to the DOM and returns a promise that will be resolved or rejected
1449
+ * with hide or cancel, respectively.
1450
+ *
1451
+ * @param {*} options is hashMap of settings
1452
+ * @returns a Promise
1453
+ *
1454
+ */
1455
+ function show(options) {
1456
+ if (stack.length) {
1457
+ service.cancel();
1458
+ }
1459
+
1460
+ var interimElement = new InterimElement(options);
1461
+
1462
+ stack.push(interimElement);
1463
+ return interimElement.show().then(function() {
1464
+ return interimElement.deferred.promise;
1465
+ });
1466
+ }
1467
+
1468
+ /*
1469
+ * @ngdoc method
1470
+ * @name $$interimElement.$service#hide
1471
+ * @kind function
1472
+ *
1473
+ * @description
1474
+ * Removes the `$interimElement` from the DOM and resolves the promise returned from `show`
1475
+ *
1476
+ * @param {*} resolveParam Data to resolve the promise with
1477
+ * @returns a Promise that will be resolved after the element has been removed.
1478
+ *
1479
+ */
1480
+ function hide(response) {
1481
+ var interimElement = stack.shift();
1482
+ interimElement && interimElement.remove().then(function() {
1483
+ interimElement.deferred.resolve(response);
1484
+ });
1485
+
1486
+ return interimElement ? interimElement.deferred.promise : $q.when(response);
1487
+ }
1488
+
1489
+ /*
1490
+ * @ngdoc method
1491
+ * @name $$interimElement.$service#cancel
1492
+ * @kind function
1493
+ *
1494
+ * @description
1495
+ * Removes the `$interimElement` from the DOM and rejects the promise returned from `show`
1496
+ *
1497
+ * @param {*} reason Data to reject the promise with
1498
+ * @returns Promise that will be rejected after the element has been removed.
1499
+ *
1500
+ */
1501
+ function cancel(reason) {
1502
+ var interimElement = stack.shift();
1503
+ interimElement && interimElement.remove().then(function() {
1504
+ interimElement.deferred.reject(reason);
1505
+ });
1506
+
1507
+ return interimElement ? interimElement.deferred.promise : $q.reject(reason);
1508
+ }
1509
+
1510
+
1511
+ /*
1512
+ * Internal Interim Element Object
1513
+ * Used internally to manage the DOM element and related data
1514
+ */
1515
+ function InterimElement(options) {
1516
+ var self;
1517
+ var hideTimeout, element;
1518
+
1519
+ options = options || {};
1520
+ options = angular.extend({
1521
+ scope: options.scope || $rootScope.$new(options.isolateScope),
1522
+ onShow: function(scope, element, options) {
1523
+ return $animate.enter(element, options.parent);
1524
+ },
1525
+ onRemove: function(scope, element, options) {
1526
+ // Element could be undefined if a new element is shown before
1527
+ // the old one finishes compiling.
1528
+ return element && $animate.leave(element) || $q.when();
1529
+ }
1530
+ }, options);
1531
+
1532
+ if (options.template) {
1533
+ options.template = processTemplate(options.template);
1534
+ }
1535
+
1536
+ return self = {
1537
+ options: options,
1538
+ deferred: $q.defer(),
1539
+ show: function() {
1540
+ return $mdCompiler.compile(options).then(function(compileData) {
1541
+ angular.extend(compileData.locals, self.options);
1542
+
1543
+ // Search for parent at insertion time, if not specified
1544
+ if (angular.isString(options.parent)) {
1545
+ options.parent = angular.element($document[0].querySelector(options.parent));
1546
+ } else if (!options.parent) {
1547
+ options.parent = $rootElement.find('body');
1548
+ if (!options.parent.length) options.parent = $rootElement;
1549
+ }
1550
+
1551
+ element = compileData.link(options.scope);
1552
+ if (options.themable) $mdTheming(element);
1553
+ var ret = options.onShow(options.scope, element, options);
1554
+ return $q.when(ret)
1555
+ .then(function(){
1556
+ // Issue onComplete callback when the `show()` finishes
1557
+ (options.onComplete || angular.noop)(options.scope, element, options);
1558
+ startHideTimeout();
1559
+ });
1560
+
1561
+ function startHideTimeout() {
1562
+ if (options.hideDelay) {
1563
+ hideTimeout = $timeout(service.cancel, options.hideDelay) ;
1564
+ }
1565
+ }
1566
+ });
1567
+ },
1568
+ cancelTimeout: function() {
1569
+ if (hideTimeout) {
1570
+ $timeout.cancel(hideTimeout);
1571
+ hideTimeout = undefined;
1572
+ }
1573
+ },
1574
+ remove: function() {
1575
+ self.cancelTimeout();
1576
+ var ret = options.onRemove(options.scope, element, options);
1577
+ return $q.when(ret).then(function() {
1578
+ options.scope.$destroy();
1579
+ });
1580
+ }
1581
+ };
1582
+ }
1583
+ };
1584
+
1585
+ /*
1586
+ * Replace `{{` and `}}` in a string (usually a template) with the actual start-/endSymbols used
1587
+ * for interpolation. This allows pre-defined templates (for components such as dialog, toast etc)
1588
+ * to continue to work in apps that use custom interpolation start-/endSymbols.
1589
+ *
1590
+ * @param {string} text The text in which to replace `{{` / `}}`
1591
+ * @returns {string} The modified string using the actual interpolation start-/endSymbols
1592
+ */
1593
+ function replaceInterpolationSymbols(text) {
1594
+ if (!text || !angular.isString(text)) return text;
1595
+ return text.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
1596
+ }
1597
+ }
1598
+
1599
+ }
1600
+
1601
+ })();
1602
+
1603
+ (function() {
1604
+ 'use strict';
1605
+
1606
+ /**
1607
+ * @ngdoc module
1608
+ * @name material.core.componentRegistry
1609
+ *
1610
+ * @description
1611
+ * A component instance registration service.
1612
+ * Note: currently this as a private service in the SideNav component.
1613
+ */
1614
+ angular.module('material.core')
1615
+ .factory('$mdComponentRegistry', ComponentRegistry);
1616
+
1617
+ /*
1618
+ * @private
1619
+ * @ngdoc factory
1620
+ * @name ComponentRegistry
1621
+ * @module material.core.componentRegistry
1622
+ *
1623
+ */
1624
+ function ComponentRegistry($log, $q) {
1625
+
1626
+ var self;
1627
+ var instances = [ ];
1628
+ var pendings = { };
1629
+
1630
+ return self = {
1631
+ /**
1632
+ * Used to print an error when an instance for a handle isn't found.
1633
+ */
1634
+ notFoundError: function(handle) {
1635
+ $log.error('No instance found for handle', handle);
1636
+ },
1637
+ /**
1638
+ * Return all registered instances as an array.
1639
+ */
1640
+ getInstances: function() {
1641
+ return instances;
1642
+ },
1643
+
1644
+ /**
1645
+ * Get a registered instance.
1646
+ * @param handle the String handle to look up for a registered instance.
1647
+ */
1648
+ get: function(handle) {
1649
+ if ( !isValidID(handle) ) return null;
1650
+
1651
+ var i, j, instance;
1652
+ for(i = 0, j = instances.length; i < j; i++) {
1653
+ instance = instances[i];
1654
+ if(instance.$$mdHandle === handle) {
1655
+ return instance;
1656
+ }
1657
+ }
1658
+ return null;
1659
+ },
1660
+
1661
+ /**
1662
+ * Register an instance.
1663
+ * @param instance the instance to register
1664
+ * @param handle the handle to identify the instance under.
1665
+ */
1666
+ register: function(instance, handle) {
1667
+ if ( !handle ) return angular.noop;
1668
+
1669
+ instance.$$mdHandle = handle;
1670
+ instances.push(instance);
1671
+ resolveWhen();
1672
+
1673
+ return deregister;
1674
+
1675
+ /**
1676
+ * Remove registration for an instance
1677
+ */
1678
+ function deregister() {
1679
+ var index = instances.indexOf(instance);
1680
+ if (index !== -1) {
1681
+ instances.splice(index, 1);
1682
+ }
1683
+ }
1684
+
1685
+ /**
1686
+ * Resolve any pending promises for this instance
1687
+ */
1688
+ function resolveWhen() {
1689
+ var dfd = pendings[handle];
1690
+ if ( dfd ) {
1691
+ dfd.resolve( instance );
1692
+ delete pendings[handle];
1693
+ }
1694
+ }
1695
+ },
1696
+
1697
+ /**
1698
+ * Async accessor to registered component instance
1699
+ * If not available then a promise is created to notify
1700
+ * all listeners when the instance is registered.
1701
+ */
1702
+ when : function(handle) {
1703
+ if ( isValidID(handle) ) {
1704
+ var deferred = $q.defer();
1705
+ var instance = self.get(handle);
1706
+
1707
+ if ( instance ) {
1708
+ deferred.resolve( instance );
1709
+ } else {
1710
+ pendings[handle] = deferred;
1711
+ }
1712
+
1713
+ return deferred.promise;
1714
+ }
1715
+ return $q.reject("Invalid `md-component-id` value.");
1716
+ }
1717
+
1718
+ };
1719
+
1720
+ function isValidID(handle){
1721
+ return handle && (handle !== "");
1722
+ }
1723
+
1724
+ }
1725
+ ComponentRegistry.$inject = ["$log", "$q"];
1726
+
1727
+
1728
+ })();
1729
+
1730
+ (function() {
1731
+ 'use strict';
1732
+
1733
+ angular.module('material.core')
1734
+ .factory('$mdInkRipple', InkRippleService)
1735
+ .directive('mdInkRipple', InkRippleDirective)
1736
+ .directive('mdNoInk', attrNoDirective())
1737
+ .directive('mdNoBar', attrNoDirective())
1738
+ .directive('mdNoStretch', attrNoDirective());
1739
+
1740
+ function InkRippleDirective($mdInkRipple) {
1741
+ return {
1742
+ controller: angular.noop,
1743
+ link: function (scope, element, attr) {
1744
+ if (attr.hasOwnProperty('mdInkRippleCheckbox')) {
1745
+ $mdInkRipple.attachCheckboxBehavior(scope, element);
1746
+ } else {
1747
+ $mdInkRipple.attachButtonBehavior(scope, element);
1748
+ }
1749
+ }
1750
+ };
1751
+ }
1752
+ InkRippleDirective.$inject = ["$mdInkRipple"];
1753
+
1754
+ function InkRippleService($window, $timeout) {
1755
+
1756
+ return {
1757
+ attachButtonBehavior: attachButtonBehavior,
1758
+ attachCheckboxBehavior: attachCheckboxBehavior,
1759
+ attachTabBehavior: attachTabBehavior,
1760
+ attach: attach
1761
+ };
1762
+
1763
+ function attachButtonBehavior(scope, element, options) {
1764
+ return attach(scope, element, angular.extend({
1765
+ isFAB: element.hasClass('md-fab'),
1766
+ isMenuItem: element.hasClass('md-menu-item'),
1767
+ center: false,
1768
+ dimBackground: true
1769
+ }, options));
1770
+ }
1771
+
1772
+ function attachCheckboxBehavior(scope, element, options) {
1773
+ return attach(scope, element, angular.extend({
1774
+ center: true,
1775
+ dimBackground: false,
1776
+ fitRipple: true
1777
+ }, options));
1778
+ }
1779
+
1780
+ function attachTabBehavior(scope, element, options) {
1781
+ return attach(scope, element, angular.extend({
1782
+ center: false,
1783
+ dimBackground: true,
1784
+ outline: true
1785
+ }, options));
1786
+ }
1787
+
1788
+ function attach(scope, element, options) {
1789
+ if (element.controller('mdNoInk')) return angular.noop;
1790
+
1791
+ options = angular.extend({
1792
+ colorElement: element,
1793
+ mousedown: true,
1794
+ hover: true,
1795
+ focus: true,
1796
+ center: false,
1797
+ mousedownPauseTime: 150,
1798
+ dimBackground: false,
1799
+ outline: false,
1800
+ isFAB: false,
1801
+ isMenuItem: false,
1802
+ fitRipple: false
1803
+ }, options);
1804
+
1805
+ var rippleSize,
1806
+ controller = element.controller('mdInkRipple') || {},
1807
+ counter = 0,
1808
+ ripples = [],
1809
+ states = [],
1810
+ isActiveExpr = element.attr('md-highlight'),
1811
+ isActive = false,
1812
+ isHeld = false,
1813
+ node = element[0],
1814
+ rippleSizeSetting = element.attr('md-ripple-size'),
1815
+ color = parseColor(element.attr('md-ink-ripple')) || parseColor($window.getComputedStyle(options.colorElement[0]).color || 'rgb(0, 0, 0)');
1816
+
1817
+ switch (rippleSizeSetting) {
1818
+ case 'full':
1819
+ options.isFAB = true;
1820
+ break;
1821
+ case 'partial':
1822
+ options.isFAB = false;
1823
+ break;
1824
+ }
1825
+
1826
+ // expose onInput for ripple testing
1827
+ if (options.mousedown) {
1828
+ element.on('$md.pressdown', onPressDown)
1829
+ .on('$md.pressup', onPressUp);
1830
+ }
1831
+
1832
+ controller.createRipple = createRipple;
1833
+
1834
+ if (isActiveExpr) {
1835
+ scope.$watch(isActiveExpr, function watchActive(newValue) {
1836
+ isActive = newValue;
1837
+ if (isActive && !ripples.length) {
1838
+ $timeout(function () { createRipple(0, 0); }, 0, false);
1839
+ }
1840
+ angular.forEach(ripples, updateElement);
1841
+ });
1842
+ }
1843
+
1844
+ // Publish self-detach method if desired...
1845
+ return function detach() {
1846
+ element.off('$md.pressdown', onPressDown)
1847
+ .off('$md.pressup', onPressUp);
1848
+ getRippleContainer().remove();
1849
+ };
1850
+
1851
+ /**
1852
+ * Gets the current ripple container
1853
+ * If there is no ripple container, it creates one and returns it
1854
+ *
1855
+ * @returns {angular.element} ripple container element
1856
+ */
1857
+ function getRippleContainer() {
1858
+ var container = element.data('$mdRippleContainer');
1859
+ if (container) return container;
1860
+ container = angular.element('<div class="md-ripple-container">');
1861
+ element.append(container);
1862
+ element.data('$mdRippleContainer', container);
1863
+ return container;
1864
+ }
1865
+
1866
+ function parseColor(color) {
1867
+ if (!color) return;
1868
+ if (color.indexOf('rgba') === 0) return color.replace(/\d?\.?\d*\s*\)\s*$/, '0.1)');
1869
+ if (color.indexOf('rgb') === 0) return rgbToRGBA(color);
1870
+ if (color.indexOf('#') === 0) return hexToRGBA(color);
1871
+
1872
+ /**
1873
+ * Converts a hex value to an rgba string
1874
+ *
1875
+ * @param {string} hex value (3 or 6 digits) to be converted
1876
+ *
1877
+ * @returns {string} rgba color with 0.1 alpha
1878
+ */
1879
+ function hexToRGBA(color) {
1880
+ var hex = color.charAt(0) === '#' ? color.substr(1) : color,
1881
+ dig = hex.length / 3,
1882
+ red = hex.substr(0, dig),
1883
+ grn = hex.substr(dig, dig),
1884
+ blu = hex.substr(dig * 2);
1885
+ if (dig === 1) {
1886
+ red += red;
1887
+ grn += grn;
1888
+ blu += blu;
1889
+ }
1890
+ return 'rgba(' + parseInt(red, 16) + ',' + parseInt(grn, 16) + ',' + parseInt(blu, 16) + ',0.1)';
1891
+ }
1892
+
1893
+ /**
1894
+ * Converts rgb value to rgba string
1895
+ *
1896
+ * @param {string} rgb color string
1897
+ *
1898
+ * @returns {string} rgba color with 0.1 alpha
1899
+ */
1900
+ function rgbToRGBA(color) {
1901
+ return color.replace(')', ', 0.1)').replace('(', 'a(');
1902
+ }
1903
+
1904
+ }
1905
+
1906
+ function removeElement(elem, wait) {
1907
+ ripples.splice(ripples.indexOf(elem), 1);
1908
+ if (ripples.length === 0) {
1909
+ getRippleContainer().css({ backgroundColor: '' });
1910
+ }
1911
+ $timeout(function () { elem.remove(); }, wait, false);
1912
+ }
1913
+
1914
+ function updateElement(elem) {
1915
+ var index = ripples.indexOf(elem),
1916
+ state = states[index] || {},
1917
+ elemIsActive = ripples.length > 1 ? false : isActive,
1918
+ elemIsHeld = ripples.length > 1 ? false : isHeld;
1919
+ if (elemIsActive || state.animating || elemIsHeld) {
1920
+ elem.addClass('md-ripple-visible');
1921
+ } else if (elem) {
1922
+ elem.removeClass('md-ripple-visible');
1923
+ if (options.outline) {
1924
+ elem.css({
1925
+ width: rippleSize + 'px',
1926
+ height: rippleSize + 'px',
1927
+ marginLeft: (rippleSize * -1) + 'px',
1928
+ marginTop: (rippleSize * -1) + 'px'
1929
+ });
1930
+ }
1931
+ removeElement(elem, options.outline ? 450 : 650);
1932
+ }
1933
+ }
1934
+
1935
+ /**
1936
+ * Creates a ripple at the provided coordinates
1937
+ *
1938
+ * @param {number} left cursor position
1939
+ * @param {number} top cursor position
1940
+ *
1941
+ * @returns {angular.element} the generated ripple element
1942
+ */
1943
+ function createRipple(left, top) {
1944
+
1945
+ color = parseColor(element.attr('md-ink-ripple')) || parseColor($window.getComputedStyle(options.colorElement[0]).color || 'rgb(0, 0, 0)');
1946
+
1947
+ var container = getRippleContainer(),
1948
+ size = getRippleSize(left, top),
1949
+ css = getRippleCss(size, left, top),
1950
+ elem = getRippleElement(css),
1951
+ index = ripples.indexOf(elem),
1952
+ state = states[index] || {};
1953
+
1954
+ rippleSize = size;
1955
+
1956
+ state.animating = true;
1957
+
1958
+ $timeout(function () {
1959
+ if (options.dimBackground) {
1960
+ container.css({ backgroundColor: color });
1961
+ }
1962
+ elem.addClass('md-ripple-placed md-ripple-scaled');
1963
+ if (options.outline) {
1964
+ elem.css({
1965
+ borderWidth: (size * 0.5) + 'px',
1966
+ marginLeft: (size * -0.5) + 'px',
1967
+ marginTop: (size * -0.5) + 'px'
1968
+ });
1969
+ } else {
1970
+ elem.css({ left: '50%', top: '50%' });
1971
+ }
1972
+ updateElement(elem);
1973
+ $timeout(function () {
1974
+ state.animating = false;
1975
+ updateElement(elem);
1976
+ }, (options.outline ? 450 : 225), false);
1977
+ }, 0, false);
1978
+
1979
+ return elem;
1980
+
1981
+ /**
1982
+ * Creates the ripple element with the provided css
1983
+ *
1984
+ * @param {object} css properties to be applied
1985
+ *
1986
+ * @returns {angular.element} the generated ripple element
1987
+ */
1988
+ function getRippleElement(css) {
1989
+ var elem = angular.element('<div class="md-ripple" data-counter="' + counter++ + '">');
1990
+ ripples.unshift(elem);
1991
+ states.unshift({ animating: true });
1992
+ container.append(elem);
1993
+ css && elem.css(css);
1994
+ return elem;
1995
+ }
1996
+
1997
+ /**
1998
+ * Calculate the ripple size
1999
+ *
2000
+ * @returns {number} calculated ripple diameter
2001
+ */
2002
+ function getRippleSize(left, top) {
2003
+ var width = container.prop('offsetWidth'),
2004
+ height = container.prop('offsetHeight'),
2005
+ multiplier, size, rect;
2006
+ if (options.isMenuItem) {
2007
+ size = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
2008
+ } else if (options.outline) {
2009
+ rect = node.getBoundingClientRect();
2010
+ left -= rect.left;
2011
+ top -= rect.top;
2012
+ width = Math.max(left, width - left);
2013
+ height = Math.max(top, height - top);
2014
+ size = 2 * Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
2015
+ } else {
2016
+ multiplier = options.isFAB ? 1.1 : 0.8;
2017
+ size = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) * multiplier;
2018
+ if (options.fitRipple) {
2019
+ size = Math.min(height, width, size);
2020
+ }
2021
+ }
2022
+ return size;
2023
+ }
2024
+
2025
+ /**
2026
+ * Generates the ripple css
2027
+ *
2028
+ * @param {number} the diameter of the ripple
2029
+ * @param {number} the left cursor offset
2030
+ * @param {number} the top cursor offset
2031
+ *
2032
+ * @returns {{backgroundColor: *, width: string, height: string, marginLeft: string, marginTop: string}}
2033
+ */
2034
+ function getRippleCss(size, left, top) {
2035
+ var rect,
2036
+ css = {
2037
+ backgroundColor: rgbaToRGB(color),
2038
+ borderColor: rgbaToRGB(color),
2039
+ width: size + 'px',
2040
+ height: size + 'px'
2041
+ };
2042
+
2043
+ if (options.outline) {
2044
+ css.width = 0;
2045
+ css.height = 0;
2046
+ } else {
2047
+ css.marginLeft = css.marginTop = (size * -0.5) + 'px';
2048
+ }
2049
+
2050
+ if (options.center) {
2051
+ css.left = css.top = '50%';
2052
+ } else {
2053
+ rect = node.getBoundingClientRect();
2054
+ css.left = Math.round((left - rect.left) / container.prop('offsetWidth') * 100) + '%';
2055
+ css.top = Math.round((top - rect.top) / container.prop('offsetHeight') * 100) + '%';
2056
+ }
2057
+
2058
+ return css;
2059
+
2060
+ /**
2061
+ * Converts rgba string to rgb, removing the alpha value
2062
+ *
2063
+ * @param {string} rgba color
2064
+ *
2065
+ * @returns {string} rgb color
2066
+ */
2067
+ function rgbaToRGB(color) {
2068
+ return color.replace('rgba', 'rgb').replace(/,[^\)\,]+\)/, ')');
2069
+ }
2070
+ }
2071
+ }
2072
+
2073
+ /**
2074
+ * Handles user input start and stop events
2075
+ *
2076
+ */
2077
+ function onPressDown(ev) {
2078
+ if (!isRippleAllowed()) return;
2079
+
2080
+ var ripple = createRipple(ev.pointer.x, ev.pointer.y);
2081
+ isHeld = true;
2082
+ }
2083
+ function onPressUp(ev) {
2084
+ isHeld = false;
2085
+ var ripple = ripples[ ripples.length - 1 ];
2086
+ $timeout(function () { updateElement(ripple); }, 0, false);
2087
+ }
2088
+
2089
+ /**
2090
+ * Determines if the ripple is allowed
2091
+ *
2092
+ * @returns {boolean} true if the ripple is allowed, false if not
2093
+ */
2094
+ function isRippleAllowed() {
2095
+ var parent = node.parentNode;
2096
+ var grandparent = parent && parent.parentNode;
2097
+ var ancestor = grandparent && grandparent.parentNode;
2098
+ return !isDisabled(node) && !isDisabled(parent) && !isDisabled(grandparent) && !isDisabled(ancestor);
2099
+ function isDisabled (elem) {
2100
+ return elem && elem.hasAttribute && elem.hasAttribute('disabled');
2101
+ }
2102
+ }
2103
+
2104
+ }
2105
+ }
2106
+ InkRippleService.$inject = ["$window", "$timeout"];
2107
+
2108
+ /**
2109
+ * noink/nobar/nostretch directive: make any element that has one of
2110
+ * these attributes be given a controller, so that other directives can
2111
+ * `require:` these and see if there is a `no<xxx>` parent attribute.
2112
+ *
2113
+ * @usage
2114
+ * <hljs lang="html">
2115
+ * <parent md-no-ink>
2116
+ * <child detect-no>
2117
+ * </child>
2118
+ * </parent>
2119
+ * </hljs>
2120
+ *
2121
+ * <hljs lang="js">
2122
+ * myApp.directive('detectNo', function() {
2123
+ * return {
2124
+ * require: ['^?mdNoInk', ^?mdNoBar'],
2125
+ * link: function(scope, element, attr, ctrls) {
2126
+ * var noinkCtrl = ctrls[0];
2127
+ * var nobarCtrl = ctrls[1];
2128
+ * if (noInkCtrl) {
2129
+ * alert("the md-no-ink flag has been specified on an ancestor!");
2130
+ * }
2131
+ * if (nobarCtrl) {
2132
+ * alert("the md-no-bar flag has been specified on an ancestor!");
2133
+ * }
2134
+ * }
2135
+ * };
2136
+ * });
2137
+ * </hljs>
2138
+ */
2139
+ function attrNoDirective() {
2140
+ return function() {
2141
+ return {
2142
+ controller: angular.noop
2143
+ };
2144
+ };
2145
+ }
2146
+ })();
2147
+
2148
+ (function() {
2149
+ 'use strict';
2150
+
2151
+ angular.module('material.core.theming.palette', [])
2152
+ .constant('$mdColorPalette', {
2153
+ 'red': {
2154
+ '50': '#ffebee',
2155
+ '100': '#ffcdd2',
2156
+ '200': '#ef9a9a',
2157
+ '300': '#e57373',
2158
+ '400': '#ef5350',
2159
+ '500': '#f44336',
2160
+ '600': '#e53935',
2161
+ '700': '#d32f2f',
2162
+ '800': '#c62828',
2163
+ '900': '#b71c1c',
2164
+ 'A100': '#ff8a80',
2165
+ 'A200': '#ff5252',
2166
+ 'A400': '#ff1744',
2167
+ 'A700': '#d50000',
2168
+ 'contrastDefaultColor': 'light',
2169
+ 'contrastDarkColors': '50 100 200 300 400 A100',
2170
+ 'contrastStrongLightColors': '500 600 700 A200 A400 A700'
2171
+ },
2172
+ 'pink': {
2173
+ '50': '#fce4ec',
2174
+ '100': '#f8bbd0',
2175
+ '200': '#f48fb1',
2176
+ '300': '#f06292',
2177
+ '400': '#ec407a',
2178
+ '500': '#e91e63',
2179
+ '600': '#d81b60',
2180
+ '700': '#c2185b',
2181
+ '800': '#ad1457',
2182
+ '900': '#880e4f',
2183
+ 'A100': '#ff80ab',
2184
+ 'A200': '#ff4081',
2185
+ 'A400': '#f50057',
2186
+ 'A700': '#c51162',
2187
+ 'contrastDefaultColor': 'light',
2188
+ 'contrastDarkColors': '50 100 200 300 400 A100',
2189
+ 'contrastStrongLightColors': '500 600 A200 A400 A700'
2190
+ },
2191
+ 'purple': {
2192
+ '50': '#f3e5f5',
2193
+ '100': '#e1bee7',
2194
+ '200': '#ce93d8',
2195
+ '300': '#ba68c8',
2196
+ '400': '#ab47bc',
2197
+ '500': '#9c27b0',
2198
+ '600': '#8e24aa',
2199
+ '700': '#7b1fa2',
2200
+ '800': '#6a1b9a',
2201
+ '900': '#4a148c',
2202
+ 'A100': '#ea80fc',
2203
+ 'A200': '#e040fb',
2204
+ 'A400': '#d500f9',
2205
+ 'A700': '#aa00ff',
2206
+ 'contrastDefaultColor': 'light',
2207
+ 'contrastDarkColors': '50 100 200 A100',
2208
+ 'contrastStrongLightColors': '300 400 A200 A400 A700'
2209
+ },
2210
+ 'deep-purple': {
2211
+ '50': '#ede7f6',
2212
+ '100': '#d1c4e9',
2213
+ '200': '#b39ddb',
2214
+ '300': '#9575cd',
2215
+ '400': '#7e57c2',
2216
+ '500': '#673ab7',
2217
+ '600': '#5e35b1',
2218
+ '700': '#512da8',
2219
+ '800': '#4527a0',
2220
+ '900': '#311b92',
2221
+ 'A100': '#b388ff',
2222
+ 'A200': '#7c4dff',
2223
+ 'A400': '#651fff',
2224
+ 'A700': '#6200ea',
2225
+ 'contrastDefaultColor': 'light',
2226
+ 'contrastDarkColors': '50 100 200 A100',
2227
+ 'contrastStrongLightColors': '300 400 A200'
2228
+ },
2229
+ 'indigo': {
2230
+ '50': '#e8eaf6',
2231
+ '100': '#c5cae9',
2232
+ '200': '#9fa8da',
2233
+ '300': '#7986cb',
2234
+ '400': '#5c6bc0',
2235
+ '500': '#3f51b5',
2236
+ '600': '#3949ab',
2237
+ '700': '#303f9f',
2238
+ '800': '#283593',
2239
+ '900': '#1a237e',
2240
+ 'A100': '#8c9eff',
2241
+ 'A200': '#536dfe',
2242
+ 'A400': '#3d5afe',
2243
+ 'A700': '#304ffe',
2244
+ 'contrastDefaultColor': 'light',
2245
+ 'contrastDarkColors': '50 100 200 A100',
2246
+ 'contrastStrongLightColors': '300 400 A200 A400'
2247
+ },
2248
+ 'blue': {
2249
+ '50': '#e3f2fd',
2250
+ '100': '#bbdefb',
2251
+ '200': '#90caf9',
2252
+ '300': '#64b5f6',
2253
+ '400': '#42a5f5',
2254
+ '500': '#2196f3',
2255
+ '600': '#1e88e5',
2256
+ '700': '#1976d2',
2257
+ '800': '#1565c0',
2258
+ '900': '#0d47a1',
2259
+ 'A100': '#82b1ff',
2260
+ 'A200': '#448aff',
2261
+ 'A400': '#2979ff',
2262
+ 'A700': '#2962ff',
2263
+ 'contrastDefaultColor': 'light',
2264
+ 'contrastDarkColors': '100 200 300 400 A100',
2265
+ 'contrastStrongLightColors': '500 600 700 A200 A400 A700'
2266
+ },
2267
+ 'light-blue': {
2268
+ '50': '#e1f5fe',
2269
+ '100': '#b3e5fc',
2270
+ '200': '#81d4fa',
2271
+ '300': '#4fc3f7',
2272
+ '400': '#29b6f6',
2273
+ '500': '#03a9f4',
2274
+ '600': '#039be5',
2275
+ '700': '#0288d1',
2276
+ '800': '#0277bd',
2277
+ '900': '#01579b',
2278
+ 'A100': '#80d8ff',
2279
+ 'A200': '#40c4ff',
2280
+ 'A400': '#00b0ff',
2281
+ 'A700': '#0091ea',
2282
+ 'contrastDefaultColor': 'dark',
2283
+ 'contrastLightColors': '500 600 700 800 900 A700',
2284
+ 'contrastStrongLightColors': '500 600 700 800 A700'
2285
+ },
2286
+ 'cyan': {
2287
+ '50': '#e0f7fa',
2288
+ '100': '#b2ebf2',
2289
+ '200': '#80deea',
2290
+ '300': '#4dd0e1',
2291
+ '400': '#26c6da',
2292
+ '500': '#00bcd4',
2293
+ '600': '#00acc1',
2294
+ '700': '#0097a7',
2295
+ '800': '#00838f',
2296
+ '900': '#006064',
2297
+ 'A100': '#84ffff',
2298
+ 'A200': '#18ffff',
2299
+ 'A400': '#00e5ff',
2300
+ 'A700': '#00b8d4',
2301
+ 'contrastDefaultColor': 'dark',
2302
+ 'contrastLightColors': '500 600 700 800 900',
2303
+ 'contrastStrongLightColors': '500 600 700 800'
2304
+ },
2305
+ 'teal': {
2306
+ '50': '#e0f2f1',
2307
+ '100': '#b2dfdb',
2308
+ '200': '#80cbc4',
2309
+ '300': '#4db6ac',
2310
+ '400': '#26a69a',
2311
+ '500': '#009688',
2312
+ '600': '#00897b',
2313
+ '700': '#00796b',
2314
+ '800': '#00695c',
2315
+ '900': '#004d40',
2316
+ 'A100': '#a7ffeb',
2317
+ 'A200': '#64ffda',
2318
+ 'A400': '#1de9b6',
2319
+ 'A700': '#00bfa5',
2320
+ 'contrastDefaultColor': 'dark',
2321
+ 'contrastLightColors': '500 600 700 800 900',
2322
+ 'contrastStrongLightColors': '500 600 700'
2323
+ },
2324
+ 'green': {
2325
+ '50': '#e8f5e9',
2326
+ '100': '#c8e6c9',
2327
+ '200': '#a5d6a7',
2328
+ '300': '#81c784',
2329
+ '400': '#66bb6a',
2330
+ '500': '#4caf50',
2331
+ '600': '#43a047',
2332
+ '700': '#388e3c',
2333
+ '800': '#2e7d32',
2334
+ '900': '#1b5e20',
2335
+ 'A100': '#b9f6ca',
2336
+ 'A200': '#69f0ae',
2337
+ 'A400': '#00e676',
2338
+ 'A700': '#00c853',
2339
+ 'contrastDefaultColor': 'dark',
2340
+ 'contrastLightColors': '500 600 700 800 900',
2341
+ 'contrastStrongLightColors': '500 600 700'
2342
+ },
2343
+ 'light-green': {
2344
+ '50': '#f1f8e9',
2345
+ '100': '#dcedc8',
2346
+ '200': '#c5e1a5',
2347
+ '300': '#aed581',
2348
+ '400': '#9ccc65',
2349
+ '500': '#8bc34a',
2350
+ '600': '#7cb342',
2351
+ '700': '#689f38',
2352
+ '800': '#558b2f',
2353
+ '900': '#33691e',
2354
+ 'A100': '#ccff90',
2355
+ 'A200': '#b2ff59',
2356
+ 'A400': '#76ff03',
2357
+ 'A700': '#64dd17',
2358
+ 'contrastDefaultColor': 'dark',
2359
+ 'contrastLightColors': '800 900',
2360
+ 'contrastStrongLightColors': '800 900'
2361
+ },
2362
+ 'lime': {
2363
+ '50': '#f9fbe7',
2364
+ '100': '#f0f4c3',
2365
+ '200': '#e6ee9c',
2366
+ '300': '#dce775',
2367
+ '400': '#d4e157',
2368
+ '500': '#cddc39',
2369
+ '600': '#c0ca33',
2370
+ '700': '#afb42b',
2371
+ '800': '#9e9d24',
2372
+ '900': '#827717',
2373
+ 'A100': '#f4ff81',
2374
+ 'A200': '#eeff41',
2375
+ 'A400': '#c6ff00',
2376
+ 'A700': '#aeea00',
2377
+ 'contrastDefaultColor': 'dark',
2378
+ 'contrastLightColors': '900',
2379
+ 'contrastStrongLightColors': '900'
2380
+ },
2381
+ 'yellow': {
2382
+ '50': '#fffde7',
2383
+ '100': '#fff9c4',
2384
+ '200': '#fff59d',
2385
+ '300': '#fff176',
2386
+ '400': '#ffee58',
2387
+ '500': '#ffeb3b',
2388
+ '600': '#fdd835',
2389
+ '700': '#fbc02d',
2390
+ '800': '#f9a825',
2391
+ '900': '#f57f17',
2392
+ 'A100': '#ffff8d',
2393
+ 'A200': '#ffff00',
2394
+ 'A400': '#ffea00',
2395
+ 'A700': '#ffd600',
2396
+ 'contrastDefaultColor': 'dark'
2397
+ },
2398
+ 'amber': {
2399
+ '50': '#fff8e1',
2400
+ '100': '#ffecb3',
2401
+ '200': '#ffe082',
2402
+ '300': '#ffd54f',
2403
+ '400': '#ffca28',
2404
+ '500': '#ffc107',
2405
+ '600': '#ffb300',
2406
+ '700': '#ffa000',
2407
+ '800': '#ff8f00',
2408
+ '900': '#ff6f00',
2409
+ 'A100': '#ffe57f',
2410
+ 'A200': '#ffd740',
2411
+ 'A400': '#ffc400',
2412
+ 'A700': '#ffab00',
2413
+ 'contrastDefaultColor': 'dark'
2414
+ },
2415
+ 'orange': {
2416
+ '50': '#fff3e0',
2417
+ '100': '#ffe0b2',
2418
+ '200': '#ffcc80',
2419
+ '300': '#ffb74d',
2420
+ '400': '#ffa726',
2421
+ '500': '#ff9800',
2422
+ '600': '#fb8c00',
2423
+ '700': '#f57c00',
2424
+ '800': '#ef6c00',
2425
+ '900': '#e65100',
2426
+ 'A100': '#ffd180',
2427
+ 'A200': '#ffab40',
2428
+ 'A400': '#ff9100',
2429
+ 'A700': '#ff6d00',
2430
+ 'contrastDefaultColor': 'dark',
2431
+ 'contrastLightColors': '800 900',
2432
+ 'contrastStrongLightColors': '800 900'
2433
+ },
2434
+ 'deep-orange': {
2435
+ '50': '#fbe9e7',
2436
+ '100': '#ffccbc',
2437
+ '200': '#ffab91',
2438
+ '300': '#ff8a65',
2439
+ '400': '#ff7043',
2440
+ '500': '#ff5722',
2441
+ '600': '#f4511e',
2442
+ '700': '#e64a19',
2443
+ '800': '#d84315',
2444
+ '900': '#bf360c',
2445
+ 'A100': '#ff9e80',
2446
+ 'A200': '#ff6e40',
2447
+ 'A400': '#ff3d00',
2448
+ 'A700': '#dd2c00',
2449
+ 'contrastDefaultColor': 'light',
2450
+ 'contrastDarkColors': '50 100 200 300 400 A100 A200',
2451
+ 'contrastStrongLightColors': '500 600 700 800 900 A400 A700'
2452
+ },
2453
+ 'brown': {
2454
+ '50': '#efebe9',
2455
+ '100': '#d7ccc8',
2456
+ '200': '#bcaaa4',
2457
+ '300': '#a1887f',
2458
+ '400': '#8d6e63',
2459
+ '500': '#795548',
2460
+ '600': '#6d4c41',
2461
+ '700': '#5d4037',
2462
+ '800': '#4e342e',
2463
+ '900': '#3e2723',
2464
+ 'A100': '#d7ccc8',
2465
+ 'A200': '#bcaaa4',
2466
+ 'A400': '#8d6e63',
2467
+ 'A700': '#5d4037',
2468
+ 'contrastDefaultColor': 'light',
2469
+ 'contrastDarkColors': '50 100 200',
2470
+ 'contrastStrongLightColors': '300 400'
2471
+ },
2472
+ 'grey': {
2473
+ '0': '#ffffff',
2474
+ '50': '#fafafa',
2475
+ '100': '#f5f5f5',
2476
+ '200': '#eeeeee',
2477
+ '300': '#e0e0e0',
2478
+ '400': '#bdbdbd',
2479
+ '500': '#9e9e9e',
2480
+ '600': '#757575',
2481
+ '700': '#616161',
2482
+ '800': '#424242',
2483
+ '900': '#212121',
2484
+ '1000': '#000000',
2485
+ 'A100': '#ffffff',
2486
+ 'A200': '#eeeeee',
2487
+ 'A400': '#bdbdbd',
2488
+ 'A700': '#616161',
2489
+ 'contrastDefaultColor': 'dark',
2490
+ 'contrastLightColors': '600 700 800 900'
2491
+ },
2492
+ 'blue-grey': {
2493
+ '50': '#eceff1',
2494
+ '100': '#cfd8dc',
2495
+ '200': '#b0bec5',
2496
+ '300': '#90a4ae',
2497
+ '400': '#78909c',
2498
+ '500': '#607d8b',
2499
+ '600': '#546e7a',
2500
+ '700': '#455a64',
2501
+ '800': '#37474f',
2502
+ '900': '#263238',
2503
+ 'A100': '#cfd8dc',
2504
+ 'A200': '#b0bec5',
2505
+ 'A400': '#78909c',
2506
+ 'A700': '#455a64',
2507
+ 'contrastDefaultColor': 'light',
2508
+ 'contrastDarkColors': '50 100 200 300',
2509
+ 'contrastStrongLightColors': '400 500'
2510
+ }
2511
+ });
2512
+ })();
2513
+
2514
+ (function() {
2515
+ 'use strict';
2516
+
2517
+ angular.module('material.core.theming', ['material.core.theming.palette'])
2518
+ .directive('mdTheme', ThemingDirective)
2519
+ .directive('mdThemable', ThemableDirective)
2520
+ .provider('$mdTheming', ThemingProvider)
2521
+ .run(generateThemes);
2522
+
2523
+ /**
2524
+ * @ngdoc provider
2525
+ * @name $mdThemingProvider
2526
+ * @module material.core
2527
+ *
2528
+ * @description Provider to configure the `$mdTheming` service.
2529
+ */
2530
+
2531
+ /**
2532
+ * @ngdoc method
2533
+ * @name $mdThemingProvider#setDefaultTheme
2534
+ * @param {string} themeName Default theme name to be applied to elements. Default value is `default`.
2535
+ */
2536
+
2537
+ /**
2538
+ * @ngdoc method
2539
+ * @name $mdThemingProvider#alwaysWatchTheme
2540
+ * @param {boolean} watch Whether or not to always watch themes for changes and re-apply
2541
+ * classes when they change. Default is `false`. Enabling can reduce performance.
2542
+ */
2543
+
2544
+ // In memory storage of defined themes and color palettes (both loaded by CSS, and user specified)
2545
+ var PALETTES;
2546
+ var THEMES;
2547
+ var themingProvider;
2548
+ var generationIsDone;
2549
+
2550
+ var DARK_FOREGROUND = {
2551
+ name: 'dark',
2552
+ '1': 'rgba(0,0,0,0.87)',
2553
+ '2': 'rgba(0,0,0,0.54)',
2554
+ '3': 'rgba(0,0,0,0.26)',
2555
+ '4': 'rgba(0,0,0,0.12)'
2556
+ };
2557
+ var LIGHT_FOREGROUND = {
2558
+ name: 'light',
2559
+ '1': 'rgba(255,255,255,1.0)',
2560
+ '2': 'rgba(255,255,255,0.7)',
2561
+ '3': 'rgba(255,255,255,0.3)',
2562
+ '4': 'rgba(255,255,255,0.12)'
2563
+ };
2564
+
2565
+ var DARK_SHADOW = '1px 1px 0px rgba(0,0,0,0.4), -1px -1px 0px rgba(0,0,0,0.4)';
2566
+ var LIGHT_SHADOW = '';
2567
+
2568
+ var DARK_CONTRAST_COLOR = colorToRgbaArray('rgba(0,0,0,0.87)');
2569
+ var LIGHT_CONTRAST_COLOR = colorToRgbaArray('rgba(255,255,255,0.87');
2570
+ var STRONG_LIGHT_CONTRAST_COLOR = colorToRgbaArray('rgb(255,255,255)');
2571
+
2572
+ var THEME_COLOR_TYPES = ['primary', 'accent', 'warn', 'background'];
2573
+ var DEFAULT_COLOR_TYPE = 'primary';
2574
+
2575
+ // A color in a theme will use these hues by default, if not specified by user.
2576
+ var LIGHT_DEFAULT_HUES = {
2577
+ 'accent': {
2578
+ 'default': 'A200',
2579
+ 'hue-1': 'A100',
2580
+ 'hue-2': 'A400',
2581
+ 'hue-3': 'A700'
2582
+ }
2583
+ };
2584
+ var DARK_DEFAULT_HUES = {
2585
+ 'background': {
2586
+ 'default': '500',
2587
+ 'hue-1': '300',
2588
+ 'hue-2': '600',
2589
+ 'hue-3': '800'
2590
+ }
2591
+ };
2592
+ THEME_COLOR_TYPES.forEach(function(colorType) {
2593
+ // Color types with unspecified default hues will use these default hue values
2594
+ var defaultDefaultHues = {
2595
+ 'default': '500',
2596
+ 'hue-1': '300',
2597
+ 'hue-2': '800',
2598
+ 'hue-3': 'A100'
2599
+ };
2600
+ if (!LIGHT_DEFAULT_HUES[colorType]) LIGHT_DEFAULT_HUES[colorType] = defaultDefaultHues;
2601
+ if (!DARK_DEFAULT_HUES[colorType]) DARK_DEFAULT_HUES[colorType] = defaultDefaultHues;
2602
+ });
2603
+
2604
+ var VALID_HUE_VALUES = [
2605
+ '50', '100', '200', '300', '400', '500', '600',
2606
+ '700', '800', '900', 'A100', 'A200', 'A400', 'A700'
2607
+ ];
2608
+
2609
+ function ThemingProvider($mdColorPalette) {
2610
+ PALETTES = {};
2611
+ THEMES = {};
2612
+ var defaultTheme = 'default';
2613
+ var alwaysWatchTheme = false;
2614
+
2615
+ // Load JS Defined Palettes
2616
+ angular.extend(PALETTES, $mdColorPalette);
2617
+
2618
+ // Default theme defined in core.js
2619
+
2620
+ ThemingService.$inject = ["$rootScope", "$log"];
2621
+ return themingProvider = {
2622
+ definePalette: definePalette,
2623
+ extendPalette: extendPalette,
2624
+ theme: registerTheme,
2625
+
2626
+ setDefaultTheme: function(theme) {
2627
+ defaultTheme = theme;
2628
+ },
2629
+ alwaysWatchTheme: function(alwaysWatch) {
2630
+ alwaysWatchTheme = alwaysWatch;
2631
+ },
2632
+ $get: ThemingService,
2633
+ _LIGHT_DEFAULT_HUES: LIGHT_DEFAULT_HUES,
2634
+ _DARK_DEFAULT_HUES: DARK_DEFAULT_HUES,
2635
+ _PALETTES: PALETTES,
2636
+ _THEMES: THEMES,
2637
+ _parseRules: parseRules,
2638
+ _rgba: rgba
2639
+ };
2640
+
2641
+ // Example: $mdThemingProvider.definePalette('neonRed', { 50: '#f5fafa', ... });
2642
+ function definePalette(name, map) {
2643
+ map = map || {};
2644
+ PALETTES[name] = checkPaletteValid(name, map);
2645
+ return themingProvider;
2646
+ }
2647
+
2648
+ // Returns an new object which is a copy of a given palette `name` with variables from
2649
+ // `map` overwritten
2650
+ // Example: var neonRedMap = $mdThemingProvider.extendPalette('red', { 50: '#f5fafafa' });
2651
+ function extendPalette(name, map) {
2652
+ return checkPaletteValid(name, angular.extend({}, PALETTES[name] || {}, map) );
2653
+ }
2654
+
2655
+ // Make sure that palette has all required hues
2656
+ function checkPaletteValid(name, map) {
2657
+ var missingColors = VALID_HUE_VALUES.filter(function(field) {
2658
+ return !map[field];
2659
+ });
2660
+ if (missingColors.length) {
2661
+ throw new Error("Missing colors %1 in palette %2!"
2662
+ .replace('%1', missingColors.join(', '))
2663
+ .replace('%2', name));
2664
+ }
2665
+
2666
+ return map;
2667
+ }
2668
+
2669
+ // Register a theme (which is a collection of color palettes to use with various states
2670
+ // ie. warn, accent, primary )
2671
+ // Optionally inherit from an existing theme
2672
+ // $mdThemingProvider.theme('custom-theme').primaryPalette('red');
2673
+ function registerTheme(name, inheritFrom) {
2674
+ inheritFrom = inheritFrom || 'default';
2675
+ if (THEMES[name]) return THEMES[name];
2676
+
2677
+ var parentTheme = typeof inheritFrom === 'string' ? THEMES[inheritFrom] : inheritFrom;
2678
+ var theme = new Theme(name);
2679
+
2680
+ if (parentTheme) {
2681
+ angular.forEach(parentTheme.colors, function(color, colorType) {
2682
+ theme.colors[colorType] = {
2683
+ name: color.name,
2684
+ // Make sure a COPY of the hues is given to the child color,
2685
+ // not the same reference.
2686
+ hues: angular.extend({}, color.hues)
2687
+ };
2688
+ });
2689
+ }
2690
+ THEMES[name] = theme;
2691
+
2692
+ return theme;
2693
+ }
2694
+
2695
+ function Theme(name) {
2696
+ var self = this;
2697
+ self.name = name;
2698
+ self.colors = {};
2699
+
2700
+ self.dark = setDark;
2701
+ setDark(false);
2702
+
2703
+ function setDark(isDark) {
2704
+ isDark = arguments.length === 0 ? true : !!isDark;
2705
+
2706
+ // If no change, abort
2707
+ if (isDark === self.isDark) return;
2708
+
2709
+ self.isDark = isDark;
2710
+
2711
+ self.foregroundPalette = self.isDark ? LIGHT_FOREGROUND : DARK_FOREGROUND;
2712
+ self.foregroundShadow = self.isDark ? DARK_SHADOW : LIGHT_SHADOW;
2713
+
2714
+ // Light and dark themes have different default hues.
2715
+ // Go through each existing color type for this theme, and for every
2716
+ // hue value that is still the default hue value from the previous light/dark setting,
2717
+ // set it to the default hue value from the new light/dark setting.
2718
+ var newDefaultHues = self.isDark ? DARK_DEFAULT_HUES : LIGHT_DEFAULT_HUES;
2719
+ var oldDefaultHues = self.isDark ? LIGHT_DEFAULT_HUES : DARK_DEFAULT_HUES;
2720
+ angular.forEach(newDefaultHues, function(newDefaults, colorType) {
2721
+ var color = self.colors[colorType];
2722
+ var oldDefaults = oldDefaultHues[colorType];
2723
+ if (color) {
2724
+ for (var hueName in color.hues) {
2725
+ if (color.hues[hueName] === oldDefaults[hueName]) {
2726
+ color.hues[hueName] = newDefaults[hueName];
2727
+ }
2728
+ }
2729
+ }
2730
+ });
2731
+
2732
+ return self;
2733
+ }
2734
+
2735
+ THEME_COLOR_TYPES.forEach(function(colorType) {
2736
+ var defaultHues = (self.isDark ? DARK_DEFAULT_HUES : LIGHT_DEFAULT_HUES)[colorType];
2737
+ self[colorType + 'Palette'] = function setPaletteType(paletteName, hues) {
2738
+ var color = self.colors[colorType] = {
2739
+ name: paletteName,
2740
+ hues: angular.extend({}, defaultHues, hues)
2741
+ };
2742
+
2743
+ Object.keys(color.hues).forEach(function(name) {
2744
+ if (!defaultHues[name]) {
2745
+ throw new Error("Invalid hue name '%1' in theme %2's %3 color %4. Available hue names: %4"
2746
+ .replace('%1', name)
2747
+ .replace('%2', self.name)
2748
+ .replace('%3', paletteName)
2749
+ .replace('%4', Object.keys(defaultHues).join(', '))
2750
+ );
2751
+ }
2752
+ });
2753
+ Object.keys(color.hues).map(function(key) {
2754
+ return color.hues[key];
2755
+ }).forEach(function(hueValue) {
2756
+ if (VALID_HUE_VALUES.indexOf(hueValue) == -1) {
2757
+ throw new Error("Invalid hue value '%1' in theme %2's %3 color %4. Available hue values: %5"
2758
+ .replace('%1', hueValue)
2759
+ .replace('%2', self.name)
2760
+ .replace('%3', colorType)
2761
+ .replace('%4', paletteName)
2762
+ .replace('%5', VALID_HUE_VALUES.join(', '))
2763
+ );
2764
+ }
2765
+ });
2766
+ return self;
2767
+ };
2768
+
2769
+ self[colorType + 'Color'] = function() {
2770
+ var args = Array.prototype.slice.call(arguments);
2771
+ console.warn('$mdThemingProviderTheme.' + colorType + 'Color() has been depricated. ' +
2772
+ 'Use $mdThemingProviderTheme.' + colorType + 'Palette() instead.');
2773
+ return self[colorType + 'Palette'].apply(self, args);
2774
+ };
2775
+ });
2776
+ }
2777
+
2778
+ /**
2779
+ * @ngdoc service
2780
+ * @name $mdTheming
2781
+ *
2782
+ * @description
2783
+ *
2784
+ * Service that makes an element apply theming related classes to itself.
2785
+ *
2786
+ * ```js
2787
+ * app.directive('myFancyDirective', function($mdTheming) {
2788
+ * return {
2789
+ * restrict: 'e',
2790
+ * link: function(scope, el, attrs) {
2791
+ * $mdTheming(el);
2792
+ * }
2793
+ * };
2794
+ * });
2795
+ * ```
2796
+ * @param {el=} element to apply theming to
2797
+ */
2798
+ /* @ngInject */
2799
+ function ThemingService($rootScope, $log) {
2800
+ applyTheme.inherit = function(el, parent) {
2801
+ var ctrl = parent.controller('mdTheme');
2802
+
2803
+ var attrThemeValue = el.attr('md-theme-watch');
2804
+ if ( (alwaysWatchTheme || angular.isDefined(attrThemeValue)) && attrThemeValue != 'false') {
2805
+ var deregisterWatch = $rootScope.$watch(function() {
2806
+ return ctrl && ctrl.$mdTheme || defaultTheme;
2807
+ }, changeTheme);
2808
+ el.on('$destroy', deregisterWatch);
2809
+ } else {
2810
+ var theme = ctrl && ctrl.$mdTheme || defaultTheme;
2811
+ changeTheme(theme);
2812
+ }
2813
+
2814
+ function changeTheme(theme) {
2815
+ if (!registered(theme)) {
2816
+ $log.warn('Attempted to use unregistered theme \'' + theme + '\'. ' +
2817
+ 'Register it with $mdThemingProvider.theme().');
2818
+ }
2819
+ var oldTheme = el.data('$mdThemeName');
2820
+ if (oldTheme) el.removeClass('md-' + oldTheme +'-theme');
2821
+ el.addClass('md-' + theme + '-theme');
2822
+ el.data('$mdThemeName', theme);
2823
+ }
2824
+ };
2825
+
2826
+ applyTheme.registered = registered;
2827
+
2828
+ return applyTheme;
2829
+
2830
+ function registered(theme) {
2831
+ if (theme === undefined || theme === '') return true;
2832
+ return THEMES[theme] !== undefined;
2833
+ }
2834
+
2835
+ function applyTheme(scope, el) {
2836
+ // Allow us to be invoked via a linking function signature.
2837
+ if (el === undefined) {
2838
+ el = scope;
2839
+ scope = undefined;
2840
+ }
2841
+ if (scope === undefined) {
2842
+ scope = $rootScope;
2843
+ }
2844
+ applyTheme.inherit(el, el);
2845
+ }
2846
+ }
2847
+ }
2848
+ ThemingProvider.$inject = ["$mdColorPalette"];
2849
+
2850
+ function ThemingDirective($mdTheming, $interpolate, $log) {
2851
+ return {
2852
+ priority: 100,
2853
+ link: {
2854
+ pre: function(scope, el, attrs) {
2855
+ var ctrl = {
2856
+ $setTheme: function(theme) {
2857
+ if (!$mdTheming.registered(theme)) {
2858
+ $log.warn('attempted to use unregistered theme \'' + theme + '\'');
2859
+ }
2860
+ ctrl.$mdTheme = theme;
2861
+ }
2862
+ };
2863
+ el.data('$mdThemeController', ctrl);
2864
+ ctrl.$setTheme($interpolate(attrs.mdTheme)(scope));
2865
+ attrs.$observe('mdTheme', ctrl.$setTheme);
2866
+ }
2867
+ }
2868
+ };
2869
+ }
2870
+ ThemingDirective.$inject = ["$mdTheming", "$interpolate", "$log"];
2871
+
2872
+ function ThemableDirective($mdTheming) {
2873
+ return $mdTheming;
2874
+ }
2875
+ ThemableDirective.$inject = ["$mdTheming"];
2876
+
2877
+ function parseRules(theme, colorType, rules) {
2878
+ checkValidPalette(theme, colorType);
2879
+
2880
+ rules = rules.replace(/THEME_NAME/g, theme.name);
2881
+ var generatedRules = [];
2882
+ var color = theme.colors[colorType];
2883
+
2884
+ var themeNameRegex = new RegExp('.md-' + theme.name + '-theme', 'g');
2885
+ // Matches '{{ primary-color }}', etc
2886
+ var hueRegex = new RegExp('(\'|")?{{\\s*(' + colorType + ')-(color|contrast)-?(\\d\\.?\\d*)?\\s*}}(\"|\')?','g');
2887
+ var simpleVariableRegex = /'?"?\{\{\s*([a-zA-Z]+)-(A?\d+|hue\-[0-3]|shadow)-?(\d\.?\d*)?\s*\}\}'?"?/g;
2888
+ var palette = PALETTES[color.name];
2889
+
2890
+ // find and replace simple variables where we use a specific hue, not angentire palette
2891
+ // eg. "{{primary-100}}"
2892
+ //\(' + THEME_COLOR_TYPES.join('\|') + '\)'
2893
+ rules = rules.replace(simpleVariableRegex, function(match, colorType, hue, opacity) {
2894
+ if (colorType === 'foreground') {
2895
+ if (hue == 'shadow') {
2896
+ return theme.foregroundShadow;
2897
+ } else {
2898
+ return theme.foregroundPalette[hue] || theme.foregroundPalette['1'];
2899
+ }
2900
+ }
2901
+ if (hue.indexOf('hue') === 0) {
2902
+ hue = theme.colors[colorType].hues[hue];
2903
+ }
2904
+ return rgba( (PALETTES[ theme.colors[colorType].name ][hue] || '').value, opacity );
2905
+ });
2906
+
2907
+ // For each type, generate rules for each hue (ie. default, md-hue-1, md-hue-2, md-hue-3)
2908
+ angular.forEach(color.hues, function(hueValue, hueName) {
2909
+ var newRule = rules
2910
+ .replace(hueRegex, function(match, _, colorType, hueType, opacity) {
2911
+ return rgba(palette[hueValue][hueType === 'color' ? 'value' : 'contrast'], opacity);
2912
+ });
2913
+ if (hueName !== 'default') {
2914
+ newRule = newRule.replace(themeNameRegex, '.md-' + theme.name + '-theme.md-' + hueName);
2915
+ }
2916
+ generatedRules.push(newRule);
2917
+ });
2918
+
2919
+ return generatedRules.join('');
2920
+ }
2921
+
2922
+ // Generate our themes at run time given the state of THEMES and PALETTES
2923
+ function generateThemes($injector) {
2924
+ var themeCss = $injector.has('$MD_THEME_CSS') ? $injector.get('$MD_THEME_CSS') : '';
2925
+
2926
+ // MD_THEME_CSS is a string generated by the build process that includes all the themable
2927
+ // components as templates
2928
+
2929
+ // Expose contrast colors for palettes to ensure that text is always readable
2930
+ angular.forEach(PALETTES, sanitizePalette);
2931
+
2932
+ // Break the CSS into individual rules
2933
+ var rules = themeCss.split(/\}(?!(\}|'|"|;))/)
2934
+ .filter(function(rule) { return rule && rule.length; })
2935
+ .map(function(rule) { return rule.trim() + '}'; });
2936
+
2937
+ var rulesByType = {};
2938
+ THEME_COLOR_TYPES.forEach(function(type) {
2939
+ rulesByType[type] = '';
2940
+ });
2941
+ var ruleMatchRegex = new RegExp('md-(' + THEME_COLOR_TYPES.join('|') + ')', 'g');
2942
+
2943
+ // Sort the rules based on type, allowing us to do color substitution on a per-type basis
2944
+ rules.forEach(function(rule) {
2945
+ var match = rule.match(ruleMatchRegex);
2946
+ // First: test that if the rule has '.md-accent', it goes into the accent set of rules
2947
+ for (var i = 0, type; type = THEME_COLOR_TYPES[i]; i++) {
2948
+ if (rule.indexOf('.md-' + type) > -1) {
2949
+ return rulesByType[type] += rule;
2950
+ }
2951
+ }
2952
+
2953
+ // If no eg 'md-accent' class is found, try to just find 'accent' in the rule and guess from
2954
+ // there
2955
+ for (i = 0; type = THEME_COLOR_TYPES[i]; i++) {
2956
+ if (rule.indexOf(type) > -1) {
2957
+ return rulesByType[type] += rule;
2958
+ }
2959
+ }
2960
+
2961
+ // Default to the primary array
2962
+ return rulesByType[DEFAULT_COLOR_TYPE] += rule;
2963
+ });
2964
+
2965
+ var styleString = '';
2966
+
2967
+ // For each theme, use the color palettes specified for `primary`, `warn` and `accent`
2968
+ // to generate CSS rules.
2969
+ angular.forEach(THEMES, function(theme) {
2970
+ THEME_COLOR_TYPES.forEach(function(colorType) {
2971
+ styleString += parseRules(theme, colorType, rulesByType[colorType] + '');
2972
+ });
2973
+ if (theme.colors.primary.name == theme.colors.accent.name) {
2974
+ console.warn("$mdThemingProvider: Using the same palette for primary and" +
2975
+ "accent. This violates the material design spec.");
2976
+ }
2977
+ });
2978
+
2979
+ // Insert our newly minted styles into the DOM
2980
+ if (!generationIsDone) {
2981
+ var style = document.createElement('style');
2982
+ style.innerHTML = styleString;
2983
+ var head = document.getElementsByTagName('head')[0];
2984
+ head.insertBefore(style, head.firstElementChild);
2985
+ generationIsDone = true;
2986
+ }
2987
+
2988
+ // The user specifies a 'default' contrast color as either light or dark,
2989
+ // then explicitly lists which hues are the opposite contrast (eg. A100 has dark, A200 has light)
2990
+ function sanitizePalette(palette) {
2991
+ var defaultContrast = palette.contrastDefaultColor;
2992
+ var lightColors = palette.contrastLightColors || [];
2993
+ var strongLightColors = palette.contrastStrongLightColors || [];
2994
+ var darkColors = palette.contrastDarkColors || [];
2995
+
2996
+ // These colors are provided as space-separated lists
2997
+ if (typeof lightColors === 'string') lightColors = lightColors.split(' ');
2998
+ if (typeof strongLightColors === 'string') strongLightColors = strongLightColors.split(' ');
2999
+ if (typeof darkColors === 'string') darkColors = darkColors.split(' ');
3000
+
3001
+ // Cleanup after ourselves
3002
+ delete palette.contrastDefaultColor;
3003
+ delete palette.contrastLightColors;
3004
+ delete palette.contrastStrongLightColors;
3005
+ delete palette.contrastDarkColors;
3006
+
3007
+ // Change { 'A100': '#fffeee' } to { 'A100': { value: '#fffeee', contrast:DARK_CONTRAST_COLOR }
3008
+ angular.forEach(palette, function(hueValue, hueName) {
3009
+ if (angular.isObject(hueValue)) return; // Already converted
3010
+ // Map everything to rgb colors
3011
+ var rgbValue = colorToRgbaArray(hueValue);
3012
+ if (!rgbValue) {
3013
+ throw new Error("Color %1, in palette %2's hue %3, is invalid. Hex or rgb(a) color expected."
3014
+ .replace('%1', hueValue)
3015
+ .replace('%2', palette.name)
3016
+ .replace('%3', hueName));
3017
+ }
3018
+
3019
+ palette[hueName] = {
3020
+ value: rgbValue,
3021
+ contrast: getContrastColor()
3022
+ };
3023
+ function getContrastColor() {
3024
+ if (defaultContrast === 'light') {
3025
+ if (darkColors.indexOf(hueName) > -1) {
3026
+ return DARK_CONTRAST_COLOR;
3027
+ } else {
3028
+ return strongLightColors.indexOf(hueName) > -1 ? STRONG_LIGHT_CONTRAST_COLOR
3029
+ : LIGHT_CONTRAST_COLOR;
3030
+ }
3031
+ } else {
3032
+ if (lightColors.indexOf(hueName) > -1) {
3033
+ return strongLightColors.indexOf(hueName) > -1 ? STRONG_LIGHT_CONTRAST_COLOR
3034
+ : LIGHT_CONTRAST_COLOR;
3035
+ } else {
3036
+ return DARK_CONTRAST_COLOR;
3037
+ }
3038
+ }
3039
+ }
3040
+ });
3041
+ }
3042
+
3043
+ }
3044
+ generateThemes.$inject = ["$injector"];
3045
+
3046
+ function checkValidPalette(theme, colorType) {
3047
+ // If theme attempts to use a palette that doesnt exist, throw error
3048
+ if (!PALETTES[ (theme.colors[colorType] || {}).name ]) {
3049
+ throw new Error(
3050
+ "You supplied an invalid color palette for theme %1's %2 palette. Available palettes: %3"
3051
+ .replace('%1', theme.name)
3052
+ .replace('%2', colorType)
3053
+ .replace('%3', Object.keys(PALETTES).join(', '))
3054
+ );
3055
+ }
3056
+ }
3057
+
3058
+ function colorToRgbaArray(clr) {
3059
+ if (angular.isArray(clr) && clr.length == 3) return clr;
3060
+ if (/^rgb/.test(clr)) {
3061
+ return clr.replace(/(^\s*rgba?\(|\)\s*$)/g, '').split(',').map(function(value, i) {
3062
+ return i == 3 ? parseFloat(value, 10) : parseInt(value, 10);
3063
+ });
3064
+ }
3065
+ if (clr.charAt(0) == '#') clr = clr.substring(1);
3066
+ if (!/^([a-fA-F0-9]{3}){1,2}$/g.test(clr)) return;
3067
+
3068
+ var dig = clr.length / 3;
3069
+ var red = clr.substr(0, dig);
3070
+ var grn = clr.substr(dig, dig);
3071
+ var blu = clr.substr(dig * 2);
3072
+ if (dig === 1) {
3073
+ red += red;
3074
+ grn += grn;
3075
+ blu += blu;
3076
+ }
3077
+ return [parseInt(red, 16), parseInt(grn, 16), parseInt(blu, 16)];
3078
+ }
3079
+
3080
+ function rgba(rgbArray, opacity) {
3081
+ if (rgbArray.length == 4) {
3082
+ rgbArray = angular.copy(rgbArray);
3083
+ opacity ? rgbArray.pop() : opacity = rgbArray.pop();
3084
+ }
3085
+ return opacity && (typeof opacity == 'number' || (typeof opacity == 'string' && opacity.length)) ?
3086
+ 'rgba(' + rgbArray.join(',') + ',' + opacity + ')' :
3087
+ 'rgb(' + rgbArray.join(',') + ')';
3088
+ }
3089
+
3090
+ })();