sw2at-ui 0.0.1

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