sw2at-ui 0.0.1

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