├── www ├── js │ ├── angular │ │ ├── version.txt │ │ ├── version.json │ │ ├── angular-cookies.min.js │ │ ├── angular-csp.css │ │ ├── angular-loader.min.js │ │ ├── angular-cookies.min.js.map │ │ ├── angular-loader.min.js.map │ │ ├── angular-resource.min.js │ │ ├── angular-touch.min.js │ │ ├── angular-route.min.js │ │ ├── angular-sanitize.min.js │ │ ├── errors.json │ │ ├── angular-cookies.js │ │ ├── angular-resource.min.js.map │ │ ├── angular-animate.min.js │ │ ├── angular-touch.min.js.map │ │ ├── angular-route.min.js.map │ │ ├── angular-sanitize.min.js.map │ │ ├── angular-loader.js │ │ ├── angular-animate.min.js.map │ │ ├── angular-touch.js │ │ ├── angular-sanitize.js │ │ └── angular-resource.js │ ├── controllers.js │ ├── services.js │ └── app.js ├── img │ └── ionic.png ├── fonts │ ├── ionicons.eot │ ├── ionicons.ttf │ └── ionicons.woff ├── res │ ├── icon │ │ ├── bada │ │ │ └── icon-128.png │ │ ├── ios │ │ │ ├── icon-57.png │ │ │ ├── icon-72.png │ │ │ ├── icon-57-2x.png │ │ │ └── icon-72-2x.png │ │ ├── webos │ │ │ └── icon-64.png │ │ ├── tizen │ │ │ └── icon-128.png │ │ ├── blackberry │ │ │ └── icon-80.png │ │ ├── android │ │ │ ├── icon-36-ldpi.png │ │ │ ├── icon-48-mdpi.png │ │ │ ├── icon-72-hdpi.png │ │ │ └── icon-96-xhdpi.png │ │ ├── bada-wac │ │ │ ├── icon-48-type5.png │ │ │ ├── icon-50-type3.png │ │ │ └── icon-80-type4.png │ │ └── windows-phone │ │ │ ├── icon-48.png │ │ │ ├── icon-173-tile.png │ │ │ └── icon-62-tile.png │ └── screen │ │ ├── tizen │ │ └── README.md │ │ ├── webos │ │ └── screen-64.png │ │ ├── bada-wac │ │ ├── screen-type3.png │ │ ├── screen-type4.png │ │ └── screen-type5.png │ │ ├── bada │ │ └── screen-portrait.png │ │ ├── blackberry │ │ └── screen-225.png │ │ ├── ios │ │ ├── screen-ipad-landscape.png │ │ ├── screen-ipad-portrait.png │ │ ├── screen-iphone-portrait.png │ │ ├── screen-ipad-landscape-2x.png │ │ ├── screen-ipad-portrait-2x.png │ │ ├── screen-iphone-landscape.png │ │ ├── screen-iphone-landscape-2x.png │ │ ├── screen-iphone-portrait-2x.png │ │ └── screen-iphone-portrait-568h-2x.png │ │ ├── android │ │ ├── screen-hdpi-portrait.png │ │ ├── screen-ldpi-portrait.png │ │ ├── screen-mdpi-portrait.png │ │ ├── screen-hdpi-landscape.png │ │ ├── screen-ldpi-landscape.png │ │ ├── screen-mdpi-landscape.png │ │ ├── screen-xhdpi-landscape.png │ │ └── screen-xhdpi-portrait.png │ │ └── windows-phone │ │ └── screen-portrait.jpg ├── css │ ├── app.css │ └── themes │ │ ├── ionic-ios7.min.css │ │ └── ionic-ios7.css ├── templates │ ├── pet.html │ └── app.html ├── config.xml └── index.html ├── .gitignore ├── .cordova └── config.json ├── README.md ├── platforms └── .gitignore ├── plugins └── .gitignore └── LICENSE /www/js/angular/version.txt: -------------------------------------------------------------------------------- 1 | 1.2.4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.keystore 2 | *.sw* 3 | platforms/^.* 4 | -------------------------------------------------------------------------------- /.cordova/config.json: -------------------------------------------------------------------------------- 1 | {"id":"com.ionicframework.starter","name":"StarterApp"} -------------------------------------------------------------------------------- /www/img/ionic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/img/ionic.png -------------------------------------------------------------------------------- /www/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/fonts/ionicons.eot -------------------------------------------------------------------------------- /www/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/fonts/ionicons.ttf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ionic-intro 2 | =========== 3 | 4 | A demo app for showing an intro tutorial for your apps 5 | -------------------------------------------------------------------------------- /platforms/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /plugins/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /www/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/fonts/ionicons.woff -------------------------------------------------------------------------------- /www/res/icon/bada/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/bada/icon-128.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/ios/icon-57.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/ios/icon-72.png -------------------------------------------------------------------------------- /www/res/icon/webos/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/webos/icon-64.png -------------------------------------------------------------------------------- /www/js/angular/version.json: -------------------------------------------------------------------------------- 1 | {"full":"1.2.4","major":"1","minor":"2","dot":"4","codename":"wormhole-baster","cdn":"1.2.3"} -------------------------------------------------------------------------------- /www/res/icon/ios/icon-57-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/ios/icon-57-2x.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-72-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/ios/icon-72-2x.png -------------------------------------------------------------------------------- /www/res/icon/tizen/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/tizen/icon-128.png -------------------------------------------------------------------------------- /www/res/screen/tizen/README.md: -------------------------------------------------------------------------------- 1 | # Tizen Splash Screen 2 | 3 | Splash screens are unsupported on the Tizen platform. 4 | -------------------------------------------------------------------------------- /www/res/icon/blackberry/icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/blackberry/icon-80.png -------------------------------------------------------------------------------- /www/res/screen/webos/screen-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/webos/screen-64.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-36-ldpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/android/icon-36-ldpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-48-mdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/android/icon-48-mdpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-72-hdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/android/icon-72-hdpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-96-xhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/android/icon-96-xhdpi.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-48-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/bada-wac/icon-48-type5.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-50-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/bada-wac/icon-50-type3.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-80-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/bada-wac/icon-80-type4.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/windows-phone/icon-48.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/bada-wac/screen-type3.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/bada-wac/screen-type4.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/bada-wac/screen-type5.png -------------------------------------------------------------------------------- /www/res/screen/bada/screen-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/bada/screen-portrait.png -------------------------------------------------------------------------------- /www/res/screen/blackberry/screen-225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/blackberry/screen-225.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-173-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/windows-phone/icon-173-tile.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-62-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/icon/windows-phone/icon-62-tile.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-ipad-landscape.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-ipad-portrait.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-iphone-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-hdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-hdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-ldpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-ldpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-mdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-mdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-ipad-landscape-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-ipad-portrait-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-iphone-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-hdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-hdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-ldpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-ldpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-mdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-mdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-xhdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-xhdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-xhdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/android/screen-xhdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-iphone-landscape-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-iphone-portrait-2x.png -------------------------------------------------------------------------------- /www/res/screen/windows-phone/screen-portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/windows-phone/screen-portrait.jpg -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait-568h-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionic-team/ionic-intro/HEAD/www/res/screen/ios/screen-iphone-portrait-568h-2x.png -------------------------------------------------------------------------------- /www/css/app.css: -------------------------------------------------------------------------------- 1 | #splash-page { 2 | background-color: white; 3 | } 4 | #logo { 5 | background: url('../img/ionic.png') no-repeat transparent; 6 | width: 128px; 7 | height: 128px; 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | margin: -64px 0px 0px -64px; 12 | } 13 | -------------------------------------------------------------------------------- /www/templates/pet.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {{ pet.description }} 10 | 11 | -------------------------------------------------------------------------------- /www/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | StarterApp 4 | 5 | A sample Ionic Framework app using Cordova and AngularJS 6 | 7 | 8 | Apache Cordova Team 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /www/js/controllers.js: -------------------------------------------------------------------------------- 1 | angular.module('starter.controllers', []) 2 | 3 | .controller('AppCtrl', function($scope) { 4 | // Main app controller, empty for the example 5 | }) 6 | 7 | // A simple controller that fetches a list of data 8 | .controller('PetsTabCtrl', function($scope, Pets) { 9 | // "Pets" is a service returning mock data (services.js) 10 | $scope.pets = Pets.all(); 11 | 12 | $scope.$on('tab.shown', function() { 13 | // Might do a load here 14 | }); 15 | $scope.$on('tab.hidden', function() { 16 | // Might recycle content here 17 | }); 18 | }) 19 | 20 | // A simple controller that shows a tapped item's data 21 | .controller('PetCtrl', function($scope, $routeParams, Pets) { 22 | // "Pets" is a service returning mock data (services.js) 23 | $scope.pet = Pets.get($routeParams.petId); 24 | }); 25 | -------------------------------------------------------------------------------- /www/js/angular/angular-cookies.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.4 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&d.$apply())})();k=!0;d.$watch(function(){var a,e,d;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)(e=c[a],f.isString(e))?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(m(e[a])?delete c[a]:c[a]=e[a])}); 7 | return c}]).factory("$cookieStore",["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular); 8 | //# sourceMappingURL=angular-cookies.min.js.map 9 | -------------------------------------------------------------------------------- /www/js/services.js: -------------------------------------------------------------------------------- 1 | angular.module('starter.services', []) 2 | 3 | /** 4 | * A simple example service that returns some data. 5 | */ 6 | .factory('Pets', function() { 7 | // Might use a resource here that returns a JSON array 8 | 9 | // Some fake testing data 10 | var pets = [ 11 | { id: 0, title: 'Cats', description: 'Furry little creatures. Obsessed with plotting assassination, but never following through on it.' }, 12 | { id: 1, title: 'Dogs', description: 'Lovable. Loyal almost to a fault. Smarter than they let on.' }, 13 | { id: 2, title: 'Turtles', description: 'Everyone likes turtles.' }, 14 | { id: 3, title: 'Sharks', description: 'An advanced pet. Needs millions of gallons of salt water. Will happily eat you.' } 15 | ]; 16 | 17 | return { 18 | all: function() { 19 | return pets; 20 | }, 21 | get: function(petId) { 22 | // Simple index lookup 23 | return pets[petId]; 24 | } 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /www/js/angular/angular-csp.css: -------------------------------------------------------------------------------- 1 | /* Include this file in your html if you are using the CSP mode. */ 2 | 3 | @charset "UTF-8"; 4 | 5 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], 6 | .ng-cloak, .x-ng-cloak, 7 | .ng-hide { 8 | display: none !important; 9 | } 10 | 11 | ng\:form { 12 | display: block; 13 | } 14 | 15 | /* The styles below ensure that the CSS transition will ALWAYS 16 | * animate and close. A nasty bug occurs with CSS transitions where 17 | * when the active class isn't set, or if the active class doesn't 18 | * contain any styles to transition to, then, if ngAnimate is used, 19 | * it will appear as if the webpage is broken due to the forever hanging 20 | * animations. The border-spacing (!ie) and zoom (ie) CSS properties are 21 | * used below since they trigger a transition without making the browser 22 | * animate anything and they're both highly underused CSS properties */ 23 | .ng-animate-start { border-spacing:1px 1px; -ms-zoom:1.0001; } 24 | .ng-animate-active { border-spacing:0px 0px; -ms-zoom:1; } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Drifty 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /www/js/app.js: -------------------------------------------------------------------------------- 1 | // angular.module is a global place for creating, registering and retrieving Angular modules 2 | // 'starter' is the name of this angular module example (also set in a attribute in index.html) 3 | // the 2nd parameter is an array or 'requires' 4 | // 'starter.services' is found in services.js 5 | // 'starter.controllers' is found in controllers.js 6 | angular.module('starter', ['ionic', 'ngRoute', 'ngAnimate', 'starter.services', 'starter.controllers']) 7 | 8 | .config(function ($compileProvider){ 9 | // Needed for routing to work 10 | $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/); 11 | }) 12 | 13 | .config(function($routeProvider, $locationProvider) { 14 | 15 | // Set up the initial routes that our app will respond to. 16 | // These are then tied up to our nav router which animates and 17 | // updates a navigation bar 18 | $routeProvider.when('/home', { 19 | templateUrl: 'templates/app.html', 20 | controller: 'AppCtrl' 21 | }); 22 | 23 | // if the url matches something like /pet/2 then this route 24 | // will fire off the PetCtrl controller (controllers.js) 25 | $routeProvider.when('/pet/:petId', { 26 | templateUrl: 'templates/pet.html', 27 | controller: 'PetCtrl' 28 | }); 29 | 30 | // if none of the above routes are met, use this fallback 31 | // which executes the 'AppCtrl' controller (controllers.js) 32 | $routeProvider.otherwise({ 33 | redirectTo: '/home' 34 | }); 35 | 36 | }); 37 | 38 | -------------------------------------------------------------------------------- /www/js/angular/angular-loader.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.4 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(){'use strict';function d(a){return function(){var c=arguments[0],b,c="["+(a?a+":":"")+c+"] http://errors.angularjs.org/1.2.4/"+(a?a+"/":"")+c;for(b=1;b 2 | 3 | 4 | 5 | Ionic Seed 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /www/templates/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

{{pet.title}}

16 |

{{pet.description}}

17 | 18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 |
27 |

Adopt a pet today.

28 |
29 |
30 | 34 | 38 | 41 | 42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 |

About this app

50 |

51 | This is a sample seed project for the Ionic Framework. Please change it to match your needs. 52 |

