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