53 |
54 |
55 | 56 |
57 |
58 | -------------------------------------------------------------------------------- /www/js/angular/angular-cookies.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-cookies.min.js", 4 | "lineCount":7, 5 | "mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAoBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CAEE,CADAY,CACK,CADGZ,CAAA,CAAQW,CAAR,CACH,CAAAjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAAL,EAMWA,CANX,GAMqBX,CAAA,CAAYU,CAAZ,CANrB,GAOEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CARZ,EACMnB,CAAAqB,UAAA,CAAkBd,CAAA,CAAYU,CAAZ,CAAlB,CAAJ,CACEX,CAAA,CAAQW,CAAR,CADF,CACkBV,CAAA,CAAYU,CAAZ,CADlB,CAGE,OAAOX,CAAA,CAAQW,CAAR,CASb,IAAIE,CAAJ,CAIE,IAAKF,CAAL,GAFAK,EAEahB,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBK,CAAA,CAAeL,CAAf,CAAtB,GAEMN,CAAA,CAAYW,CAAA,CAAeL,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBK,CAAA,CAAeL,CAAf,CALpB,CAlCU,CAThB,CAEA;MAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA4HW,cA5HX,CA4H2B,CAAC,UAAD,CAAa,QAAQ,CAACoB,CAAD,CAAW,CAErD,MAAO,KAYAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHP,CACG,CADKK,CAAA,CAASE,CAAT,CACL,EAAQzB,CAAA0B,SAAA,CAAiBR,CAAjB,CAAR,CAAkCA,CAFxB,CAZd,KA4BAS,QAAQ,CAACF,CAAD,CAAMP,CAAN,CAAa,CACxBK,CAAA,CAASE,CAAT,CAAA,CAAgBzB,CAAA4B,OAAA,CAAeV,CAAf,CADQ,CA5BrB,QA0CGW,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CA1CjB,CAF8C,CAAhC,CA5H3B,CApBsC,CAArC,CAAA,CAoME1B,MApMF,CAoMUA,MAAAC,QApMV;", 6 | "sources":["angular-cookies.js"], 7 | "names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","isDefined","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] 8 | } 9 | -------------------------------------------------------------------------------- /www/css/themes/ionic-ios7.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";/*! 2 | * Copyright 2013 Drifty Co. 3 | * http://drifty.com/ 4 | 5 | * Ionic - a powerful HTML5 mobile app framework. 6 | * http://ionicframework.com/ 7 | * 8 | * 9 | * By @maxlynch, @helloimben, @adamdbradley <3 10 | * 11 | * Licensed under the MIT license. Please see LICENSE for more information. 12 | * 13 | */.content-slide-out.ng-enter,.content-slide-out>.ng-enter{z-index:1;-webkit-transition:.5s ease-in-out all;-webkit-transform:translate3d(-100%,0,0);box-shadow:-1px 0 10px rgba(0,0,0,.6)}.content-slide-out.ng-enter-active,.content-slide-out>.ng-enter-active{-webkit-transform:translate3d(0,0,0)}.content-slide-out.ng-leave,.content-slide-out>.ng-leave{z-index:0;-webkit-transition:.5s ease-in-out all;-webkit-transform:translate3d(0%,0,0)}.content-slide-out.ng-leave-active,.content-slide-out>.ng-leave-active{-webkit-transform:translate3d(10%,0,0);opacity:.8}.bar-title-in-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out;-webkit-transform:translate3d(100%,0,0);opacity:0}.bar-title-in-add-active{-webkit-transform:translate3d(0px,0,0);opacity:1}.bar-title-out-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out}.bar-title-out-add-active{-webkit-transform:translate3d(-100%,0,0);opacity:0}.bar-button-in{opacity:0}.bar-button-in-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out;-webkit-transform:translate3d(50%,0,0);opacity:0}.bar-button-in-active{-webkit-transform:translate3d(0px,0,0);opacity:1}.fade-in-out.ng-enter,.fade-in-out>.ng-enter{opacity:0;-webkit-transition:opacity .3s ease-in-out}.fade-in-out.ng-enter-active,.fade-in-out>.ng-enter-active{opacity:1}.fade-in-out.ng-leave,.fade-in-out>.ng-leave{opacity:1;-webkit-transition:opacity .3s ease-in-out}.fade-in-out.ng-leave-active,.fade-in-out>.ng-leave-active{opacity:0}.toggle{display:inline-block}.toggle input{display:none}.toggle .track{position:relative;display:inline-block;box-sizing:border-box;width:54px;height:32px;border:solid 2px #ddd;border-radius:20px;background-color:#fff;cursor:pointer;transition:.4s ease}.toggle .handle{position:absolute;display:block;width:auto;height:auto;box-shadow:0 0 2px rgba(0,0,0,.5),0 4px 5px rgba(0,0,0,.25);border-radius:20px;background-color:#fff;left:0;top:0;bottom:0;right:20px;transition:.2s ease;transition-property:left,right;transition-delay:0s,.05s}.toggle :checked+.track{border-color:#4bd863;background-color:#ccc;box-shadow:inset 0 0 0 20px #4bd863;transition:.2s ease}.toggle :checked+.track .handle{background-color:#fff;right:0;left:20px;-webkit-transform:none;transition-delay:.05s,0s} -------------------------------------------------------------------------------- /www/js/angular/angular-loader.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-loader.min.js", 4 | "lineCount":8, 5 | "mappings":"A;;;;;aAMC,SAAQ,EAAG,CCNZA,QAAS,EAAM,CAAC,CAAD,CAAS,CAWtB,MAAO,SAAS,EAAG,CAAA,IACb,EAAO,SAAA,CAAU,CAAV,CADM,CAIf,CAJe,CAKjB,EAHW,GAGX,EAHkB,CAAA,CAAS,CAAT,CAAkB,GAAlB,CAAwB,EAG1C,EAHgD,CAGhD,CAAmB,sCAAnB,EAA2D,CAAA,CAAS,CAAT,CAAkB,GAAlB,CAAwB,EAAnF,EAAyF,CACzF,KAAK,CAAL,CAAS,CAAT,CAAY,CAAZ,CAAgB,SAAA,OAAhB,CAAkC,CAAA,EAAlC,CACE,CAAA,CAAU,CAAV,EAA0B,CAAL,EAAA,CAAA,CAAS,GAAT,CAAe,GAApC,EAA2C,GAA3C,EAAkD,CAAlD,CAAoD,CAApD,EAAyD,GAAzD,CACE,kBAAA,CAjBc,UAAlB,EAAI,MAiB6B,UAAA,CAAU,CAAV,CAjBjC,CAiBiC,SAAA,CAAU,CAAV,CAhBxB,SAAA,EAAA,QAAA,CAAuB,aAAvB,CAAsC,EAAtC,CADT,CAEyB,WAAlB,EAAI,MAesB,UAAA,CAAU,CAAV,CAf1B,CACE,WADF,CAEoB,QAApB,EAAM,MAaoB,UAAA,CAAU,CAAV,CAb1B,CACE,IAAA,UAAA,CAYwB,SAAA,CAAU,CAAV,CAZxB,CADF,CAa0B,SAAA,CAAU,CAAV,CAA7B,CAEJ,OAAW,MAAJ,CAAU,CAAV,CAVU,CAXG,CD0FxBC,SAA0B,CAACC,CAAD,CAAS,CAEjC,IAAIC,EAAkBH,CAAA,CAAO,WAAP,CAAtB,CACII,EAAWJ,CAAA,CAAO,IAAP,CAMXK,EAAAA,CAAiBH,CAHZ,QAGLG;CAAiBH,CAHE,QAGnBG,CAH+B,EAG/BA,CAGJA,EAAAC,SAAA,CAAmBD,CAAAC,SAAnB,EAAuCN,CAEvC,OAAcK,EARL,OAQT,GAAcA,CARS,OAQvB,CAAiCE,QAAQ,EAAG,CAE1C,IAAIC,EAAU,EAoDd,OAAOC,SAAe,CAACC,CAAD,CAAOC,CAAP,CAAiBC,CAAjB,CAA2B,CAE7C,GAAa,gBAAb,GAKsBF,CALtB,CACE,KAAMN,EAAA,CAAS,SAAT,CAIoBS,QAJpB,CAAN,CAKAF,CAAJ,EAAgBH,CAAAM,eAAA,CAAuBJ,CAAvB,CAAhB,GACEF,CAAA,CAAQE,CAAR,CADF,CACkB,IADlB,CAGA,OAAcF,EAzET,CAyEkBE,CAzElB,CAyEL,GAAcF,CAzEK,CAyEIE,CAzEJ,CAyEnB,CAA6BH,QAAQ,EAAG,CAgNtCQ,QAASA,EAAW,CAACC,CAAD,CAAWC,CAAX,CAAmBC,CAAnB,CAAiC,CACnD,MAAO,SAAQ,EAAG,CAChBC,CAAA,CAAYD,CAAZ,EAA4B,MAA5B,CAAA,CAAoC,CAACF,CAAD,CAAWC,CAAX,CAAmBG,SAAnB,CAApC,CACA,OAAOC,EAFS,CADiC,CA/MrD,GAAI,CAACV,CAAL,CACE,KAAMR,EAAA,CAAgB,OAAhB,CAEiDO,CAFjD,CAAN,CAMF,IAAIS,EAAc,EAAlB,CAGIG,EAAY,EAHhB,CAKIC,EAASR,CAAA,CAAY,WAAZ,CAAyB,QAAzB,CALb,CAQIM,EAAiB,cAELF,CAFK,YAGPG,CAHO,UAcTX,CAdS,MAuBbD,CAvBa,UAoCTK,CAAA,CAAY,UAAZ,CAAwB,UAAxB,CApCS,SA+CVA,CAAA,CAAY,UAAZ,CAAwB,SAAxB,CA/CU,SA0DVA,CAAA,CAAY,UAAZ;AAAwB,SAAxB,CA1DU,OAqEZA,CAAA,CAAY,UAAZ,CAAwB,OAAxB,CArEY,UAiFTA,CAAA,CAAY,UAAZ,CAAwB,UAAxB,CAAoC,SAApC,CAjFS,WAmHRA,CAAA,CAAY,kBAAZ,CAAgC,UAAhC,CAnHQ,QA8HXA,CAAA,CAAY,iBAAZ,CAA+B,UAA/B,CA9HW,YA0IPA,CAAA,CAAY,qBAAZ,CAAmC,UAAnC,CA1IO,WAuJRA,CAAA,CAAY,kBAAZ,CAAgC,WAAhC,CAvJQ,QAkKXQ,CAlKW,KA8KdC,QAAQ,CAACC,CAAD,CAAQ,CACnBH,CAAAI,KAAA,CAAeD,CAAf,CACA,OAAO,KAFY,CA9KF,CAoLjBb,EAAJ,EACEW,CAAA,CAAOX,CAAP,CAGF,OAAQS,EAxM8B,CAzET,EAyE/B,CAX+C,CAtDP,CART,EAQnC,CAdiC,CAAnCpB,CA2SA,CAAkBC,MAAlB,CA/XY,CAAX,CAAA,CAgYEA,MAhYF;", 6 | "sources":["angular-loader.js","MINERR_ASSET"], 7 | "names":["minErr","setupModuleLoader","window","$injectorMinErr","ngMinErr","angular","$$minErr","factory","modules","module","name","requires","configFn","context","hasOwnProperty","invokeLater","provider","method","insertMethod","invokeQueue","arguments","moduleInstance","runBlocks","config","run","block","push"] 8 | } 9 | -------------------------------------------------------------------------------- /www/js/angular/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.4 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(H,f,z){'use strict';var u=f.$$minErr("$resource"),A=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;f.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(D,E){function n(f,h){this.template=f;this.defaults=h||{};this.urlParams={}}function v(m,h,k){function r(d,c){var e={};c=w({},h,c);s(c,function(a,c){t(a)&&(a=a());var g;if(a&&a.charAt&&"@"==a.charAt(0)){g=d;var b=a.substr(1);if(null==b||""===b||"hasOwnProperty"===b||!A.test("."+b))throw u("badmember",b);for(var b=b.split("."),f=0,h= 7 | b.length;fd&&c/el&&10>n|| 8 | (n>l?(d=!1,b.cancel&&b.cancel(a)):(a.preventDefault(),b.move&&b.move(m,a)))}});a.on("touchend mouseup",function(a){d&&(d=!1,b.end&&b.end(g(a),a))})}}}]);q.config(["$provide",function(g){g.decorator("ngClickDirective",["$delegate",function(a){a.shift();return a}])}]);q.directive("ngClick",["$parse","$timeout","$rootElement",function(g,a,b){function l(a,c,b){for(var f=0;fh)){var c= 9 | a.touches&&a.touches.length?a.touches:[a],b=c[0].clientX,c=c[0].clientY;1>b&&1>c||l(k,b,c)||(a.stopPropagation(),a.preventDefault(),a.target&&a.target.blur())}}function r(b){b=b.touches&&b.touches.length?b.touches:[b];var c=b[0].clientX,d=b[0].clientY;k.push(c,d);a(function(){for(var a=0;ah&&12>p)&&(k||(b[0].addEventListener("click",n,!0),b[0].addEventListener("touchstart",r,!0),k=[]),m=Date.now(),l(k,e,g),s&&s.blur(),v.isDefined(d.disabled)&&!1!==d.disabled||c.triggerHandler("click",[a]));f()});c.onclick=function(a){};c.on("click",function(b,c){a.$apply(function(){h(a,{$event:c||b})})});c.on("mousedown",function(a){c.addClass(p)});c.on("mousemove mouseup",function(a){c.removeClass(p)})}}]);t("ngSwipeLeft",-1,"swipeleft");t("ngSwipeRight",1,"swiperight")})(window, 12 | window.angular); 13 | //# sourceMappingURL=angular-touch.min.js.map 14 | -------------------------------------------------------------------------------- /www/js/angular/angular-route.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.4 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(t,c,A){'use strict';function x(r,m,d,b,h){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(l,z,k,B,w){function v(){g&&(g.$destroy(),g=null);q&&(h.leave(q),q=null)}function u(){var a=r.current&&r.current.locals,e=a&&a.$template;if(e){var y=l.$new(),s=w(y,c.noop);s.html(e);h.enter(s,null,q||z,function(){!c.isDefined(n)||n&&!l.$eval(n)||m()});v();var e=d(s.contents()),f=r.current;g=f.scope=y;q=s;f.controller&&(a.$scope=g,a=b(f.controller,a),f.controllerAs&& 7 | (g[f.controllerAs]=a),s.data("$ngControllerController",a),s.children().data("$ngControllerController",a));e(g);g.$emit("$viewContentLoaded");g.$eval(p)}else v()}var g,q,n=k.autoscroll,p=k.onload||"";l.$on("$routeChangeSuccess",u);u()}}}t=c.module("ngRoute",["ng"]).provider("$route",function(){function r(b,h){return c.extend(new (c.extend(function(){},{prototype:b})),h)}function m(b,c){var l=c.caseInsensitiveMatch,d={originalPath:b,regexp:b},k=d.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g, 8 | function(b,c,h,d){b="?"===d?d:null;d="*"===d?d:null;k.push({name:h,optional:!!b});c=c||"";return""+(b?"":c)+"(?:"+(b?c:"")+(d&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=RegExp("^"+b+"$",l?"i":"");return d}var d={};this.when=function(b,h){d[b]=c.extend({reloadOnSearch:!0},h,b&&m(b,h));if(b){var l="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/";d[l]=c.extend({redirectTo:b},m(l,h))}return this};this.otherwise=function(b){this.when(null,b);return this};this.$get= 9 | ["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(b,h,l,m,k,t,w,v){function u(){var a=g(),e=p.current;if(a&&e&&a.$$route===e.$$route&&c.equals(a.pathParams,e.pathParams)&&!a.reloadOnSearch&&!n)e.params=a.params,c.copy(e.params,l),b.$broadcast("$routeUpdate",e);else if(a||e)n=!1,b.$broadcast("$routeChangeStart",a,e),(p.current=a)&&a.redirectTo&&(c.isString(a.redirectTo)?h.path(q(a.redirectTo,a.params)).search(a.params).replace():h.url(a.redirectTo(a.pathParams, 10 | h.path(),h.search())).replace()),m.when(a).then(function(){if(a){var b=c.extend({},a.resolve),e,f;c.forEach(b,function(a,e){b[e]=c.isString(a)?k.get(a):k.invoke(a)});c.isDefined(e=a.template)?c.isFunction(e)&&(e=e(a.params)):c.isDefined(f=a.templateUrl)&&(c.isFunction(f)&&(f=f(a.params)),f=v.getTrustedResourceUrl(f),c.isDefined(f)&&(a.loadedTemplateUrl=f,e=t.get(f,{cache:w}).then(function(a){return a.data})));c.isDefined(e)&&(b.$template=e);return m.all(b)}}).then(function(d){a==p.current&&(a&&(a.locals= 11 | d,c.copy(a.params,l)),b.$broadcast("$routeChangeSuccess",a,e))},function(c){a==p.current&&b.$broadcast("$routeChangeError",a,e,c)})}function g(){var a,b;c.forEach(d,function(d,l){var f;if(f=!b){var g=h.path();f=d.keys;var m={};if(d.regexp)if(g=d.regexp.exec(g)){for(var k=1,q=g.length;k=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= 8 | a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| 10 | c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); 14 | //# sourceMappingURL=angular-sanitize.min.js.map 15 | -------------------------------------------------------------------------------- /www/css/themes/ionic-ios7.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /*! 3 | * Copyright 2013 Drifty Co. 4 | * http://drifty.com/ 5 | 6 | * Ionic - a powerful HTML5 mobile app framework. 7 | * http://ionicframework.com/ 8 | * 9 | * 10 | * By @maxlynch, @helloimben, @adamdbradley <3 11 | * 12 | * Licensed under the MIT license. Please see LICENSE for more information. 13 | * 14 | */ 15 | /** 16 | * Nav controllers and header bar animations 17 | */ 18 | /* 19 | .content-slide-in { 20 | &.ng-enter, > .ng-enter { 21 | -webkit-transition: 0.5s ease-in-out all; 22 | -webkit-transform:translate3d(100%,0,0) ; 23 | box-shadow: -1px 0px 10px rgba(0,0,0,0.6); 24 | } 25 | &.ng-enter-active, > .ng-enter-active { 26 | -webkit-transform:translate3d(0,0,0) ; 27 | } 28 | &.ng-leave, > .ng-leave { 29 | -webkit-transition: 0.5s ease-in-out all; 30 | -webkit-transform:translate3d(0%,0,0); 31 | } 32 | &.ng-leave-active, > .ng-leave-active { 33 | -webkit-transform:translate3d(-10%,0,0); 34 | opacity: 0.8; 35 | } 36 | } 37 | */ 38 | .content-slide-out.ng-enter, .content-slide-out > .ng-enter { 39 | z-index: 1; 40 | -webkit-transition: 0.5s ease-in-out all; 41 | -webkit-transform: translate3d(-100%, 0, 0); 42 | box-shadow: -1px 0px 10px rgba(0, 0, 0, 0.6); } 43 | .content-slide-out.ng-enter-active, .content-slide-out > .ng-enter-active { 44 | -webkit-transform: translate3d(0, 0, 0); } 45 | .content-slide-out.ng-leave, .content-slide-out > .ng-leave { 46 | z-index: 0; 47 | -webkit-transition: 0.5s ease-in-out all; 48 | -webkit-transform: translate3d(0%, 0, 0); } 49 | .content-slide-out.ng-leave-active, .content-slide-out > .ng-leave-active { 50 | -webkit-transform: translate3d(10%, 0, 0); 51 | opacity: 0.8; } 52 | 53 | .bar-title-in-add { 54 | -webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out; 55 | -webkit-transform: translate3d(100%, 0, 0); 56 | opacity: 0; } 57 | 58 | .bar-title-in-add-active { 59 | -webkit-transform: translate3d(0px, 0, 0); 60 | opacity: 1; } 61 | 62 | .bar-title-out-add { 63 | -webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out; } 64 | 65 | .bar-title-out-add-active { 66 | -webkit-transform: translate3d(-100%, 0, 0); 67 | opacity: 0; } 68 | 69 | .bar-button-in { 70 | opacity: 0; } 71 | 72 | .bar-button-in-add { 73 | -webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out; 74 | -webkit-transform: translate3d(50%, 0, 0); 75 | opacity: 0; } 76 | 77 | .bar-button-in-active { 78 | -webkit-transform: translate3d(0px, 0, 0); 79 | opacity: 1; } 80 | 81 | /** 82 | * Tab controller animations 83 | */ 84 | .fade-in-out.ng-enter, .fade-in-out > .ng-enter { 85 | opacity: 0; 86 | -webkit-transition: opacity 0.3s ease-in-out; } 87 | .fade-in-out.ng-enter-active, .fade-in-out > .ng-enter-active { 88 | opacity: 1; } 89 | .fade-in-out.ng-leave, .fade-in-out > .ng-leave { 90 | opacity: 1; 91 | -webkit-transition: opacity 0.3s ease-in-out; } 92 | .fade-in-out.ng-leave-active, .fade-in-out > .ng-leave-active { 93 | opacity: 0; } 94 | 95 | /* the overall container of the toggle */ 96 | .toggle { 97 | display: inline-block; } 98 | 99 | /* hide the actual checkbox */ 100 | .toggle input { 101 | display: none; } 102 | 103 | .toggle .track { 104 | /* the background of the toggle's track area */ 105 | /* also the track appearance when the toggle is "off" */ 106 | position: relative; 107 | display: inline-block; 108 | box-sizing: border-box; 109 | width: 54px; 110 | height: 32px; 111 | border: solid 2px #dddddd; 112 | border-radius: 20px; 113 | background-color: white; 114 | cursor: pointer; 115 | transition: 0.4s ease; } 116 | 117 | .toggle .handle { 118 | /* the handle (circle) thats inside the toggle's track area */ 119 | /* also the appearance when the handle is "off" */ 120 | position: absolute; 121 | display: block; 122 | width: auto; 123 | /* override defaults */ 124 | height: auto; 125 | /* override defaults */ 126 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.5), 0 4px 5px rgba(0, 0, 0, 0.25); 127 | border-radius: 20px; 128 | background-color: white; 129 | left: 0; 130 | top: 0; 131 | bottom: 0; 132 | right: 20px; 133 | transition: 0.2s ease; 134 | transition-property: left, right; 135 | transition-delay: 0s, .05s; } 136 | 137 | .toggle :checked + .track { 138 | /* When the toggle is "on" */ 139 | /* the track when the toggle is "on" */ 140 | border-color: #4bd863; 141 | background-color: #ccc; 142 | box-shadow: inset 0 0 0 20px #4bd863; 143 | transition: 0.2s ease; 144 | /* the handle when the toggle is "on" */ } 145 | .toggle :checked + .track .handle { 146 | background-color: white; 147 | right: 0; 148 | left: 20px; 149 | -webkit-transform: none; 150 | transition-delay: .05s, 0s; } 151 | -------------------------------------------------------------------------------- /www/js/angular/errors.json: -------------------------------------------------------------------------------- 1 | {"id":"ng","generated":"Fri Dec 06 2013 13:49:28 GMT-0500 (EST)","errors":{"$cacheFactory":{"iid":"CacheId '{0}' is already taken!"},"ngModel":{"nonassign":"Expression '{0}' is non-assignable. Element: {1}"},"$sce":{"iequirks":"Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks mode. You can fix this by adding the text to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.","insecurl":"Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}","icontext":"Attempted to trust a value in invalid context. Context: {0}; Value: {1}","imatcher":"Matchers may only be \"self\", string patterns or RegExp objects","iwcard":"Illegal sequence *** in string matcher. String: {0}","itype":"Attempted to trust a non-string value in a content requiring a string: Context: {0}","unsafe":"Attempting to use an unsafe value in a safe context."},"$controller":{"noscp":"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`."},"$compile":{"nodomevents":"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.","multidir":"Multiple directives [{0}, {1}] asking for {2} on: {3}","nonassign":"Expression '{0}' used with directive '{1}' is non-assignable!","tplrt":"Template for directive '{0}' must have exactly one root element. {1}","selmulti":"Binding to the 'multiple' attribute is not supported. Element: {0}","tpload":"Failed to load template: {0}","iscp":"Invalid isolate scope definition for directive '{0}'. Definition: {... {1}: '{2}' ...}","ctreq":"Controller '{0}', required by directive '{1}', can't be found!","uterdir":"Unterminated attribute, found '{0}' but no matching '{1}' found."},"$injector":{"modulerr":"Failed to instantiate module {0} due to:\n{1}","unpr":"Unknown provider: {0}","itkn":"Incorrect injection token! Expected service name as string, got {0}","cdep":"Circular dependency found: {0}","nomod":"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.","pget":"Provider '{0}' must define $get factory method."},"$rootScope":{"inprog":"{0} already in progress","infdig":"{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}"},"ngPattern":{"noregexp":"Expected {0} to be a RegExp but was {1}. Element: {2}"},"$interpolate":{"noconcat":"Error while interpolating: {0}\nStrict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce","interr":"Can't interpolate: {0}\n{1}"},"jqLite":{"offargs":"jqLite#off() does not support the `selector` argument","onargs":"jqLite#on() does not support the `selector` or `eventData` parameters","nosel":"Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"},"ngOptions":{"iexp":"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}"},"ngRepeat":{"iidexp":"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.","dupes":"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}","iexp":"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'."},"ng":{"areq":"Argument '{0}' is {1}","cpws":"Can't copy! Making copies of Window or Scope instances is not supported.","badname":"hasOwnProperty is not a valid {0} name","btstrpd":"App Already Bootstrapped with this Element '{0}'","cpi":"Can't copy! Source and destination are identical."},"$animate":{"notcsel":"Expecting class selector starting with '.' got '{0}'."},"ngTransclude":{"orphan":"Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: {0}"},"$parse":{"isecfld":"Referencing \"constructor\" field in Angular expressions is disallowed! Expression: {0}","syntax":"Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].","isecdom":"Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}","lexerr":"Lexer Error: {0} at column{1} in expression [{2}].","ueoe":"Unexpected end of expression: {0}","isecwindow":"Referencing the Window in Angular expressions is disallowed! Expression: {0}","isecfn":"Referencing Function in Angular expressions is disallowed! Expression: {0}"},"$httpBackend":{"noxhr":"This browser does not support XMLHttpRequest."},"$location":{"ipthprfx":"Invalid url \"{0}\", missing path prefix \"{1}\".","isrcharg":"The first argument of the `$location#search()` call must be a string or an object.","ihshprfx":"Invalid url \"{0}\", missing hash prefix \"{1}\"."},"$resource":{"badargs":"Expected up to 4 arguments [params, data, success, error], got {0} arguments","badmember":"Dotted member path \"@{0}\" is invalid.","badcfg":"Error in resource configuration. Expected response to contain an {0} but got an {1}","badname":"hasOwnProperty is not a valid parameter name."},"$sanitize":{"badparse":"The sanitizer was unable to parse the following block of html: {0}"}}} -------------------------------------------------------------------------------- /www/js/angular/angular-cookies.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.4 3 | * (c) 2010-2014 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | /** 9 | * @ngdoc overview 10 | * @name ngCookies 11 | * @description 12 | * 13 | * # ngCookies 14 | * 15 | * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies. 16 | * 17 | * {@installModule cookies} 18 | * 19 | *
20 | * 21 | * See {@link ngCookies.$cookies `$cookies`} and 22 | * {@link ngCookies.$cookieStore `$cookieStore`} for usage. 23 | */ 24 | 25 | 26 | angular.module('ngCookies', ['ng']). 27 | /** 28 | * @ngdoc object 29 | * @name ngCookies.$cookies 30 | * @requires $browser 31 | * 32 | * @description 33 | * Provides read/write access to browser's cookies. 34 | * 35 | * Only a simple Object is exposed and by adding or removing properties to/from 36 | * this object, new cookies are created/deleted at the end of current $eval. 37 | * 38 | * Requires the {@link ngCookies `ngCookies`} module to be installed. 39 | * 40 | * @example 41 | 42 | 43 | 51 | 52 | 53 | */ 54 | factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) { 55 | var cookies = {}, 56 | lastCookies = {}, 57 | lastBrowserCookies, 58 | runEval = false, 59 | copy = angular.copy, 60 | isUndefined = angular.isUndefined; 61 | 62 | //creates a poller fn that copies all cookies from the $browser to service & inits the service 63 | $browser.addPollFn(function() { 64 | var currentCookies = $browser.cookies(); 65 | if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl 66 | lastBrowserCookies = currentCookies; 67 | copy(currentCookies, lastCookies); 68 | copy(currentCookies, cookies); 69 | if (runEval) $rootScope.$apply(); 70 | } 71 | })(); 72 | 73 | runEval = true; 74 | 75 | //at the end of each eval, push cookies 76 | //TODO: this should happen before the "delayed" watches fire, because if some cookies are not 77 | // strings or browser refuses to store some cookies, we update the model in the push fn. 78 | $rootScope.$watch(push); 79 | 80 | return cookies; 81 | 82 | 83 | /** 84 | * Pushes all the cookies from the service to the browser and verifies if all cookies were 85 | * stored. 86 | */ 87 | function push() { 88 | var name, 89 | value, 90 | browserCookies, 91 | updated; 92 | 93 | //delete any cookies deleted in $cookies 94 | for (name in lastCookies) { 95 | if (isUndefined(cookies[name])) { 96 | $browser.cookies(name, undefined); 97 | } 98 | } 99 | 100 | //update all cookies updated in $cookies 101 | for(name in cookies) { 102 | value = cookies[name]; 103 | if (!angular.isString(value)) { 104 | if (angular.isDefined(lastCookies[name])) { 105 | cookies[name] = lastCookies[name]; 106 | } else { 107 | delete cookies[name]; 108 | } 109 | } else if (value !== lastCookies[name]) { 110 | $browser.cookies(name, value); 111 | updated = true; 112 | } 113 | } 114 | 115 | //verify what was actually stored 116 | if (updated){ 117 | updated = false; 118 | browserCookies = $browser.cookies(); 119 | 120 | for (name in cookies) { 121 | if (cookies[name] !== browserCookies[name]) { 122 | //delete or reset all cookies that the browser dropped from $cookies 123 | if (isUndefined(browserCookies[name])) { 124 | delete cookies[name]; 125 | } else { 126 | cookies[name] = browserCookies[name]; 127 | } 128 | updated = true; 129 | } 130 | } 131 | } 132 | } 133 | }]). 134 | 135 | 136 | /** 137 | * @ngdoc object 138 | * @name ngCookies.$cookieStore 139 | * @requires $cookies 140 | * 141 | * @description 142 | * Provides a key-value (string-object) storage, that is backed by session cookies. 143 | * Objects put or retrieved from this storage are automatically serialized or 144 | * deserialized by angular's toJson/fromJson. 145 | * 146 | * Requires the {@link ngCookies `ngCookies`} module to be installed. 147 | * 148 | * @example 149 | */ 150 | factory('$cookieStore', ['$cookies', function($cookies) { 151 | 152 | return { 153 | /** 154 | * @ngdoc method 155 | * @name ngCookies.$cookieStore#get 156 | * @methodOf ngCookies.$cookieStore 157 | * 158 | * @description 159 | * Returns the value of given cookie key 160 | * 161 | * @param {string} key Id to use for lookup. 162 | * @returns {Object} Deserialized cookie value. 163 | */ 164 | get: function(key) { 165 | var value = $cookies[key]; 166 | return value ? angular.fromJson(value) : value; 167 | }, 168 | 169 | /** 170 | * @ngdoc method 171 | * @name ngCookies.$cookieStore#put 172 | * @methodOf ngCookies.$cookieStore 173 | * 174 | * @description 175 | * Sets a value for given cookie key 176 | * 177 | * @param {string} key Id for the `value`. 178 | * @param {Object} value Value to be stored. 179 | */ 180 | put: function(key, value) { 181 | $cookies[key] = angular.toJson(value); 182 | }, 183 | 184 | /** 185 | * @ngdoc method 186 | * @name ngCookies.$cookieStore#remove 187 | * @methodOf ngCookies.$cookieStore 188 | * 189 | * @description 190 | * Remove given cookie 191 | * 192 | * @param {string} key Id of the key-value pair to delete. 193 | */ 194 | remove: function(key) { 195 | delete $cookies[key]; 196 | } 197 | }; 198 | 199 | }]); 200 | 201 | 202 | })(window, window.angular); 203 | -------------------------------------------------------------------------------- /www/js/angular/angular-resource.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-resource.min.js", 4 | "lineCount":11, 5 | "mappings":"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", 6 | "sources":["angular-resource.js"], 7 | "names":["window","angular","undefined","$resourceMinErr","$$minErr","MEMBER_NAME_REGEX","module","factory","$http","$q","Route","template","defaults","urlParams","resourceFactory","url","paramDefaults","actions","extractParams","data","actionParams","ids","extend","forEach","value","key","isFunction","charAt","path","test","keys","split","i","ii","length","obj","defaultResponseInterceptor","response","resource","Resource","copy","route","DEFAULT_ACTIONS","action","name","hasBody","method","a1","a2","a3","a4","params","success","error","arguments","isInstanceCall","isArray","httpConfig","responseInterceptor","interceptor","responseErrorInterceptor","responseError","setUrlParams","promise","then","$promise","item","push","$resolved","noop","reject","headers","prototype","result","call","bind","Resource.bind","additionalParamDefaults","config","actionUrl","self","val","encodedVal","param","RegExp","replace","_","urlParam","hasOwnProperty","isDefined","encodeURIComponent","match","leadingSlashes","tail"] 8 | } 9 | -------------------------------------------------------------------------------- /www/js/angular/angular-animate.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.4 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(C,k,F){'use strict';k.module("ngAnimate",["ng"]).config(["$provide","$animateProvider",function(M,G){function l(l){for(var h=0;h=v&&d>=p&&f()}var r=a.data(z),m=l(a);if(-1!=m.className.indexOf(c)&&r){var k=r.timings,n=r.stagger,p=r.maxDuration,q=r.activeClassName,v=1E3*Math.max(k.transitionDelay,k.animationDelay),x=Date.now(),w=Q+" "+P,u=r.ii,y,r="",s=[];if(0} */ 107 | var modules = {}; 108 | 109 | /** 110 | * @ngdoc function 111 | * @name angular.module 112 | * @description 113 | * 114 | * The `angular.module` is a global place for creating, registering and retrieving Angular 115 | * modules. 116 | * All modules (angular core or 3rd party) that should be available to an application must be 117 | * registered using this mechanism. 118 | * 119 | * When passed two or more arguments, a new module is created. If passed only one argument, an 120 | * existing module (the name passed as the first argument to `module`) is retrieved. 121 | * 122 | * 123 | * # Module 124 | * 125 | * A module is a collection of services, directives, filters, and configuration information. 126 | * `angular.module` is used to configure the {@link AUTO.$injector $injector}. 127 | * 128 | *
129 |      * // Create a new module
130 |      * var myModule = angular.module('myModule', []);
131 |      *
132 |      * // register a new service
133 |      * myModule.value('appName', 'MyCoolApp');
134 |      *
135 |      * // configure existing services inside initialization blocks.
136 |      * myModule.config(function($locationProvider) {
137 |      *   // Configure existing providers
138 |      *   $locationProvider.hashPrefix('!');
139 |      * });
140 |      * 
141 | * 142 | * Then you can create an injector and load your modules like this: 143 | * 144 | *
145 |      * var injector = angular.injector(['ng', 'MyModule'])
146 |      * 
147 | * 148 | * However it's more likely that you'll just use 149 | * {@link ng.directive:ngApp ngApp} or 150 | * {@link angular.bootstrap} to simplify this process for you. 151 | * 152 | * @param {!string} name The name of the module to create or retrieve. 153 | * @param {Array.=} requires If specified then new module is being created. If 154 | * unspecified then the the module is being retrieved for further configuration. 155 | * @param {Function} configFn Optional configuration function for the module. Same as 156 | * {@link angular.Module#methods_config Module#config()}. 157 | * @returns {module} new module with the {@link angular.Module} api. 158 | */ 159 | return function module(name, requires, configFn) { 160 | var assertNotHasOwnProperty = function(name, context) { 161 | if (name === 'hasOwnProperty') { 162 | throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); 163 | } 164 | }; 165 | 166 | assertNotHasOwnProperty(name, 'module'); 167 | if (requires && modules.hasOwnProperty(name)) { 168 | modules[name] = null; 169 | } 170 | return ensure(modules, name, function() { 171 | if (!requires) { 172 | throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + 173 | "the module name or forgot to load it. If registering a module ensure that you " + 174 | "specify the dependencies as the second argument.", name); 175 | } 176 | 177 | /** @type {!Array.>} */ 178 | var invokeQueue = []; 179 | 180 | /** @type {!Array.} */ 181 | var runBlocks = []; 182 | 183 | var config = invokeLater('$injector', 'invoke'); 184 | 185 | /** @type {angular.Module} */ 186 | var moduleInstance = { 187 | // Private state 188 | _invokeQueue: invokeQueue, 189 | _runBlocks: runBlocks, 190 | 191 | /** 192 | * @ngdoc property 193 | * @name angular.Module#requires 194 | * @propertyOf angular.Module 195 | * @returns {Array.} List of module names which must be loaded before this module. 196 | * @description 197 | * Holds the list of modules which the injector will load before the current module is 198 | * loaded. 199 | */ 200 | requires: requires, 201 | 202 | /** 203 | * @ngdoc property 204 | * @name angular.Module#name 205 | * @propertyOf angular.Module 206 | * @returns {string} Name of the module. 207 | * @description 208 | */ 209 | name: name, 210 | 211 | 212 | /** 213 | * @ngdoc method 214 | * @name angular.Module#provider 215 | * @methodOf angular.Module 216 | * @param {string} name service name 217 | * @param {Function} providerType Construction function for creating new instance of the 218 | * service. 219 | * @description 220 | * See {@link AUTO.$provide#provider $provide.provider()}. 221 | */ 222 | provider: invokeLater('$provide', 'provider'), 223 | 224 | /** 225 | * @ngdoc method 226 | * @name angular.Module#factory 227 | * @methodOf angular.Module 228 | * @param {string} name service name 229 | * @param {Function} providerFunction Function for creating new instance of the service. 230 | * @description 231 | * See {@link AUTO.$provide#factory $provide.factory()}. 232 | */ 233 | factory: invokeLater('$provide', 'factory'), 234 | 235 | /** 236 | * @ngdoc method 237 | * @name angular.Module#service 238 | * @methodOf angular.Module 239 | * @param {string} name service name 240 | * @param {Function} constructor A constructor function that will be instantiated. 241 | * @description 242 | * See {@link AUTO.$provide#service $provide.service()}. 243 | */ 244 | service: invokeLater('$provide', 'service'), 245 | 246 | /** 247 | * @ngdoc method 248 | * @name angular.Module#value 249 | * @methodOf angular.Module 250 | * @param {string} name service name 251 | * @param {*} object Service instance object. 252 | * @description 253 | * See {@link AUTO.$provide#value $provide.value()}. 254 | */ 255 | value: invokeLater('$provide', 'value'), 256 | 257 | /** 258 | * @ngdoc method 259 | * @name angular.Module#constant 260 | * @methodOf angular.Module 261 | * @param {string} name constant name 262 | * @param {*} object Constant value. 263 | * @description 264 | * Because the constant are fixed, they get applied before other provide methods. 265 | * See {@link AUTO.$provide#constant $provide.constant()}. 266 | */ 267 | constant: invokeLater('$provide', 'constant', 'unshift'), 268 | 269 | /** 270 | * @ngdoc method 271 | * @name angular.Module#animation 272 | * @methodOf angular.Module 273 | * @param {string} name animation name 274 | * @param {Function} animationFactory Factory function for creating new instance of an 275 | * animation. 276 | * @description 277 | * 278 | * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. 279 | * 280 | * 281 | * Defines an animation hook that can be later used with 282 | * {@link ngAnimate.$animate $animate} service and directives that use this service. 283 | * 284 | *
285 |            * module.animation('.animation-name', function($inject1, $inject2) {
286 |            *   return {
287 |            *     eventName : function(element, done) {
288 |            *       //code to run the animation
289 |            *       //once complete, then run done()
290 |            *       return function cancellationFunction(element) {
291 |            *         //code to cancel the animation
292 |            *       }
293 |            *     }
294 |            *   }
295 |            * })
296 |            * 
297 | * 298 | * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and 299 | * {@link ngAnimate ngAnimate module} for more information. 300 | */ 301 | animation: invokeLater('$animateProvider', 'register'), 302 | 303 | /** 304 | * @ngdoc method 305 | * @name angular.Module#filter 306 | * @methodOf angular.Module 307 | * @param {string} name Filter name. 308 | * @param {Function} filterFactory Factory function for creating new instance of filter. 309 | * @description 310 | * See {@link ng.$filterProvider#register $filterProvider.register()}. 311 | */ 312 | filter: invokeLater('$filterProvider', 'register'), 313 | 314 | /** 315 | * @ngdoc method 316 | * @name angular.Module#controller 317 | * @methodOf angular.Module 318 | * @param {string|Object} name Controller name, or an object map of controllers where the 319 | * keys are the names and the values are the constructors. 320 | * @param {Function} constructor Controller constructor function. 321 | * @description 322 | * See {@link ng.$controllerProvider#register $controllerProvider.register()}. 323 | */ 324 | controller: invokeLater('$controllerProvider', 'register'), 325 | 326 | /** 327 | * @ngdoc method 328 | * @name angular.Module#directive 329 | * @methodOf angular.Module 330 | * @param {string|Object} name Directive name, or an object map of directives where the 331 | * keys are the names and the values are the factories. 332 | * @param {Function} directiveFactory Factory function for creating new instance of 333 | * directives. 334 | * @description 335 | * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}. 336 | */ 337 | directive: invokeLater('$compileProvider', 'directive'), 338 | 339 | /** 340 | * @ngdoc method 341 | * @name angular.Module#config 342 | * @methodOf angular.Module 343 | * @param {Function} configFn Execute this function on module load. Useful for service 344 | * configuration. 345 | * @description 346 | * Use this method to register work which needs to be performed on module loading. 347 | */ 348 | config: config, 349 | 350 | /** 351 | * @ngdoc method 352 | * @name angular.Module#run 353 | * @methodOf angular.Module 354 | * @param {Function} initializationFn Execute this function after injector creation. 355 | * Useful for application initialization. 356 | * @description 357 | * Use this method to register work which should be performed when the injector is done 358 | * loading all modules. 359 | */ 360 | run: function(block) { 361 | runBlocks.push(block); 362 | return this; 363 | } 364 | }; 365 | 366 | if (configFn) { 367 | config(configFn); 368 | } 369 | 370 | return moduleInstance; 371 | 372 | /** 373 | * @param {string} provider 374 | * @param {string} method 375 | * @param {String=} insertMethod 376 | * @returns {angular.Module} 377 | */ 378 | function invokeLater(provider, method, insertMethod) { 379 | return function() { 380 | invokeQueue[insertMethod || 'push']([provider, method, arguments]); 381 | return moduleInstance; 382 | }; 383 | } 384 | }); 385 | }; 386 | }); 387 | 388 | } 389 | 390 | setupModuleLoader(window); 391 | })(window); 392 | 393 | /** 394 | * Closure compiler type information 395 | * 396 | * @typedef { { 397 | * requires: !Array., 398 | * invokeQueue: !Array.>, 399 | * 400 | * service: function(string, Function):angular.Module, 401 | * factory: function(string, Function):angular.Module, 402 | * value: function(string, *):angular.Module, 403 | * 404 | * filter: function(string, Function):angular.Module, 405 | * 406 | * init: function(Function):angular.Module 407 | * } } 408 | */ 409 | angular.Module; 410 | 411 | -------------------------------------------------------------------------------- /www/js/angular/angular-animate.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-animate.min.js", 4 | "lineCount":22, 5 | "mappings":"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", 6 | "sources":["angular-animate.js"], 7 | "names":["window","angular","undefined","module","config","$provide","$animateProvider","extractElementNode","element","i","length","elm","nodeType","ELEMENT_NODE","noop","forEach","selectors","$$selectors","NG_ANIMATE_STATE","NG_ANIMATE_CLASS_NAME","rootAnimateState","decorator","$delegate","$injector","$sniffer","$rootElement","$timeout","$rootScope","$document","lookup","name","matches","flagMap","classes","substr","split","transitions","animations","push","klass","selectorFactoryName","get","performAnimation","animationEvent","className","parentElement","afterElement","domOperation","doneCallback","onBeforeAnimationsComplete","cancelled","fireDOMOperation","closeAnimation","data","done","invokeRegisteredAnimationFns","phase","allAnimationFnsComplete","endFnName","animation","index","animationPhaseCompleted","phaseCompletionFlag","currentAnimation","isClassBased","fireDoneCallbackAsync","hasBeenRun","cleanup","closeAnimationTimeout","node","currentClassName","animationLookup","replace","parent","ngAnimateState","animationsDisabled","running","structural","allowCancel","afterFn","beforeFn","charAt","toUpperCase","futureClassName","cancel","cancelAnimations","beforeComplete","event","classNameToken","indexOf","addClass","cancelChildAnimations","querySelectorAll","beforeEnd","isCancelledFlag","afterComplete","afterEnd","disabled","removeClass","removeData","isRoot","state","result","$$postDigest","enter","enabled","leave","move","value","arguments","register","$window","afterReflow","callback","animationReflowQueue","animationTimer","fn","lookupCache","getElementAnimationDetails","cacheKey","transitionDuration","transitionDelay","animationDuration","animationDelay","transitionDelayStyle","animationDelayStyle","transitionDurationStyle","transitionPropertyStyle","elementStyles","getComputedStyle","TRANSITION_PROP","DURATION_KEY","Math","max","parseMaxTime","PROPERTY_KEY","DELAY_KEY","ANIMATION_PROP","aDuration","parseInt","ANIMATION_ITERATION_COUNT_KEY","str","maxValue","values","isString","parseFloat","getCacheKey","parentID","NG_ANIMATE_PARENT_KEY","parentCounter","animateSetup","eventCacheKey","stagger","ii","total","staggerClassName","staggerCacheKey","applyClasses","timings","maxDuration","activeClassName","NG_ANIMATE_FALLBACK_CLASS_NAME","NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME","style","NG_ANIMATE_CSS_DATA_KEY","unblockTransitions","prop","unblockKeyframeAnimations","animateRun","activeAnimationComplete","onAnimationProgress","stopPropagation","ev","originalEvent","timeStamp","$manualTimeStamp","Date","now","elapsedTime","toFixed","ELAPSED_TIME_MAX_DECIMAL_PLACES","startTime","maxDelayTime","css3AnimationEvents","ANIMATIONEND_EVENT","TRANSITIONEND_EVENT","applyFallbackStyle","appliedStyles","propertyStyle","CSS_PREFIX","msie","fallbackProperty","delayStyle","prepareStaggerDelay","oldStyle","getAttribute","setAttribute","on","onEnd","off","animateClose","removeProperty","staggerDelay","val","animateBefore","animateAfter","afterAnimationComplete","animate","animationComplete","preReflowCancellation","suffixClasses","suffix","isArray","ontransitionend","onwebkittransitionend","onanimationend","onwebkitanimationend","oldClasses","clone","cloneNode","attr","removeAttr","html","append","remove","animationCompleted","beforeAddClass","cancellationMethod","beforeRemoveClass"] 8 | } 9 | -------------------------------------------------------------------------------- /www/js/angular/angular-touch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.4 3 | * (c) 2010-2014 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | /** 9 | * @ngdoc overview 10 | * @name ngTouch 11 | * @description 12 | * 13 | * # ngTouch 14 | * 15 | * The `ngTouch` module provides touch events and other helpers for touch-enabled devices. 16 | * The implementation is based on jQuery Mobile touch event handling 17 | * ([jquerymobile.com](http://jquerymobile.com/)). 18 | * 19 | * {@installModule touch} 20 | * 21 | * See {@link ngTouch.$swipe `$swipe`} for usage. 22 | * 23 | *
24 | * 25 | */ 26 | 27 | // define ngTouch module 28 | /* global -ngTouch */ 29 | var ngTouch = angular.module('ngTouch', []); 30 | 31 | /* global ngTouch: false */ 32 | 33 | /** 34 | * @ngdoc object 35 | * @name ngTouch.$swipe 36 | * 37 | * @description 38 | * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe 39 | * behavior, to make implementing swipe-related directives more convenient. 40 | * 41 | * Requires the {@link ngTouch `ngTouch`} module to be installed. 42 | * 43 | * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by 44 | * `ngCarousel` in a separate component. 45 | * 46 | * # Usage 47 | * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element 48 | * which is to be watched for swipes, and an object with four handler functions. See the 49 | * documentation for `bind` below. 50 | */ 51 | 52 | ngTouch.factory('$swipe', [function() { 53 | // The total distance in any direction before we make the call on swipe vs. scroll. 54 | var MOVE_BUFFER_RADIUS = 10; 55 | 56 | function getCoordinates(event) { 57 | var touches = event.touches && event.touches.length ? event.touches : [event]; 58 | var e = (event.changedTouches && event.changedTouches[0]) || 59 | (event.originalEvent && event.originalEvent.changedTouches && 60 | event.originalEvent.changedTouches[0]) || 61 | touches[0].originalEvent || touches[0]; 62 | 63 | return { 64 | x: e.clientX, 65 | y: e.clientY 66 | }; 67 | } 68 | 69 | return { 70 | /** 71 | * @ngdoc method 72 | * @name ngTouch.$swipe#bind 73 | * @methodOf ngTouch.$swipe 74 | * 75 | * @description 76 | * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an 77 | * object containing event handlers. 78 | * 79 | * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end` 80 | * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`. 81 | * 82 | * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is 83 | * watching for `touchmove` or `mousemove` events. These events are ignored until the total 84 | * distance moved in either dimension exceeds a small threshold. 85 | * 86 | * Once this threshold is exceeded, either the horizontal or vertical delta is greater. 87 | * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow. 88 | * - If the vertical distance is greater, this is a scroll, and we let the browser take over. 89 | * A `cancel` event is sent. 90 | * 91 | * `move` is called on `mousemove` and `touchmove` after the above logic has determined that 92 | * a swipe is in progress. 93 | * 94 | * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`. 95 | * 96 | * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling 97 | * as described above. 98 | * 99 | */ 100 | bind: function(element, eventHandlers) { 101 | // Absolute total movement, used to control swipe vs. scroll. 102 | var totalX, totalY; 103 | // Coordinates of the start position. 104 | var startCoords; 105 | // Last event's position. 106 | var lastPos; 107 | // Whether a swipe is active. 108 | var active = false; 109 | 110 | element.on('touchstart mousedown', function(event) { 111 | startCoords = getCoordinates(event); 112 | active = true; 113 | totalX = 0; 114 | totalY = 0; 115 | lastPos = startCoords; 116 | eventHandlers['start'] && eventHandlers['start'](startCoords, event); 117 | }); 118 | 119 | element.on('touchcancel', function(event) { 120 | active = false; 121 | eventHandlers['cancel'] && eventHandlers['cancel'](event); 122 | }); 123 | 124 | element.on('touchmove mousemove', function(event) { 125 | if (!active) return; 126 | 127 | // Android will send a touchcancel if it thinks we're starting to scroll. 128 | // So when the total distance (+ or - or both) exceeds 10px in either direction, 129 | // we either: 130 | // - On totalX > totalY, we send preventDefault() and treat this as a swipe. 131 | // - On totalY > totalX, we let the browser handle it as a scroll. 132 | 133 | if (!startCoords) return; 134 | var coords = getCoordinates(event); 135 | 136 | totalX += Math.abs(coords.x - lastPos.x); 137 | totalY += Math.abs(coords.y - lastPos.y); 138 | 139 | lastPos = coords; 140 | 141 | if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) { 142 | return; 143 | } 144 | 145 | // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll. 146 | if (totalY > totalX) { 147 | // Allow native scrolling to take over. 148 | active = false; 149 | eventHandlers['cancel'] && eventHandlers['cancel'](event); 150 | return; 151 | } else { 152 | // Prevent the browser from scrolling. 153 | event.preventDefault(); 154 | eventHandlers['move'] && eventHandlers['move'](coords, event); 155 | } 156 | }); 157 | 158 | element.on('touchend mouseup', function(event) { 159 | if (!active) return; 160 | active = false; 161 | eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event); 162 | }); 163 | } 164 | }; 165 | }]); 166 | 167 | /* global ngTouch: false */ 168 | 169 | /** 170 | * @ngdoc directive 171 | * @name ngTouch.directive:ngClick 172 | * 173 | * @description 174 | * A more powerful replacement for the default ngClick designed to be used on touchscreen 175 | * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending 176 | * the click event. This version handles them immediately, and then prevents the 177 | * following click event from propagating. 178 | * 179 | * Requires the {@link ngTouch `ngTouch`} module to be installed. 180 | * 181 | * This directive can fall back to using an ordinary click event, and so works on desktop 182 | * browsers as well as mobile. 183 | * 184 | * This directive also sets the CSS class `ng-click-active` while the element is being held 185 | * down (by a mouse click or touch) so you can restyle the depressed element if you wish. 186 | * 187 | * @element ANY 188 | * @param {expression} ngClick {@link guide/expression Expression} to evaluate 189 | * upon tap. (Event object is available as `$event`) 190 | * 191 | * @example 192 | 193 | 194 | 197 | count: {{ count }} 198 | 199 | 200 | */ 201 | 202 | ngTouch.config(['$provide', function($provide) { 203 | $provide.decorator('ngClickDirective', ['$delegate', function($delegate) { 204 | // drop the default ngClick directive 205 | $delegate.shift(); 206 | return $delegate; 207 | }]); 208 | }]); 209 | 210 | ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement', 211 | function($parse, $timeout, $rootElement) { 212 | var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag. 213 | var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers. 214 | var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click 215 | var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks. 216 | 217 | var ACTIVE_CLASS_NAME = 'ng-click-active'; 218 | var lastPreventedTime; 219 | var touchCoordinates; 220 | 221 | 222 | // TAP EVENTS AND GHOST CLICKS 223 | // 224 | // Why tap events? 225 | // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're 226 | // double-tapping, and then fire a click event. 227 | // 228 | // This delay sucks and makes mobile apps feel unresponsive. 229 | // So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when 230 | // the user has tapped on something. 231 | // 232 | // What happens when the browser then generates a click event? 233 | // The browser, of course, also detects the tap and fires a click after a delay. This results in 234 | // tapping/clicking twice. So we do "clickbusting" to prevent it. 235 | // 236 | // How does it work? 237 | // We attach global touchstart and click handlers, that run during the capture (early) phase. 238 | // So the sequence for a tap is: 239 | // - global touchstart: Sets an "allowable region" at the point touched. 240 | // - element's touchstart: Starts a touch 241 | // (- touchmove or touchcancel ends the touch, no click follows) 242 | // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold 243 | // too long) and fires the user's tap handler. The touchend also calls preventGhostClick(). 244 | // - preventGhostClick() removes the allowable region the global touchstart created. 245 | // - The browser generates a click event. 246 | // - The global click handler catches the click, and checks whether it was in an allowable region. 247 | // - If preventGhostClick was called, the region will have been removed, the click is busted. 248 | // - If the region is still there, the click proceeds normally. Therefore clicks on links and 249 | // other elements without ngTap on them work normally. 250 | // 251 | // This is an ugly, terrible hack! 252 | // Yeah, tell me about it. The alternatives are using the slow click events, or making our users 253 | // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular 254 | // encapsulates this ugly logic away from the user. 255 | // 256 | // Why not just put click handlers on the element? 257 | // We do that too, just to be sure. The problem is that the tap event might have caused the DOM 258 | // to change, so that the click fires in the same position but something else is there now. So 259 | // the handlers are global and care only about coordinates and not elements. 260 | 261 | // Checks if the coordinates are close enough to be within the region. 262 | function hit(x1, y1, x2, y2) { 263 | return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD; 264 | } 265 | 266 | // Checks a list of allowable regions against a click location. 267 | // Returns true if the click should be allowed. 268 | // Splices out the allowable region from the list after it has been used. 269 | function checkAllowableRegions(touchCoordinates, x, y) { 270 | for (var i = 0; i < touchCoordinates.length; i += 2) { 271 | if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) { 272 | touchCoordinates.splice(i, i + 2); 273 | return true; // allowable region 274 | } 275 | } 276 | return false; // No allowable region; bust it. 277 | } 278 | 279 | // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick 280 | // was called recently. 281 | function onClick(event) { 282 | if (Date.now() - lastPreventedTime > PREVENT_DURATION) { 283 | return; // Too old. 284 | } 285 | 286 | var touches = event.touches && event.touches.length ? event.touches : [event]; 287 | var x = touches[0].clientX; 288 | var y = touches[0].clientY; 289 | // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label 290 | // and on the input element). Depending on the exact browser, this second click we don't want 291 | // to bust has either (0,0) or negative coordinates. 292 | if (x < 1 && y < 1) { 293 | return; // offscreen 294 | } 295 | 296 | // Look for an allowable region containing this click. 297 | // If we find one, that means it was created by touchstart and not removed by 298 | // preventGhostClick, so we don't bust it. 299 | if (checkAllowableRegions(touchCoordinates, x, y)) { 300 | return; 301 | } 302 | 303 | // If we didn't find an allowable region, bust the click. 304 | event.stopPropagation(); 305 | event.preventDefault(); 306 | 307 | // Blur focused form elements 308 | event.target && event.target.blur(); 309 | } 310 | 311 | 312 | // Global touchstart handler that creates an allowable region for a click event. 313 | // This allowable region can be removed by preventGhostClick if we want to bust it. 314 | function onTouchStart(event) { 315 | var touches = event.touches && event.touches.length ? event.touches : [event]; 316 | var x = touches[0].clientX; 317 | var y = touches[0].clientY; 318 | touchCoordinates.push(x, y); 319 | 320 | $timeout(function() { 321 | // Remove the allowable region. 322 | for (var i = 0; i < touchCoordinates.length; i += 2) { 323 | if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) { 324 | touchCoordinates.splice(i, i + 2); 325 | return; 326 | } 327 | } 328 | }, PREVENT_DURATION, false); 329 | } 330 | 331 | // On the first call, attaches some event handlers. Then whenever it gets called, it creates a 332 | // zone around the touchstart where clicks will get busted. 333 | function preventGhostClick(x, y) { 334 | if (!touchCoordinates) { 335 | $rootElement[0].addEventListener('click', onClick, true); 336 | $rootElement[0].addEventListener('touchstart', onTouchStart, true); 337 | touchCoordinates = []; 338 | } 339 | 340 | lastPreventedTime = Date.now(); 341 | 342 | checkAllowableRegions(touchCoordinates, x, y); 343 | } 344 | 345 | // Actual linking function. 346 | return function(scope, element, attr) { 347 | var clickHandler = $parse(attr.ngClick), 348 | tapping = false, 349 | tapElement, // Used to blur the element after a tap. 350 | startTime, // Used to check if the tap was held too long. 351 | touchStartX, 352 | touchStartY; 353 | 354 | function resetState() { 355 | tapping = false; 356 | element.removeClass(ACTIVE_CLASS_NAME); 357 | } 358 | 359 | element.on('touchstart', function(event) { 360 | tapping = true; 361 | tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement. 362 | // Hack for Safari, which can target text nodes instead of containers. 363 | if(tapElement.nodeType == 3) { 364 | tapElement = tapElement.parentNode; 365 | } 366 | 367 | element.addClass(ACTIVE_CLASS_NAME); 368 | 369 | startTime = Date.now(); 370 | 371 | var touches = event.touches && event.touches.length ? event.touches : [event]; 372 | var e = touches[0].originalEvent || touches[0]; 373 | touchStartX = e.clientX; 374 | touchStartY = e.clientY; 375 | }); 376 | 377 | element.on('touchmove', function(event) { 378 | resetState(); 379 | }); 380 | 381 | element.on('touchcancel', function(event) { 382 | resetState(); 383 | }); 384 | 385 | element.on('touchend', function(event) { 386 | var diff = Date.now() - startTime; 387 | 388 | var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches : 389 | ((event.touches && event.touches.length) ? event.touches : [event]); 390 | var e = touches[0].originalEvent || touches[0]; 391 | var x = e.clientX; 392 | var y = e.clientY; 393 | var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) ); 394 | 395 | if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) { 396 | // Call preventGhostClick so the clickbuster will catch the corresponding click. 397 | preventGhostClick(x, y); 398 | 399 | // Blur the focused element (the button, probably) before firing the callback. 400 | // This doesn't work perfectly on Android Chrome, but seems to work elsewhere. 401 | // I couldn't get anything to work reliably on Android Chrome. 402 | if (tapElement) { 403 | tapElement.blur(); 404 | } 405 | 406 | if (!angular.isDefined(attr.disabled) || attr.disabled === false) { 407 | element.triggerHandler('click', [event]); 408 | } 409 | } 410 | 411 | resetState(); 412 | }); 413 | 414 | // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click 415 | // something else nearby. 416 | element.onclick = function(event) { }; 417 | 418 | // Actual click handler. 419 | // There are three different kinds of clicks, only two of which reach this point. 420 | // - On desktop browsers without touch events, their clicks will always come here. 421 | // - On mobile browsers, the simulated "fast" click will call this. 422 | // - But the browser's follow-up slow click will be "busted" before it reaches this handler. 423 | // Therefore it's safe to use this directive on both mobile and desktop. 424 | element.on('click', function(event, touchend) { 425 | scope.$apply(function() { 426 | clickHandler(scope, {$event: (touchend || event)}); 427 | }); 428 | }); 429 | 430 | element.on('mousedown', function(event) { 431 | element.addClass(ACTIVE_CLASS_NAME); 432 | }); 433 | 434 | element.on('mousemove mouseup', function(event) { 435 | element.removeClass(ACTIVE_CLASS_NAME); 436 | }); 437 | 438 | }; 439 | }]); 440 | 441 | /* global ngTouch: false */ 442 | 443 | /** 444 | * @ngdoc directive 445 | * @name ngTouch.directive:ngSwipeLeft 446 | * 447 | * @description 448 | * Specify custom behavior when an element is swiped to the left on a touchscreen device. 449 | * A leftward swipe is a quick, right-to-left slide of the finger. 450 | * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag 451 | * too. 452 | * 453 | * Requires the {@link ngTouch `ngTouch`} module to be installed. 454 | * 455 | * @element ANY 456 | * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate 457 | * upon left swipe. (Event object is available as `$event`) 458 | * 459 | * @example 460 | 461 | 462 |
463 | Some list content, like an email in the inbox 464 |
465 |
466 | 467 | 468 |
469 |
470 |
471 | */ 472 | 473 | /** 474 | * @ngdoc directive 475 | * @name ngTouch.directive:ngSwipeRight 476 | * 477 | * @description 478 | * Specify custom behavior when an element is swiped to the right on a touchscreen device. 479 | * A rightward swipe is a quick, left-to-right slide of the finger. 480 | * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag 481 | * too. 482 | * 483 | * Requires the {@link ngTouch `ngTouch`} module to be installed. 484 | * 485 | * @element ANY 486 | * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate 487 | * upon right swipe. (Event object is available as `$event`) 488 | * 489 | * @example 490 | 491 | 492 |
493 | Some list content, like an email in the inbox 494 |
495 |
496 | 497 | 498 |
499 |
500 |
501 | */ 502 | 503 | function makeSwipeDirective(directiveName, direction, eventName) { 504 | ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) { 505 | // The maximum vertical delta for a swipe should be less than 75px. 506 | var MAX_VERTICAL_DISTANCE = 75; 507 | // Vertical distance should not be more than a fraction of the horizontal distance. 508 | var MAX_VERTICAL_RATIO = 0.3; 509 | // At least a 30px lateral motion is necessary for a swipe. 510 | var MIN_HORIZONTAL_DISTANCE = 30; 511 | 512 | return function(scope, element, attr) { 513 | var swipeHandler = $parse(attr[directiveName]); 514 | 515 | var startCoords, valid; 516 | 517 | function validSwipe(coords) { 518 | // Check that it's within the coordinates. 519 | // Absolute vertical distance must be within tolerances. 520 | // Horizontal distance, we take the current X - the starting X. 521 | // This is negative for leftward swipes and positive for rightward swipes. 522 | // After multiplying by the direction (-1 for left, +1 for right), legal swipes 523 | // (ie. same direction as the directive wants) will have a positive delta and 524 | // illegal ones a negative delta. 525 | // Therefore this delta must be positive, and larger than the minimum. 526 | if (!startCoords) return false; 527 | var deltaY = Math.abs(coords.y - startCoords.y); 528 | var deltaX = (coords.x - startCoords.x) * direction; 529 | return valid && // Short circuit for already-invalidated swipes. 530 | deltaY < MAX_VERTICAL_DISTANCE && 531 | deltaX > 0 && 532 | deltaX > MIN_HORIZONTAL_DISTANCE && 533 | deltaY / deltaX < MAX_VERTICAL_RATIO; 534 | } 535 | 536 | $swipe.bind(element, { 537 | 'start': function(coords, event) { 538 | startCoords = coords; 539 | valid = true; 540 | }, 541 | 'cancel': function(event) { 542 | valid = false; 543 | }, 544 | 'end': function(coords, event) { 545 | if (validSwipe(coords)) { 546 | scope.$apply(function() { 547 | element.triggerHandler(eventName); 548 | swipeHandler(scope, {$event: event}); 549 | }); 550 | } 551 | } 552 | }); 553 | }; 554 | }]); 555 | } 556 | 557 | // Left is negative X-coordinate, right is positive. 558 | makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft'); 559 | makeSwipeDirective('ngSwipeRight', 1, 'swiperight'); 560 | 561 | 562 | 563 | })(window, window.angular); 564 | -------------------------------------------------------------------------------- /www/js/angular/angular-sanitize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.4 3 | * (c) 2010-2014 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | var $sanitizeMinErr = angular.$$minErr('$sanitize'); 9 | 10 | /** 11 | * @ngdoc overview 12 | * @name ngSanitize 13 | * @description 14 | * 15 | * # ngSanitize 16 | * 17 | * The `ngSanitize` module provides functionality to sanitize HTML. 18 | * 19 | * {@installModule sanitize} 20 | * 21 | *
22 | * 23 | * See {@link ngSanitize.$sanitize `$sanitize`} for usage. 24 | */ 25 | 26 | /* 27 | * HTML Parser By Misko Hevery (misko@hevery.com) 28 | * based on: HTML Parser By John Resig (ejohn.org) 29 | * Original code by Erik Arvidsson, Mozilla Public License 30 | * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js 31 | * 32 | * // Use like so: 33 | * htmlParser(htmlString, { 34 | * start: function(tag, attrs, unary) {}, 35 | * end: function(tag) {}, 36 | * chars: function(text) {}, 37 | * comment: function(text) {} 38 | * }); 39 | * 40 | */ 41 | 42 | 43 | /** 44 | * @ngdoc service 45 | * @name ngSanitize.$sanitize 46 | * @function 47 | * 48 | * @description 49 | * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are 50 | * then serialized back to properly escaped html string. This means that no unsafe input can make 51 | * it into the returned string, however, since our parser is more strict than a typical browser 52 | * parser, it's possible that some obscure input, which would be recognized as valid HTML by a 53 | * browser, won't make it through the sanitizer. 54 | * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and 55 | * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. 56 | * 57 | * @param {string} html Html input. 58 | * @returns {string} Sanitized html. 59 | * 60 | * @example 61 | 62 | 63 | 74 |
75 | Snippet: 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value 93 |
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
 94 | </div>
95 |
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
105 |
106 |
107 | 108 | it('should sanitize the html snippet by default', function() { 109 | expect(using('#bind-html-with-sanitize').element('div').html()). 110 | toBe('

an html\nclick here\nsnippet

'); 111 | }); 112 | 113 | it('should inline raw snippet if bound to a trusted value', function() { 114 | expect(using('#bind-html-with-trust').element("div").html()). 115 | toBe("

an html\n" + 116 | "click here\n" + 117 | "snippet

"); 118 | }); 119 | 120 | it('should escape snippet without any filter', function() { 121 | expect(using('#bind-default').element('div').html()). 122 | toBe("<p style=\"color:blue\">an html\n" + 123 | "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + 124 | "snippet</p>"); 125 | }); 126 | 127 | it('should update', function() { 128 | input('snippet').enter('new text'); 129 | expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new text'); 130 | expect(using('#bind-html-with-trust').element('div').html()).toBe( 131 | 'new text'); 132 | expect(using('#bind-default').element('div').html()).toBe( 133 | "new <b onclick=\"alert(1)\">text</b>"); 134 | }); 135 |
136 |
137 | */ 138 | function $SanitizeProvider() { 139 | this.$get = ['$$sanitizeUri', function($$sanitizeUri) { 140 | return function(html) { 141 | var buf = []; 142 | htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { 143 | return !/^unsafe/.test($$sanitizeUri(uri, isImage)); 144 | })); 145 | return buf.join(''); 146 | }; 147 | }]; 148 | } 149 | 150 | function sanitizeText(chars) { 151 | var buf = []; 152 | var writer = htmlSanitizeWriter(buf, angular.noop); 153 | writer.chars(chars); 154 | return buf.join(''); 155 | } 156 | 157 | 158 | // Regular Expressions for parsing tags and attributes 159 | var START_TAG_REGEXP = 160 | /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, 161 | END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, 162 | ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, 163 | BEGIN_TAG_REGEXP = /^/g, 166 | DOCTYPE_REGEXP = /]*?)>/i, 167 | CDATA_REGEXP = //g, 168 | // Match everything outside of normal chars and " (quote character) 169 | NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; 170 | 171 | 172 | // Good source of info about elements and attributes 173 | // http://dev.w3.org/html5/spec/Overview.html#semantics 174 | // http://simon.html5.org/html-elements 175 | 176 | // Safe Void Elements - HTML5 177 | // http://dev.w3.org/html5/spec/Overview.html#void-elements 178 | var voidElements = makeMap("area,br,col,hr,img,wbr"); 179 | 180 | // Elements that you can, intentionally, leave open (and which close themselves) 181 | // http://dev.w3.org/html5/spec/Overview.html#optional-tags 182 | var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), 183 | optionalEndTagInlineElements = makeMap("rp,rt"), 184 | optionalEndTagElements = angular.extend({}, 185 | optionalEndTagInlineElements, 186 | optionalEndTagBlockElements); 187 | 188 | // Safe Block Elements - HTML5 189 | var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + 190 | "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + 191 | "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); 192 | 193 | // Inline Elements - HTML5 194 | var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + 195 | "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + 196 | "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); 197 | 198 | 199 | // Special Elements (can contain anything) 200 | var specialElements = makeMap("script,style"); 201 | 202 | var validElements = angular.extend({}, 203 | voidElements, 204 | blockElements, 205 | inlineElements, 206 | optionalEndTagElements); 207 | 208 | //Attributes that have href and hence need to be sanitized 209 | var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); 210 | var validAttrs = angular.extend({}, uriAttrs, makeMap( 211 | 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ 212 | 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ 213 | 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ 214 | 'scope,scrolling,shape,span,start,summary,target,title,type,'+ 215 | 'valign,value,vspace,width')); 216 | 217 | function makeMap(str) { 218 | var obj = {}, items = str.split(','), i; 219 | for (i = 0; i < items.length; i++) obj[items[i]] = true; 220 | return obj; 221 | } 222 | 223 | 224 | /** 225 | * @example 226 | * htmlParser(htmlString, { 227 | * start: function(tag, attrs, unary) {}, 228 | * end: function(tag) {}, 229 | * chars: function(text) {}, 230 | * comment: function(text) {} 231 | * }); 232 | * 233 | * @param {string} html string 234 | * @param {object} handler 235 | */ 236 | function htmlParser( html, handler ) { 237 | var index, chars, match, stack = [], last = html; 238 | stack.last = function() { return stack[ stack.length - 1 ]; }; 239 | 240 | while ( html ) { 241 | chars = true; 242 | 243 | // Make sure we're not in a script or style element 244 | if ( !stack.last() || !specialElements[ stack.last() ] ) { 245 | 246 | // Comment 247 | if ( html.indexOf("", index) === index) { 252 | if (handler.comment) handler.comment( html.substring( 4, index ) ); 253 | html = html.substring( index + 3 ); 254 | chars = false; 255 | } 256 | // DOCTYPE 257 | } else if ( DOCTYPE_REGEXP.test(html) ) { 258 | match = html.match( DOCTYPE_REGEXP ); 259 | 260 | if ( match ) { 261 | html = html.replace( match[0] , ''); 262 | chars = false; 263 | } 264 | // end tag 265 | } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { 266 | match = html.match( END_TAG_REGEXP ); 267 | 268 | if ( match ) { 269 | html = html.substring( match[0].length ); 270 | match[0].replace( END_TAG_REGEXP, parseEndTag ); 271 | chars = false; 272 | } 273 | 274 | // start tag 275 | } else if ( BEGIN_TAG_REGEXP.test(html) ) { 276 | match = html.match( START_TAG_REGEXP ); 277 | 278 | if ( match ) { 279 | html = html.substring( match[0].length ); 280 | match[0].replace( START_TAG_REGEXP, parseStartTag ); 281 | chars = false; 282 | } 283 | } 284 | 285 | if ( chars ) { 286 | index = html.indexOf("<"); 287 | 288 | var text = index < 0 ? html : html.substring( 0, index ); 289 | html = index < 0 ? "" : html.substring( index ); 290 | 291 | if (handler.chars) handler.chars( decodeEntities(text) ); 292 | } 293 | 294 | } else { 295 | html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), 296 | function(all, text){ 297 | text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); 298 | 299 | if (handler.chars) handler.chars( decodeEntities(text) ); 300 | 301 | return ""; 302 | }); 303 | 304 | parseEndTag( "", stack.last() ); 305 | } 306 | 307 | if ( html == last ) { 308 | throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + 309 | "of html: {0}", html); 310 | } 311 | last = html; 312 | } 313 | 314 | // Clean up any remaining tags 315 | parseEndTag(); 316 | 317 | function parseStartTag( tag, tagName, rest, unary ) { 318 | tagName = angular.lowercase(tagName); 319 | if ( blockElements[ tagName ] ) { 320 | while ( stack.last() && inlineElements[ stack.last() ] ) { 321 | parseEndTag( "", stack.last() ); 322 | } 323 | } 324 | 325 | if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { 326 | parseEndTag( "", tagName ); 327 | } 328 | 329 | unary = voidElements[ tagName ] || !!unary; 330 | 331 | if ( !unary ) 332 | stack.push( tagName ); 333 | 334 | var attrs = {}; 335 | 336 | rest.replace(ATTR_REGEXP, 337 | function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { 338 | var value = doubleQuotedValue 339 | || singleQuotedValue 340 | || unquotedValue 341 | || ''; 342 | 343 | attrs[name] = decodeEntities(value); 344 | }); 345 | if (handler.start) handler.start( tagName, attrs, unary ); 346 | } 347 | 348 | function parseEndTag( tag, tagName ) { 349 | var pos = 0, i; 350 | tagName = angular.lowercase(tagName); 351 | if ( tagName ) 352 | // Find the closest opened tag of the same type 353 | for ( pos = stack.length - 1; pos >= 0; pos-- ) 354 | if ( stack[ pos ] == tagName ) 355 | break; 356 | 357 | if ( pos >= 0 ) { 358 | // Close all the open elements, up the stack 359 | for ( i = stack.length - 1; i >= pos; i-- ) 360 | if (handler.end) handler.end( stack[ i ] ); 361 | 362 | // Remove the open elements from the stack 363 | stack.length = pos; 364 | } 365 | } 366 | } 367 | 368 | var hiddenPre=document.createElement("pre"); 369 | var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; 370 | /** 371 | * decodes all entities into regular string 372 | * @param value 373 | * @returns {string} A string with decoded entities. 374 | */ 375 | function decodeEntities(value) { 376 | if (!value) { return ''; } 377 | 378 | // Note: IE8 does not preserve spaces at the start/end of innerHTML 379 | // so we must capture them and reattach them afterward 380 | var parts = spaceRe.exec(value); 381 | var spaceBefore = parts[1]; 382 | var spaceAfter = parts[3]; 383 | var content = parts[2]; 384 | if (content) { 385 | hiddenPre.innerHTML=content.replace(//g, '>'); 411 | } 412 | 413 | /** 414 | * create an HTML/XML writer which writes to buffer 415 | * @param {Array} buf use buf.jain('') to get out sanitized html string 416 | * @returns {object} in the form of { 417 | * start: function(tag, attrs, unary) {}, 418 | * end: function(tag) {}, 419 | * chars: function(text) {}, 420 | * comment: function(text) {} 421 | * } 422 | */ 423 | function htmlSanitizeWriter(buf, uriValidator){ 424 | var ignore = false; 425 | var out = angular.bind(buf, buf.push); 426 | return { 427 | start: function(tag, attrs, unary){ 428 | tag = angular.lowercase(tag); 429 | if (!ignore && specialElements[tag]) { 430 | ignore = tag; 431 | } 432 | if (!ignore && validElements[tag] === true) { 433 | out('<'); 434 | out(tag); 435 | angular.forEach(attrs, function(value, key){ 436 | var lkey=angular.lowercase(key); 437 | var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); 438 | if (validAttrs[lkey] === true && 439 | (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { 440 | out(' '); 441 | out(key); 442 | out('="'); 443 | out(encodeEntities(value)); 444 | out('"'); 445 | } 446 | }); 447 | out(unary ? '/>' : '>'); 448 | } 449 | }, 450 | end: function(tag){ 451 | tag = angular.lowercase(tag); 452 | if (!ignore && validElements[tag] === true) { 453 | out(''); 456 | } 457 | if (tag == ignore) { 458 | ignore = false; 459 | } 460 | }, 461 | chars: function(chars){ 462 | if (!ignore) { 463 | out(encodeEntities(chars)); 464 | } 465 | } 466 | }; 467 | } 468 | 469 | 470 | // define ngSanitize module and register $sanitize service 471 | angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); 472 | 473 | /* global sanitizeText: false */ 474 | 475 | /** 476 | * @ngdoc filter 477 | * @name ngSanitize.filter:linky 478 | * @function 479 | * 480 | * @description 481 | * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and 482 | * plain email address links. 483 | * 484 | * Requires the {@link ngSanitize `ngSanitize`} module to be installed. 485 | * 486 | * @param {string} text Input text. 487 | * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. 488 | * @returns {string} Html-linkified text. 489 | * 490 | * @usage 491 | 492 | * 493 | * @example 494 | 495 | 496 | 507 |
508 | Snippet: 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 520 | 523 | 524 | 525 | 526 | 529 | 532 | 533 | 534 | 535 | 536 | 537 | 538 |
FilterSourceRendered
linky filter 518 |
<div ng-bind-html="snippet | linky">
</div>
519 |
521 |
522 |
linky target 527 |
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
528 |
530 |
531 |
no filter
<div ng-bind="snippet">
</div>
539 | 540 | 541 | it('should linkify the snippet with urls', function() { 542 | expect(using('#linky-filter').binding('snippet | linky')). 543 | toBe('Pretty text with some links: ' + 544 | 'http://angularjs.org/, ' + 545 | 'us@somewhere.org, ' + 546 | 'another@somewhere.org, ' + 547 | 'and one more: ftp://127.0.0.1/.'); 548 | }); 549 | 550 | it ('should not linkify snippet without the linky filter', function() { 551 | expect(using('#escaped-html').binding('snippet')). 552 | toBe("Pretty text with some links:\n" + 553 | "http://angularjs.org/,\n" + 554 | "mailto:us@somewhere.org,\n" + 555 | "another@somewhere.org,\n" + 556 | "and one more: ftp://127.0.0.1/."); 557 | }); 558 | 559 | it('should update', function() { 560 | input('snippet').enter('new http://link.'); 561 | expect(using('#linky-filter').binding('snippet | linky')). 562 | toBe('new http://link.'); 563 | expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); 564 | }); 565 | 566 | it('should work with the target property', function() { 567 | expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")). 568 | toBe('http://angularjs.org/'); 569 | }); 570 | 571 | 572 | */ 573 | angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { 574 | var LINKY_URL_REGEXP = 575 | /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, 576 | MAILTO_REGEXP = /^mailto:/; 577 | 578 | return function(text, target) { 579 | if (!text) return text; 580 | var match; 581 | var raw = text; 582 | var html = []; 583 | var url; 584 | var i; 585 | while ((match = raw.match(LINKY_URL_REGEXP))) { 586 | // We can not end in these as they are sometimes found at the end of the sentence 587 | url = match[0]; 588 | // if we did not match ftp/http/mailto then assume mailto 589 | if (match[2] == match[3]) url = 'mailto:' + url; 590 | i = match.index; 591 | addText(raw.substr(0, i)); 592 | addLink(url, match[0].replace(MAILTO_REGEXP, '')); 593 | raw = raw.substring(i + match[0].length); 594 | } 595 | addText(raw); 596 | return $sanitize(html.join('')); 597 | 598 | function addText(text) { 599 | if (!text) { 600 | return; 601 | } 602 | html.push(sanitizeText(text)); 603 | } 604 | 605 | function addLink(url, text) { 606 | html.push(''); 615 | addText(text); 616 | html.push(''); 617 | } 618 | }; 619 | }]); 620 | 621 | 622 | })(window, window.angular); 623 | -------------------------------------------------------------------------------- /www/js/angular/angular-resource.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.4 3 | * (c) 2010-2014 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | var $resourceMinErr = angular.$$minErr('$resource'); 9 | 10 | // Helper functions and regex to lookup a dotted path on an object 11 | // stopping at undefined/null. The path must be composed of ASCII 12 | // identifiers (just like $parse) 13 | var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; 14 | 15 | function isValidDottedPath(path) { 16 | return (path != null && path !== '' && path !== 'hasOwnProperty' && 17 | MEMBER_NAME_REGEX.test('.' + path)); 18 | } 19 | 20 | function lookupDottedPath(obj, path) { 21 | if (!isValidDottedPath(path)) { 22 | throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); 23 | } 24 | var keys = path.split('.'); 25 | for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { 26 | var key = keys[i]; 27 | obj = (obj !== null) ? obj[key] : undefined; 28 | } 29 | return obj; 30 | } 31 | 32 | /** 33 | * @ngdoc overview 34 | * @name ngResource 35 | * @description 36 | * 37 | * # ngResource 38 | * 39 | * The `ngResource` module provides interaction support with RESTful services 40 | * via the $resource service. 41 | * 42 | * {@installModule resource} 43 | * 44 | *
45 | * 46 | * See {@link ngResource.$resource `$resource`} for usage. 47 | */ 48 | 49 | /** 50 | * @ngdoc object 51 | * @name ngResource.$resource 52 | * @requires $http 53 | * 54 | * @description 55 | * A factory which creates a resource object that lets you interact with 56 | * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. 57 | * 58 | * The returned resource object has action methods which provide high-level behaviors without 59 | * the need to interact with the low level {@link ng.$http $http} service. 60 | * 61 | * Requires the {@link ngResource `ngResource`} module to be installed. 62 | * 63 | * @param {string} url A parametrized URL template with parameters prefixed by `:` as in 64 | * `/user/:username`. If you are using a URL with a port number (e.g. 65 | * `http://example.com:8080/api`), it will be respected. 66 | * 67 | * If you are using a url with a suffix, just add the suffix, like this: 68 | * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` 69 | * or even `$resource('http://example.com/resource/:resource_id.:format')` 70 | * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be 71 | * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you 72 | * can escape it with `/\.`. 73 | * 74 | * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in 75 | * `actions` methods. If any of the parameter value is a function, it will be executed every time 76 | * when a param value needs to be obtained for a request (unless the param was overridden). 77 | * 78 | * Each key value in the parameter object is first bound to url template if present and then any 79 | * excess keys are appended to the url search query after the `?`. 80 | * 81 | * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in 82 | * URL `/path/greet?salutation=Hello`. 83 | * 84 | * If the parameter value is prefixed with `@` then the value of that parameter is extracted from 85 | * the data object (useful for non-GET operations). 86 | * 87 | * @param {Object.=} actions Hash with declaration of custom action that should extend the 88 | * default set of resource actions. The declaration should be created in the format of {@link 89 | * ng.$http#usage_parameters $http.config}: 90 | * 91 | * {action1: {method:?, params:?, isArray:?, headers:?, ...}, 92 | * action2: {method:?, params:?, isArray:?, headers:?, ...}, 93 | * ...} 94 | * 95 | * Where: 96 | * 97 | * - **`action`** – {string} – The name of action. This name becomes the name of the method on 98 | * your resource object. 99 | * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, 100 | * `DELETE`, and `JSONP`. 101 | * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of 102 | * the parameter value is a function, it will be executed every time when a param value needs to 103 | * be obtained for a request (unless the param was overridden). 104 | * - **`url`** – {string} – action specific `url` override. The url templating is supported just 105 | * like for the resource-level urls. 106 | * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, 107 | * see `returns` section. 108 | * - **`transformRequest`** – 109 | * `{function(data, headersGetter)|Array.}` – 110 | * transform function or an array of such functions. The transform function takes the http 111 | * request body and headers and returns its transformed (typically serialized) version. 112 | * - **`transformResponse`** – 113 | * `{function(data, headersGetter)|Array.}` – 114 | * transform function or an array of such functions. The transform function takes the http 115 | * response body and headers and returns its transformed (typically deserialized) version. 116 | * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the 117 | * GET request, otherwise if a cache instance built with 118 | * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for 119 | * caching. 120 | * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that 121 | * should abort the request when resolved. 122 | * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the 123 | * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 124 | * requests with credentials} for more information. 125 | * - **`responseType`** - `{string}` - see {@link 126 | * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. 127 | * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - 128 | * `response` and `responseError`. Both `response` and `responseError` interceptors get called 129 | * with `http response` object. See {@link ng.$http $http interceptors}. 130 | * 131 | * @returns {Object} A resource "class" object with methods for the default set of resource actions 132 | * optionally extended with custom `actions`. The default set contains these actions: 133 | * 134 | * { 'get': {method:'GET'}, 135 | * 'save': {method:'POST'}, 136 | * 'query': {method:'GET', isArray:true}, 137 | * 'remove': {method:'DELETE'}, 138 | * 'delete': {method:'DELETE'} }; 139 | * 140 | * Calling these methods invoke an {@link ng.$http} with the specified http method, 141 | * destination and parameters. When the data is returned from the server then the object is an 142 | * instance of the resource class. The actions `save`, `remove` and `delete` are available on it 143 | * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, 144 | * read, update, delete) on server-side data like this: 145 | *
146 |         var User = $resource('/user/:userId', {userId:'@id'});
147 |         var user = User.get({userId:123}, function() {
148 |           user.abc = true;
149 |           user.$save();
150 |         });
151 |      
152 | * 153 | * It is important to realize that invoking a $resource object method immediately returns an 154 | * empty reference (object or array depending on `isArray`). Once the data is returned from the 155 | * server the existing reference is populated with the actual data. This is a useful trick since 156 | * usually the resource is assigned to a model which is then rendered by the view. Having an empty 157 | * object results in no rendering, once the data arrives from the server then the object is 158 | * populated with the data and the view automatically re-renders itself showing the new data. This 159 | * means that in most cases one never has to write a callback function for the action methods. 160 | * 161 | * The action methods on the class object or instance object can be invoked with the following 162 | * parameters: 163 | * 164 | * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` 165 | * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` 166 | * - non-GET instance actions: `instance.$action([parameters], [success], [error])` 167 | * 168 | * Success callback is called with (value, responseHeaders) arguments. Error callback is called 169 | * with (httpResponse) argument. 170 | * 171 | * Class actions return empty instance (with additional properties below). 172 | * Instance actions return promise of the action. 173 | * 174 | * The Resource instances and collection have these additional properties: 175 | * 176 | * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this 177 | * instance or collection. 178 | * 179 | * On success, the promise is resolved with the same resource instance or collection object, 180 | * updated with data from server. This makes it easy to use in 181 | * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view 182 | * rendering until the resource(s) are loaded. 183 | * 184 | * On failure, the promise is resolved with the {@link ng.$http http response} object, without 185 | * the `resource` property. 186 | * 187 | * - `$resolved`: `true` after first server interaction is completed (either with success or 188 | * rejection), `false` before that. Knowing if the Resource has been resolved is useful in 189 | * data-binding. 190 | * 191 | * @example 192 | * 193 | * # Credit card resource 194 | * 195 | *
196 |      // Define CreditCard class
197 |      var CreditCard = $resource('/user/:userId/card/:cardId',
198 |       {userId:123, cardId:'@id'}, {
199 |        charge: {method:'POST', params:{charge:true}}
200 |       });
201 | 
202 |      // We can retrieve a collection from the server
203 |      var cards = CreditCard.query(function() {
204 |        // GET: /user/123/card
205 |        // server returns: [ {id:456, number:'1234', name:'Smith'} ];
206 | 
207 |        var card = cards[0];
208 |        // each item is an instance of CreditCard
209 |        expect(card instanceof CreditCard).toEqual(true);
210 |        card.name = "J. Smith";
211 |        // non GET methods are mapped onto the instances
212 |        card.$save();
213 |        // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
214 |        // server returns: {id:456, number:'1234', name: 'J. Smith'};
215 | 
216 |        // our custom method is mapped as well.
217 |        card.$charge({amount:9.99});
218 |        // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
219 |      });
220 | 
221 |      // we can create an instance as well
222 |      var newCard = new CreditCard({number:'0123'});
223 |      newCard.name = "Mike Smith";
224 |      newCard.$save();
225 |      // POST: /user/123/card {number:'0123', name:'Mike Smith'}
226 |      // server returns: {id:789, number:'01234', name: 'Mike Smith'};
227 |      expect(newCard.id).toEqual(789);
228 |  * 
229 | * 230 | * The object returned from this function execution is a resource "class" which has "static" method 231 | * for each action in the definition. 232 | * 233 | * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and 234 | * `headers`. 235 | * When the data is returned from the server then the object is an instance of the resource type and 236 | * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD 237 | * operations (create, read, update, delete) on server-side data. 238 | 239 |
240 |      var User = $resource('/user/:userId', {userId:'@id'});
241 |      var user = User.get({userId:123}, function() {
242 |        user.abc = true;
243 |        user.$save();
244 |      });
245 |    
246 | * 247 | * It's worth noting that the success callback for `get`, `query` and other methods gets passed 248 | * in the response that came from the server as well as $http header getter function, so one 249 | * could rewrite the above example and get access to http headers as: 250 | * 251 |
252 |      var User = $resource('/user/:userId', {userId:'@id'});
253 |      User.get({userId:123}, function(u, getResponseHeaders){
254 |        u.abc = true;
255 |        u.$save(function(u, putResponseHeaders) {
256 |          //u => saved user object
257 |          //putResponseHeaders => $http header getter
258 |        });
259 |      });
260 |    
261 | */ 262 | angular.module('ngResource', ['ng']). 263 | factory('$resource', ['$http', '$q', function($http, $q) { 264 | 265 | var DEFAULT_ACTIONS = { 266 | 'get': {method:'GET'}, 267 | 'save': {method:'POST'}, 268 | 'query': {method:'GET', isArray:true}, 269 | 'remove': {method:'DELETE'}, 270 | 'delete': {method:'DELETE'} 271 | }; 272 | var noop = angular.noop, 273 | forEach = angular.forEach, 274 | extend = angular.extend, 275 | copy = angular.copy, 276 | isFunction = angular.isFunction; 277 | 278 | /** 279 | * We need our custom method because encodeURIComponent is too aggressive and doesn't follow 280 | * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path 281 | * segments: 282 | * segment = *pchar 283 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 284 | * pct-encoded = "%" HEXDIG HEXDIG 285 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 286 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 287 | * / "*" / "+" / "," / ";" / "=" 288 | */ 289 | function encodeUriSegment(val) { 290 | return encodeUriQuery(val, true). 291 | replace(/%26/gi, '&'). 292 | replace(/%3D/gi, '='). 293 | replace(/%2B/gi, '+'); 294 | } 295 | 296 | 297 | /** 298 | * This method is intended for encoding *key* or *value* parts of query component. We need a 299 | * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't 300 | * have to be encoded per http://tools.ietf.org/html/rfc3986: 301 | * query = *( pchar / "/" / "?" ) 302 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 303 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 304 | * pct-encoded = "%" HEXDIG HEXDIG 305 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 306 | * / "*" / "+" / "," / ";" / "=" 307 | */ 308 | function encodeUriQuery(val, pctEncodeSpaces) { 309 | return encodeURIComponent(val). 310 | replace(/%40/gi, '@'). 311 | replace(/%3A/gi, ':'). 312 | replace(/%24/g, '$'). 313 | replace(/%2C/gi, ','). 314 | replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); 315 | } 316 | 317 | function Route(template, defaults) { 318 | this.template = template; 319 | this.defaults = defaults || {}; 320 | this.urlParams = {}; 321 | } 322 | 323 | Route.prototype = { 324 | setUrlParams: function(config, params, actionUrl) { 325 | var self = this, 326 | url = actionUrl || self.template, 327 | val, 328 | encodedVal; 329 | 330 | var urlParams = self.urlParams = {}; 331 | forEach(url.split(/\W/), function(param){ 332 | if (param === 'hasOwnProperty') { 333 | throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); 334 | } 335 | if (!(new RegExp("^\\d+$").test(param)) && param && 336 | (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { 337 | urlParams[param] = true; 338 | } 339 | }); 340 | url = url.replace(/\\:/g, ':'); 341 | 342 | params = params || {}; 343 | forEach(self.urlParams, function(_, urlParam){ 344 | val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; 345 | if (angular.isDefined(val) && val !== null) { 346 | encodedVal = encodeUriSegment(val); 347 | url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1"); 348 | } else { 349 | url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, 350 | leadingSlashes, tail) { 351 | if (tail.charAt(0) == '/') { 352 | return tail; 353 | } else { 354 | return leadingSlashes + tail; 355 | } 356 | }); 357 | } 358 | }); 359 | 360 | // strip trailing slashes and set the url 361 | url = url.replace(/\/+$/, ''); 362 | // then replace collapse `/.` if found in the last URL path segment before the query 363 | // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` 364 | url = url.replace(/\/\.(?=\w+($|\?))/, '.'); 365 | // replace escaped `/\.` with `/.` 366 | config.url = url.replace(/\/\\\./, '/.'); 367 | 368 | 369 | // set params - delegate param encoding to $http 370 | forEach(params, function(value, key){ 371 | if (!self.urlParams[key]) { 372 | config.params = config.params || {}; 373 | config.params[key] = value; 374 | } 375 | }); 376 | } 377 | }; 378 | 379 | 380 | function resourceFactory(url, paramDefaults, actions) { 381 | var route = new Route(url); 382 | 383 | actions = extend({}, DEFAULT_ACTIONS, actions); 384 | 385 | function extractParams(data, actionParams){ 386 | var ids = {}; 387 | actionParams = extend({}, paramDefaults, actionParams); 388 | forEach(actionParams, function(value, key){ 389 | if (isFunction(value)) { value = value(); } 390 | ids[key] = value && value.charAt && value.charAt(0) == '@' ? 391 | lookupDottedPath(data, value.substr(1)) : value; 392 | }); 393 | return ids; 394 | } 395 | 396 | function defaultResponseInterceptor(response) { 397 | return response.resource; 398 | } 399 | 400 | function Resource(value){ 401 | copy(value || {}, this); 402 | } 403 | 404 | forEach(actions, function(action, name) { 405 | var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); 406 | 407 | Resource[name] = function(a1, a2, a3, a4) { 408 | var params = {}, data, success, error; 409 | 410 | /* jshint -W086 */ /* (purposefully fall through case statements) */ 411 | switch(arguments.length) { 412 | case 4: 413 | error = a4; 414 | success = a3; 415 | //fallthrough 416 | case 3: 417 | case 2: 418 | if (isFunction(a2)) { 419 | if (isFunction(a1)) { 420 | success = a1; 421 | error = a2; 422 | break; 423 | } 424 | 425 | success = a2; 426 | error = a3; 427 | //fallthrough 428 | } else { 429 | params = a1; 430 | data = a2; 431 | success = a3; 432 | break; 433 | } 434 | case 1: 435 | if (isFunction(a1)) success = a1; 436 | else if (hasBody) data = a1; 437 | else params = a1; 438 | break; 439 | case 0: break; 440 | default: 441 | throw $resourceMinErr('badargs', 442 | "Expected up to 4 arguments [params, data, success, error], got {0} arguments", 443 | arguments.length); 444 | } 445 | /* jshint +W086 */ /* (purposefully fall through case statements) */ 446 | 447 | var isInstanceCall = this instanceof Resource; 448 | var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); 449 | var httpConfig = {}; 450 | var responseInterceptor = action.interceptor && action.interceptor.response || 451 | defaultResponseInterceptor; 452 | var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || 453 | undefined; 454 | 455 | forEach(action, function(value, key) { 456 | if (key != 'params' && key != 'isArray' && key != 'interceptor') { 457 | httpConfig[key] = copy(value); 458 | } 459 | }); 460 | 461 | if (hasBody) httpConfig.data = data; 462 | route.setUrlParams(httpConfig, 463 | extend({}, extractParams(data, action.params || {}), params), 464 | action.url); 465 | 466 | var promise = $http(httpConfig).then(function(response) { 467 | var data = response.data, 468 | promise = value.$promise; 469 | 470 | if (data) { 471 | // Need to convert action.isArray to boolean in case it is undefined 472 | // jshint -W018 473 | if ( angular.isArray(data) !== (!!action.isArray) ) { 474 | throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + 475 | 'response to contain an {0} but got an {1}', 476 | action.isArray?'array':'object', angular.isArray(data)?'array':'object'); 477 | } 478 | // jshint +W018 479 | if (action.isArray) { 480 | value.length = 0; 481 | forEach(data, function(item) { 482 | value.push(new Resource(item)); 483 | }); 484 | } else { 485 | copy(data, value); 486 | value.$promise = promise; 487 | } 488 | } 489 | 490 | value.$resolved = true; 491 | 492 | response.resource = value; 493 | 494 | return response; 495 | }, function(response) { 496 | value.$resolved = true; 497 | 498 | (error||noop)(response); 499 | 500 | return $q.reject(response); 501 | }); 502 | 503 | promise = promise.then( 504 | function(response) { 505 | var value = responseInterceptor(response); 506 | (success||noop)(value, response.headers); 507 | return value; 508 | }, 509 | responseErrorInterceptor); 510 | 511 | if (!isInstanceCall) { 512 | // we are creating instance / collection 513 | // - set the initial promise 514 | // - return the instance / collection 515 | value.$promise = promise; 516 | value.$resolved = false; 517 | 518 | return value; 519 | } 520 | 521 | // instance call 522 | return promise; 523 | }; 524 | 525 | 526 | Resource.prototype['$' + name] = function(params, success, error) { 527 | if (isFunction(params)) { 528 | error = success; success = params; params = {}; 529 | } 530 | var result = Resource[name].call(this, params, this, success, error); 531 | return result.$promise || result; 532 | }; 533 | }); 534 | 535 | Resource.bind = function(additionalParamDefaults){ 536 | return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); 537 | }; 538 | 539 | return Resource; 540 | } 541 | 542 | return resourceFactory; 543 | }]); 544 | 545 | 546 | })(window, window.angular); 547 | --------------------------------------------------------------------------------