├── .cordova └── config.json ├── README.md ├── config.xml ├── hooks └── README.md ├── plugins └── com.ionic.keyboard │ ├── .fetch.json │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── plugin.xml │ ├── src │ ├── android │ │ └── IonicKeyboard.java │ └── ios │ │ ├── IonicKeyboard.h │ │ ├── IonicKeyboard.m │ │ ├── UIWebViewExtension.h │ │ └── UIWebViewExtension.m │ └── www │ └── keyboard.js └── www ├── css └── index.css ├── icon.png ├── img ├── ionic.png └── logo.png ├── index.html ├── js ├── app.js ├── bootstrap.js ├── config.js ├── controllers │ ├── LoginCtrl.js │ ├── PetDetailCtrl.js │ ├── PetIndexCtrl.js │ └── controllers.js ├── directives │ ├── VersionDirective.js │ └── directives.js ├── filters │ ├── InterpolateFilter.js │ └── filters.js ├── main.js ├── routes.js └── services │ ├── PetService.js │ └── services.js ├── lib ├── css │ ├── ionic.css │ └── ionic.min.css ├── fonts │ ├── ionicons.eot │ ├── ionicons.svg │ ├── ionicons.ttf │ └── ionicons.woff └── js │ ├── angular-ui │ ├── angular-ui-router.js │ └── angular-ui-router.min.js │ ├── angular │ ├── angular-animate.js │ ├── angular-animate.min.js │ ├── angular-resource.js │ ├── angular-resource.min.js │ ├── angular-sanitize.js │ ├── angular-sanitize.min.js │ ├── angular.js │ └── angular.min.js │ ├── ionic-angular.js │ ├── ionic-angular.min.js │ ├── ionic.bundle.js │ ├── ionic.bundle.min.js │ ├── ionic.js │ ├── ionic.min.js │ ├── require.js │ └── text.js ├── res ├── .pgbomit ├── icon │ ├── 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 │ ├── bada │ │ └── icon-128.png │ ├── blackberry │ │ └── icon-80.png │ ├── ios │ │ ├── icon-57-2x.png │ │ ├── icon-57.png │ │ ├── icon-72-2x.png │ │ └── icon-72.png │ ├── tizen │ │ └── icon-128.png │ ├── webos │ │ └── icon-64.png │ └── windows-phone │ │ ├── icon-173-tile.png │ │ ├── icon-48.png │ │ └── icon-62-tile.png └── screen │ ├── android │ ├── screen-hdpi-landscape.png │ ├── screen-hdpi-portrait.png │ ├── screen-ldpi-landscape.png │ ├── screen-ldpi-portrait.png │ ├── screen-mdpi-landscape.png │ ├── screen-mdpi-portrait.png │ ├── screen-xhdpi-landscape.png │ └── screen-xhdpi-portrait.png │ ├── bada-wac │ ├── screen-type3.png │ ├── screen-type4.png │ └── screen-type5.png │ ├── bada │ └── screen-portrait.png │ ├── blackberry │ └── screen-225.png │ ├── ios │ ├── screen-ipad-landscape-2x.png │ ├── screen-ipad-landscape.png │ ├── screen-ipad-portrait-2x.png │ ├── screen-ipad-portrait.png │ ├── screen-iphone-landscape-2x.png │ ├── screen-iphone-landscape.png │ ├── screen-iphone-portrait-2x.png │ ├── screen-iphone-portrait-568h-2x.png │ └── screen-iphone-portrait.png │ ├── tizen │ └── README.md │ ├── webos │ └── screen-64.png │ └── windows-phone │ └── screen-portrait.jpg ├── spec.html ├── spec ├── helper.js ├── index.js └── lib │ └── jasmine-1.2.0 │ ├── MIT.LICENSE │ ├── jasmine-html.js │ ├── jasmine.css │ └── jasmine.js └── templates ├── about.html ├── adopt.html ├── login.html ├── pet-detail.html ├── pet-index.html └── tabs.html /.cordova/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "www": { 4 | "id": "com.phonegap.helloworld", 5 | "version": "3.6.0", 6 | "uri": "https://github.com/phonegap/phonegap-app-hello-world/archive/3.6.0.tar.gz" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-ionic-requirejs-phonegap-seed 2 | ===================================== 3 | 4 | Sample PhoneGap / Cordova application built with Angular and Ionic Framework, uses RequireJS for loading scripts. Example controllers, filters, services, directives and config. 5 | 6 | Forked from ionic seed (https://github.com/driftyco/ionic-angular-cordova-seed) and other seed projects. 7 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ionic (RequireJS) Seed App 4 | 5 | Sample PhoneGap / Cordova application built with Angular and Ionic Framework, uses RequireJS for loading scripts. Example controllers, filters, services, directives and config. 6 | 7 | 8 | Domonkos Pal 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 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | This directory may contain scripts used to customize cordova commands. This 24 | directory used to exist at `.cordova/hooks`, but has now been moved to the 25 | project root. Any scripts you add to these directories will be executed before 26 | and after the commands corresponding to the directory name. Useful for 27 | integrating your own build systems or integrating with version control systems. 28 | 29 | __Remember__: Make your scripts executable. 30 | 31 | ## Hook Directories 32 | The following subdirectories will be used for hooks: 33 | 34 | after_build/ 35 | after_compile/ 36 | after_docs/ 37 | after_emulate/ 38 | after_platform_add/ 39 | after_platform_rm/ 40 | after_platform_ls/ 41 | after_plugin_add/ 42 | after_plugin_ls/ 43 | after_plugin_rm/ 44 | after_plugin_search/ 45 | after_prepare/ 46 | after_run/ 47 | after_serve/ 48 | before_build/ 49 | before_compile/ 50 | before_docs/ 51 | before_emulate/ 52 | before_platform_add/ 53 | before_platform_rm/ 54 | before_platform_ls/ 55 | before_plugin_add/ 56 | before_plugin_ls/ 57 | before_plugin_rm/ 58 | before_plugin_search/ 59 | before_prepare/ 60 | before_run/ 61 | before_serve/ 62 | pre_package/ <-- Windows 8 and Windows Phone only. 63 | 64 | ## Script Interface 65 | 66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 67 | 68 | * CORDOVA_VERSION - The version of the Cordova-CLI. 69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 71 | * CORDOVA_HOOK - Path to the hook that is being executed. 72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 73 | 74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 75 | 76 | 77 | ## Writing hooks 78 | 79 | We highly recommend writting your hooks using Node.js so that they are 80 | cross-platform. Some good examples are shown here: 81 | 82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 83 | 84 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/.fetch.json: -------------------------------------------------------------------------------- 1 | {"source":{"type":"git","url":"https://github.com/driftyco/ionic-plugins-keyboard.git","subdir":"."}} -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2014 Drifty Co. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/README.md: -------------------------------------------------------------------------------- 1 | Keyboard 2 | ====== 3 | 4 | The `Keyboard` object on the `cordova.plugins` object provides functions to make interacting with the keyboard easier, and fires events to indicate that the keyboard will hide/show. 5 | 6 | cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard.git 7 | 8 | Methods 9 | ------- 10 | 11 | - cordova.plugins.Keyboard.hideKeyboardAccessoryBar 12 | - cordova.plugins.Keyboard.close 13 | - cordova.plugins.Keyboard.disableScroll 14 | 15 | Properties 16 | -------- 17 | 18 | - cordova.plugins.Keyboard.isVisible 19 | 20 | Events 21 | -------- 22 | 23 | - native.keyboardshow 24 | - native.keyboardhide 25 | 26 | Permissions 27 | ----------- 28 | 29 | #### config.xml 30 | 31 | 32 | 33 | 34 | 35 | 36 | Keyboard.hideKeyboardAccessoryBar 37 | ================= 38 | 39 | Hide the keyboard accessory bar with the next, previous and done buttons. 40 | 41 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); 42 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false); 43 | 44 | Supported Platforms 45 | ------------------- 46 | 47 | - iOS 48 | 49 | 50 | Keyboard.close 51 | ================= 52 | 53 | Close the keyboard if it is open. 54 | 55 | cordova.plugins.Keyboard.close(); 56 | 57 | Supported Platforms 58 | ------------------- 59 | 60 | - iOS 61 | 62 | 63 | Keyboard.disableScroll 64 | ================= 65 | 66 | Disable native scrolling, useful if you are using JavaScript to scroll 67 | 68 | cordova.plugins.Keyboard.disableScroll(true); 69 | cordova.plugins.Keyboard.disableScroll(false); 70 | 71 | Supported Platforms 72 | ------------------- 73 | 74 | - iOS 75 | 76 | 77 | native.keyboardshow 78 | ================= 79 | 80 | This event fires when the keyboard will be shown 81 | 82 | window.addEventListener('native.keyboardshow', keyboardShowHandler); 83 | 84 | function keyboardShowHandler(e){ 85 | alert('Keyboard height is: ' + e.keyboardHeight); 86 | } 87 | 88 | Properties 89 | ----------- 90 | 91 | keyboardHeight: the height of the keyboard in pixels 92 | 93 | 94 | Supported Platforms 95 | ------------------- 96 | 97 | - iOS, Android 98 | 99 | 100 | native.keyboardhide 101 | ================= 102 | 103 | This event fires when the keyboard will hide 104 | 105 | window.addEventListener('native.keyboardhide', keyboardHideHandler); 106 | 107 | function keyboardHideHandler(e){ 108 | alert('Goodnight, sweet prince'); 109 | } 110 | 111 | Properties 112 | ----------- 113 | 114 | None 115 | 116 | Supported Platforms 117 | ------------------- 118 | 119 | - iOS, Android 120 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "name": "com.ionic.keyboard" 4 | "cordova_name": "Keyboard", 5 | "description": "Ionic Keyboard Plugin", 6 | "license": "MIT", 7 | "keywords": [ 8 | "ionic", 9 | "keyboard" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | Keyboard 7 | Ionic Keyboard Plugin 8 | Apache 2.0 9 | Ionic,keyboard 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 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/src/android/IonicKeyboard.java: -------------------------------------------------------------------------------- 1 | package com.ionic.keyboard; 2 | 3 | import org.apache.cordova.CordovaInterface; 4 | import org.apache.cordova.CordovaPlugin; 5 | import org.apache.cordova.CordovaWebView; 6 | 7 | import android.graphics.Rect; 8 | import android.util.DisplayMetrics; 9 | import android.view.View; 10 | import android.view.ViewTreeObserver.OnGlobalLayoutListener; 11 | 12 | public class IonicKeyboard extends CordovaPlugin{ 13 | 14 | public void initialize(CordovaInterface cordova, CordovaWebView webView) { 15 | super.initialize(cordova, webView); 16 | 17 | //calculate density-independent pixels (dp) 18 | //http://developer.android.com/guide/practices/screens_support.html 19 | DisplayMetrics dm = new DisplayMetrics(); 20 | cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); 21 | final float density = dm.density; 22 | 23 | final CordovaWebView appView = webView; 24 | 25 | //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing 26 | final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView(); 27 | OnGlobalLayoutListener list = new OnGlobalLayoutListener() { 28 | int previousHeightDiff = 0; 29 | @Override 30 | public void onGlobalLayout() { 31 | Rect r = new Rect(); 32 | //r will be populated with the coordinates of your view that area still visible. 33 | rootView.getWindowVisibleDisplayFrame(r); 34 | 35 | int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top); 36 | int pixelHeightDiff = (int)(heightDiff / density); 37 | if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard... 38 | appView.sendJavascript("cordova.plugins.Keyboard.isVisible = true"); 39 | appView.sendJavascript("cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});"); 40 | 41 | //deprecated 42 | appView.sendJavascript("cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});"); 43 | } 44 | else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){ 45 | appView.sendJavascript("cordova.plugins.Keyboard.isVisible = false"); 46 | appView.sendJavascript("cordova.fireWindowEvent('native.keyboardhide')"); 47 | 48 | //deprecated 49 | appView.sendJavascript("cordova.fireWindowEvent('native.hidekeyboard')"); 50 | } 51 | previousHeightDiff = pixelHeightDiff; 52 | } 53 | }; 54 | 55 | rootView.getViewTreeObserver().addOnGlobalLayoutListener(list); 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/src/ios/IonicKeyboard.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface IonicKeyboard : CDVPlugin { 4 | @protected 5 | id _keyboardShowObserver, _keyboardHideObserver; 6 | } 7 | 8 | @property (readwrite, assign) BOOL hideKeyboardAccessoryBar; 9 | @property (readwrite, assign) BOOL disableScroll; 10 | //@property (readwrite, assign) BOOL styleDark; 11 | 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/src/ios/IonicKeyboard.m: -------------------------------------------------------------------------------- 1 | #import "IonicKeyboard.h" 2 | #import "UIWebViewExtension.h" 3 | #import 4 | 5 | @implementation IonicKeyboard 6 | 7 | @synthesize hideKeyboardAccessoryBar = _hideKeyboardAccessoryBar; 8 | @synthesize disableScroll = _disableScroll; 9 | //@synthesize styleDark = _styleDark; 10 | 11 | - (void)pluginInitialize { 12 | 13 | NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; 14 | __weak IonicKeyboard* weakSelf = self; 15 | 16 | //set defaults 17 | self.hideKeyboardAccessoryBar = NO; 18 | self.disableScroll = NO; 19 | //self.styleDark = NO; 20 | 21 | _keyboardShowObserver = [nc addObserverForName:UIKeyboardWillShowNotification 22 | object:nil 23 | queue:[NSOperationQueue mainQueue] 24 | usingBlock:^(NSNotification* notification) { 25 | 26 | CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 27 | keyboardFrame = [self.viewController.view convertRect:keyboardFrame fromView:nil]; 28 | 29 | [weakSelf.commandDelegate evalJs:[NSString stringWithFormat:@"cordova.plugins.Keyboard.isVisible = true; cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight': %@ }); ", [@(keyboardFrame.size.height) stringValue]]]; 30 | 31 | //deprecated 32 | [weakSelf.commandDelegate evalJs:[NSString stringWithFormat:@"cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight': %@ }); ", [@(keyboardFrame.size.height) stringValue]]]; 33 | }]; 34 | 35 | _keyboardHideObserver = [nc addObserverForName:UIKeyboardWillHideNotification 36 | object:nil 37 | queue:[NSOperationQueue mainQueue] 38 | usingBlock:^(NSNotification* notification) { 39 | [weakSelf.commandDelegate evalJs:@"cordova.plugins.Keyboard.isVisible = false; cordova.fireWindowEvent('native.keyboardhide'); "]; 40 | 41 | //deprecated 42 | [weakSelf.commandDelegate evalJs:@"cordova.fireWindowEvent('native.hidekeyboard'); "]; 43 | }]; 44 | } 45 | - (BOOL)disableScroll { 46 | return _disableScroll; 47 | } 48 | 49 | - (void)setDisableScroll:(BOOL)disableScroll { 50 | if (disableScroll == _disableScroll) { 51 | return; 52 | } 53 | if (disableScroll) { 54 | self.webView.scrollView.scrollEnabled = NO; 55 | self.webView.scrollView.delegate = self; 56 | } 57 | else { 58 | self.webView.scrollView.scrollEnabled = YES; 59 | self.webView.scrollView.delegate = nil; 60 | } 61 | 62 | _disableScroll = disableScroll; 63 | } 64 | 65 | 66 | - (BOOL)hideKeyboardAccessoryBar { 67 | return _hideKeyboardAccessoryBar; 68 | } 69 | 70 | - (void)setHideKeyboardAccessoryBar:(BOOL)hideKeyboardAccessoryBar { 71 | if (hideKeyboardAccessoryBar == _hideKeyboardAccessoryBar) { 72 | return; 73 | } 74 | if (hideKeyboardAccessoryBar) { 75 | self.webView.hackishlyHidesInputAccessoryView = YES; 76 | } 77 | else { 78 | self.webView.hackishlyHidesInputAccessoryView = NO; 79 | } 80 | 81 | _hideKeyboardAccessoryBar = hideKeyboardAccessoryBar; 82 | } 83 | 84 | /* 85 | - (BOOL)styleDark { 86 | return _styleDark; 87 | } 88 | 89 | - (void)setStyleDark:(BOOL)styleDark { 90 | if (styleDark == _styleDark) { 91 | return; 92 | } 93 | if (styleDark) { 94 | self.webView.styleDark = YES; 95 | } 96 | else { 97 | self.webView.styleDark = NO; 98 | } 99 | 100 | _styleDark = styleDark; 101 | } 102 | */ 103 | 104 | 105 | /* ------------------------------------------------------------- */ 106 | 107 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 108 | [scrollView setContentOffset: CGPointZero]; 109 | } 110 | 111 | /* ------------------------------------------------------------- */ 112 | 113 | - (void)dealloc { 114 | NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; 115 | 116 | [nc removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 117 | [nc removeObserver:self name:UIKeyboardWillHideNotification object:nil]; 118 | } 119 | 120 | /* ------------------------------------------------------------- */ 121 | 122 | - (void) disableScroll:(CDVInvokedUrlCommand*)command { 123 | if (!command.arguments || ![command.arguments count]){ 124 | return; 125 | } 126 | id value = [command.arguments objectAtIndex:0]; 127 | 128 | self.disableScroll = [value boolValue]; 129 | } 130 | 131 | - (void) hideKeyboardAccessoryBar:(CDVInvokedUrlCommand*)command { 132 | if (!command.arguments || ![command.arguments count]){ 133 | return; 134 | } 135 | id value = [command.arguments objectAtIndex:0]; 136 | 137 | self.hideKeyboardAccessoryBar = [value boolValue]; 138 | } 139 | 140 | - (void) close:(CDVInvokedUrlCommand*)command { 141 | [self.webView endEditing:YES]; 142 | } 143 | 144 | /* 145 | - (void) styleDark:(CDVInvokedUrlCommand*)command { 146 | if (!command.arguments || ![command.arguments count]){ 147 | return; 148 | } 149 | id value = [command.arguments objectAtIndex:0]; 150 | 151 | self.styleDark = [value boolValue]; 152 | } 153 | */ 154 | 155 | @end 156 | 157 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/src/ios/UIWebViewExtension.h: -------------------------------------------------------------------------------- 1 | @interface UIWebView (HackishAccessoryHiding) 2 | @property (nonatomic, assign) BOOL hackishlyHidesInputAccessoryView; 3 | //@property (nonatomic, assign) BOOL styleDark; 4 | @end 5 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/src/ios/UIWebViewExtension.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "UIWebViewExtension.h" 4 | 5 | //Credit: https://gist.github.com/bjhomer/2048571 6 | //Also: http://stackoverflow.com/a/23398487/1091751 7 | @implementation UIWebView (HackishAccessoryHiding) 8 | 9 | static const char * const hackishFixClassName = "UIWebBrowserViewMinusAccessoryView"; 10 | static Class hackishFixClass = Nil; 11 | 12 | - (UIView *)hackishlyFoundBrowserView { 13 | UIScrollView *scrollView = self.scrollView; 14 | 15 | UIView *browserView = nil; 16 | for (UIView *subview in scrollView.subviews) { 17 | if ([NSStringFromClass([subview class]) hasPrefix:@"UIWebBrowserView"]) { 18 | browserView = subview; 19 | break; 20 | } 21 | } 22 | return browserView; 23 | } 24 | 25 | - (id)methodReturningNil { 26 | return nil; 27 | } 28 | 29 | - (void)ensureHackishSubclassExistsOfBrowserViewClass:(Class)browserViewClass { 30 | if (!hackishFixClass) { 31 | Class newClass = objc_allocateClassPair(browserViewClass, hackishFixClassName, 0); 32 | IMP nilImp = [self methodForSelector:@selector(methodReturningNil)]; 33 | class_addMethod(newClass, @selector(inputAccessoryView), nilImp, "@@:"); 34 | objc_registerClassPair(newClass); 35 | 36 | hackishFixClass = newClass; 37 | } 38 | } 39 | 40 | - (BOOL) hackishlyHidesInputAccessoryView { 41 | UIView *browserView = [self hackishlyFoundBrowserView]; 42 | return [browserView class] == hackishFixClass; 43 | } 44 | 45 | - (void) setHackishlyHidesInputAccessoryView:(BOOL)value { 46 | UIView *browserView = [self hackishlyFoundBrowserView]; 47 | if (browserView == nil) { 48 | return; 49 | } 50 | [self ensureHackishSubclassExistsOfBrowserViewClass:[browserView class]]; 51 | 52 | if (value) { 53 | object_setClass(browserView, hackishFixClass); 54 | } 55 | else { 56 | Class normalClass = objc_getClass("UIWebBrowserView"); 57 | object_setClass(browserView, normalClass); 58 | } 59 | [browserView reloadInputViews]; 60 | } 61 | /* ---------------------------------------------------------------- */ 62 | 63 | /* 64 | - (UIKeyboardAppearance) darkKeyboardAppearanceTemplateMethod { 65 | return UIKeyboardAppearanceDark; 66 | } 67 | 68 | - (UIKeyboardAppearance) lightKeyboardAppearanceTemplateMethod { 69 | return UIKeyboardAppearanceLight; 70 | } 71 | 72 | - (BOOL) styleDark { 73 | UIView *browserView = [self hackishlyFoundBrowserView]; 74 | if (browserView == nil) { 75 | return false; 76 | } 77 | 78 | Method m = class_getInstanceMethod( [self class], @selector( darkKeyboardAppearanceTemplateMethod ) ); 79 | IMP imp = method_getImplementation( m ); 80 | 81 | Method m2 = class_getInstanceMethod( [browserView class], @selector(keyboardAppearance) ); 82 | IMP imp2 = method_getImplementation( m2 ); 83 | 84 | return imp == imp2; 85 | } 86 | 87 | - (void) setStyleDark:(BOOL)styleDark { 88 | UIView *browserView = [self hackishlyFoundBrowserView]; 89 | if (browserView == nil) { 90 | return; 91 | } 92 | 93 | if ( styleDark ) { 94 | Method m = class_getInstanceMethod( [self class], @selector( darkKeyboardAppearanceTemplateMethod ) ); 95 | IMP imp = method_getImplementation( m ); 96 | const char* typeEncoding = method_getTypeEncoding( m ); 97 | class_replaceMethod( [browserView class], @selector(keyboardAppearance), imp, typeEncoding ); 98 | } 99 | else { 100 | Method m = class_getInstanceMethod( [self class], @selector( lightKeyboardAppearanceTemplateMethod ) ); 101 | IMP imp = method_getImplementation( m ); 102 | const char* typeEncoding = method_getTypeEncoding( m ); 103 | class_replaceMethod( [browserView class], @selector(keyboardAppearance), imp, typeEncoding ); 104 | } 105 | } 106 | */ 107 | 108 | @end 109 | 110 | -------------------------------------------------------------------------------- /plugins/com.ionic.keyboard/www/keyboard.js: -------------------------------------------------------------------------------- 1 | 2 | var argscheck = require('cordova/argscheck'), 3 | utils = require('cordova/utils'), 4 | exec = require('cordova/exec'); 5 | 6 | var Keyboard = function() { 7 | }; 8 | 9 | Keyboard.hideKeyboardAccessoryBar = function(hide) { 10 | exec(null, null, "Keyboard", "hideKeyboardAccessoryBar", [hide]); 11 | }; 12 | 13 | Keyboard.close = function() { 14 | exec(null, null, "Keyboard", "close", []); 15 | }; 16 | 17 | Keyboard.disableScroll = function(disable) { 18 | exec(null, null, "Keyboard", "disableScroll", [disable]); 19 | }; 20 | 21 | /* 22 | Keyboard.styleDark = function(dark) { 23 | exec(null, null, "Keyboard", "styleDark", [dark]); 24 | }; 25 | */ 26 | 27 | Keyboard.isVisible = false; 28 | 29 | module.exports = Keyboard; 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /www/css/index.css: -------------------------------------------------------------------------------- 1 | .ionic-logo { 2 | display: block; 3 | margin: 15px auto; 4 | width: 96px; 5 | height: 96px; 6 | } -------------------------------------------------------------------------------- /www/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/icon.png -------------------------------------------------------------------------------- /www/img/ionic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/img/ionic.png -------------------------------------------------------------------------------- /www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/img/logo.png -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ionic (RequireJS) Seed App 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Back 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /www/js/app.js: -------------------------------------------------------------------------------- 1 | /*global define, require */ 2 | 3 | define(['angular', 4 | 'uiRouter', 5 | 'config', 6 | 'filters/filters', 7 | 'services/services', 8 | 'directives/directives', 9 | 'controllers/controllers', 10 | 'ionicAngular'], 11 | 12 | function (angular, uiRouter) { 13 | 'use strict'; 14 | 15 | var app = angular.module('app', [ 16 | 'ionic', 17 | 'app.controllers', 18 | 'app.filters', 19 | 'app.services', 20 | 'app.directives', 21 | 'app.config', 22 | 'ui.router']); 23 | 24 | return app; 25 | 26 | }); -------------------------------------------------------------------------------- /www/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | /*global define, require, console, cordova, navigator */ 2 | 3 | define(['ionic', 'angular', 'app', 'routes'], function (ionic, angular, app) { 4 | 'use strict'; 5 | 6 | var $html, 7 | onDeviceReady = function () { 8 | angular.bootstrap(document, [app.name]); 9 | }; 10 | 11 | document.addEventListener("deviceready", onDeviceReady, false); 12 | 13 | if (typeof cordova === 'undefined') { 14 | $html = angular.element(document.getElementsByTagName('html')[0]); 15 | angular.element().ready(function () { 16 | try { 17 | angular.bootstrap(document, [app.name]); 18 | } catch (e) { 19 | console.error(e.stack || e.message || e); 20 | } 21 | }); 22 | } 23 | 24 | }); -------------------------------------------------------------------------------- /www/js/config.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | 3 | define(['angular'], function (angular) { 4 | 'use strict'; 5 | 6 | return angular.module('app.config', []) 7 | .constant('VERSION', '0.1'); 8 | 9 | }); -------------------------------------------------------------------------------- /www/js/controllers/LoginCtrl.js: -------------------------------------------------------------------------------- 1 | /*global define, console */ 2 | 3 | define(function () { 4 | 'use strict'; 5 | 6 | function ctrl($scope, $state) { 7 | 8 | $scope.login = function () { 9 | $state.go('tab.pet-index'); 10 | }; 11 | 12 | } 13 | 14 | ctrl.$inject = ['$scope', '$state']; 15 | return ctrl; 16 | 17 | }); -------------------------------------------------------------------------------- /www/js/controllers/PetDetailCtrl.js: -------------------------------------------------------------------------------- 1 | /*global define*/ 2 | 3 | define(function () { 4 | 'use strict'; 5 | 6 | function ctrl($scope, $stateParams, PetService) { 7 | $scope.pet = PetService.get($stateParams.petId); 8 | } 9 | 10 | ctrl.$inject = ['$scope', '$stateParams', 'PetService']; 11 | return ctrl; 12 | 13 | }); -------------------------------------------------------------------------------- /www/js/controllers/PetIndexCtrl.js: -------------------------------------------------------------------------------- 1 | /*global define*/ 2 | 3 | define(function () { 4 | 'use strict'; 5 | 6 | function ctrl($scope, PetService) { 7 | $scope.pets = PetService.all(); 8 | } 9 | 10 | ctrl.$inject = ['$scope', 'PetService']; 11 | return ctrl; 12 | 13 | }); -------------------------------------------------------------------------------- /www/js/controllers/controllers.js: -------------------------------------------------------------------------------- 1 | /*global define, require */ 2 | 3 | define(function (require) { 4 | 5 | 'use strict'; 6 | 7 | var angular = require('angular'), 8 | services = require('services/services'), 9 | config = require('config'), 10 | controllers = angular.module('app.controllers', ['app.services', 'app.config']); 11 | 12 | controllers.controller('LoginCtrl', require('controllers/LoginCtrl')); 13 | controllers.controller('PetIndexCtrl', require('controllers/PetIndexCtrl')); 14 | controllers.controller('PetDetailCtrl', require('controllers/PetDetailCtrl')); 15 | 16 | controllers.run(['$rootScope', function ($rootScope) { 17 | $rootScope.sampleParam = "value"; 18 | }]); 19 | 20 | return controllers; 21 | 22 | }); -------------------------------------------------------------------------------- /www/js/directives/VersionDirective.js: -------------------------------------------------------------------------------- 1 | /*global define*/ 2 | 3 | define(['angular'], function (angular) { 4 | "use strict"; 5 | 6 | var directive = function (VERSION) { 7 | return function (scope, elm, attrs) { 8 | elm.text(VERSION); 9 | }; 10 | }; 11 | 12 | directive.$inject = ['VERSION']; 13 | return directive; 14 | }); -------------------------------------------------------------------------------- /www/js/directives/directives.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | 3 | define(function (require) { 4 | 5 | 'use strict'; 6 | 7 | var angular = require('angular'), 8 | services = require('services/services'), 9 | directives = angular.module('app.directives', ['app.services']); 10 | 11 | directives.directive('appVersion', require('directives/VersionDirective')); 12 | return directives; 13 | }); -------------------------------------------------------------------------------- /www/js/filters/InterpolateFilter.js: -------------------------------------------------------------------------------- 1 | /*global define*/ 2 | 3 | define(['angular'], function (angular) { 4 | "use strict"; 5 | 6 | var filter = function (VERSION) { 7 | return function (text) { 8 | return String(text).replace(/\%VERSION\%/mg, VERSION); 9 | }; 10 | }; 11 | 12 | filter.$inject = ['VERSION']; 13 | return filter; 14 | }); -------------------------------------------------------------------------------- /www/js/filters/filters.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | 3 | define(['angular', 'filters/InterpolateFilter', 'services/services'], 4 | function (angular, InterpolateFilter) { 5 | 'use strict'; 6 | 7 | var filters = angular.module('app.filters', ['app.services']); 8 | filters.filter('interpolate', InterpolateFilter); 9 | return filters; 10 | 11 | }); -------------------------------------------------------------------------------- /www/js/main.js: -------------------------------------------------------------------------------- 1 | /*global requirejs, document, cordova, window, navigator, console */ 2 | 3 | requirejs.config({ 4 | paths: { 5 | angular: '../lib/js/angular/angular.min', 6 | angularAnimate: '../lib/js/angular/angular-animate.min', 7 | angularSanitize: '../lib/js/angular/angular-sanitize.min', 8 | uiRouter: '../lib/js/angular-ui/angular-ui-router.min', 9 | ionic: '../lib/js/ionic.min', 10 | ionicAngular: '../lib/js/ionic-angular.min', 11 | text: '../lib/js/text' 12 | }, 13 | shim: { 14 | angular : {exports : 'angular'}, 15 | angularAnimate : {deps: ['angular']}, 16 | angularSanitize : {deps: ['angular']}, 17 | uiRouter : {deps: ['angular']}, 18 | ionic : {deps: ['angular'], exports : 'ionic'}, 19 | ionicAngular: {deps: ['angular', 'ionic', 'uiRouter', 'angularAnimate', 'angularSanitize']} 20 | }, 21 | priority: [ 22 | 'angular', 23 | 'ionic' 24 | ], 25 | deps: [ 26 | 'bootstrap' 27 | ] 28 | }); -------------------------------------------------------------------------------- /www/js/routes.js: -------------------------------------------------------------------------------- 1 | /*global define, require */ 2 | 3 | define(['app'], function (app) { 4 | 'use strict'; 5 | 6 | app.config(['$stateProvider', '$urlRouterProvider', 7 | function ($stateProvider, $urlRouterProvider) { 8 | 9 | $stateProvider 10 | .state('login', { 11 | url: "/login", 12 | templateUrl: "templates/login.html", 13 | controller: 'LoginCtrl' 14 | }) 15 | .state('tab', { 16 | url: "/tab", 17 | abstract: true, 18 | templateUrl: "templates/tabs.html" 19 | }) 20 | .state('tab.pet-index', { 21 | url: '/pets', 22 | views: { 23 | 'pets-tab': { 24 | templateUrl: 'templates/pet-index.html', 25 | controller: 'PetIndexCtrl' 26 | } 27 | } 28 | }) 29 | .state('tab.pet-detail', { 30 | url: '/pet/:petId', 31 | views: { 32 | 'pets-tab': { 33 | templateUrl: 'templates/pet-detail.html', 34 | controller: 'PetDetailCtrl' 35 | } 36 | } 37 | }) 38 | .state('tab.adopt', { 39 | url: '/adopt', 40 | views: { 41 | 'adopt-tab': { 42 | templateUrl: 'templates/adopt.html' 43 | } 44 | } 45 | }) 46 | .state('tab.about', { 47 | url: '/about', 48 | views: { 49 | 'about-tab': { 50 | templateUrl: 'templates/about.html' 51 | } 52 | } 53 | }); 54 | 55 | 56 | $urlRouterProvider.otherwise("/login"); 57 | 58 | }]); 59 | 60 | 61 | }); -------------------------------------------------------------------------------- /www/js/services/PetService.js: -------------------------------------------------------------------------------- 1 | /*global define, console */ 2 | 3 | define(['angular'], function (angular) { 4 | "use strict"; 5 | 6 | var factory = function () { 7 | 8 | var pets = [ 9 | { id: 0, title: 'Cats', description: 'Furry little creatures. Obsessed with plotting assassination, but never following through on it.' }, 10 | { id: 1, title: 'Dogs', description: 'Lovable. Loyal almost to a fault. Smarter than they let on.' }, 11 | { id: 2, title: 'Turtles', description: 'Everyone likes turtles.' }, 12 | { id: 3, title: 'Sharks', description: 'An advanced pet. Needs millions of gallons of salt water. Will happily eat you.' } 13 | ]; 14 | 15 | return { 16 | all: function () { 17 | return pets; 18 | }, 19 | get: function (petId) { 20 | return pets[petId]; 21 | } 22 | }; 23 | 24 | }; 25 | 26 | factory.$inject = []; 27 | return factory; 28 | }); -------------------------------------------------------------------------------- /www/js/services/services.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | 3 | define(function (require) { 4 | 5 | 'use strict'; 6 | 7 | var angular = require('angular'), 8 | config = require('config'), 9 | services = angular.module('app.services', ['app.config']); 10 | 11 | services.factory('PetService', require('services/PetService')); 12 | 13 | return services; 14 | 15 | }); -------------------------------------------------------------------------------- /www/lib/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/lib/fonts/ionicons.eot -------------------------------------------------------------------------------- /www/lib/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/lib/fonts/ionicons.ttf -------------------------------------------------------------------------------- /www/lib/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/lib/fonts/ionicons.woff -------------------------------------------------------------------------------- /www/lib/js/angular-ui/angular-ui-router.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * State-based routing for AngularJS 3 | * @version v0.2.10 4 | * @link http://angular-ui.github.com/ 5 | * @license MIT License, http://www.opensource.org/licenses/MIT 6 | */ 7 | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return I(new(I(function(){},{prototype:a})),b)}function e(a){return H(arguments,function(b){b!==a&&H(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return I({},i,b)}function i(a,b){var c={};return H(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(o[c]=d,E(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);H(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return F(a)&&a.then&&a.$$promises}if(!F(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return H(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!C(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;H(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!F(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=I({},d),s=1+m.length/3,t=!1;if(C(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(I(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return C(a.template)?this.fromString(a.template,b):C(a.templateUrl)?this.fromUrl(a.templateUrl,b):C(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return D(a)?a(b):a},this.fromUrl=function(c,d){return D(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),H(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return F(a)&&D(a.exec)&&D(a.format)&&D(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return C(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!D(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(E(a)){var b=a;a=function(){return b}}else if(!D(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=E(f);if(E(e)&&(e=a.compile(e)),!h&&!D(f)&&!G(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),I(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:E(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),I(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(E(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=E(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=w[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){x[a]||(x[a]=[]),x[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!E(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(w.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):E(b.parent)?b.parent:"";if(e&&!w[e])return m(e,b.self);for(var f in z)D(z[f])&&(b[f]=z[f](b,z.$delegates[f]));if(w[c]=b,!b[y]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){v.$current.navigable==b&&j(a,c)||v.transitionTo(b,a,{location:!1})}]),x[c])for(var g=0;g-1}function p(a){var b=a.split("."),c=v.$current.name.split(".");if("**"===b[0]&&(c=c.slice(c.indexOf(b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(c.indexOf(b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function q(a,b){return E(a)&&!C(b)?z[a]:D(b)&&E(a)?(z[a]&&!z.$delegates[a]&&(z.$delegates[a]=z[a]),z[a]=b,this):this}function r(a,b){return F(a)?b=a:b.name=a,n(b),this}function s(a,e,g,m,n,q,r,s,x){function z(){r.url()!==M&&(r.url(M),r.replace())}function A(a,c,d,f,h){var i=d?c:k(a.params,c),j={$stateParams:i};h.resolve=n.resolve(a.resolve,j,h.resolve,a);var l=[h.resolve.then(function(a){h.globals=a})];return f&&l.push(f),H(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return g.load(d,{view:c,locals:j,params:i,notify:!1})||""}],l.push(n.resolve(e,j,h.resolve,a).then(function(f){if(D(c.controllerProvider)||G(c.controllerProvider)){var g=b.extend({},e,j);f.$$controller=m.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,h[d]=f}))}),e.all(l).then(function(){return h})}var B=e.reject(new Error("transition superseded")),F=e.reject(new Error("transition prevented")),K=e.reject(new Error("transition aborted")),L=e.reject(new Error("transition failed")),M=r.url(),N=x.baseHref();return u.locals={resolve:null,globals:{$stateParams:{}}},v={params:{},current:u.self,$current:u,transition:null},v.reload=function(){v.transitionTo(v.current,q,{reload:!0,inherit:!1,notify:!1})},v.go=function(a,b,c){return this.transitionTo(a,b,I({inherit:!0,relative:v.$current},c))},v.transitionTo=function(b,c,f){c=c||{},f=I({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,k=v.$current,n=v.params,o=k.path,p=l(b,f.relative);if(!C(p)){var s={to:b,toParams:c,options:f};if(g=a.$broadcast("$stateNotFound",s,k.self,n),g.defaultPrevented)return z(),K;if(g.retry){if(f.$retry)return z(),L;var w=v.transition=e.when(g.retry);return w.then(function(){return w!==v.transition?B:(s.options.$retry=!0,v.transitionTo(s.to,s.toParams,s.options))},function(){return K}),z(),w}if(b=s.to,c=s.toParams,f=s.options,p=l(b,f.relative),!C(p)){if(f.relative)throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'");throw new Error("No such state '"+b+"'")}}if(p[y])throw new Error("Cannot transition to abstract state '"+b+"'");f.inherit&&(c=h(q,c||{},v.$current,p)),b=p;var x,D,E=b.path,G=u.locals,H=[];for(x=0,D=E[x];D&&D===o[x]&&j(c,n,D.ownParams)&&!f.reload;x++,D=E[x])G=H[x]=D.locals;if(t(b,k,G,f))return b.self.reloadOnSearch!==!1&&z(),v.transition=null,e.when(v.current);if(c=i(b.params,c||{}),f.notify&&(g=a.$broadcast("$stateChangeStart",b.self,c,k.self,n),g.defaultPrevented))return z(),F;for(var N=e.when(G),O=x;O=x;d--)g=o[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=x;d1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target")||(c(function(){a.go(i.state,j,o)}),b.preventDefault())})}}}function y(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,w(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}]}}function z(a){return function(b){return a.is(b)}}function A(a){return function(b){return a.includes(b)}}function B(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(E(j))h=j;else{if(!D(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),J(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var C=b.isDefined,D=b.isFunction,E=b.isString,F=b.isObject,G=b.isArray,H=b.forEach,I=b.extend,J=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),b.module("ui.router.state").provider("$uiViewScroll",s),t.$inject=["$state","$injector","$uiViewScroll"],u.$inject=["$compile","$controller","$state"],b.module("ui.router.state").directive("uiView",t),b.module("ui.router.state").directive("uiView",u),x.$inject=["$state","$timeout"],y.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",x).directive("uiSrefActive",y),z.$inject=["$state"],A.$inject=["$state"],b.module("ui.router.state").filter("isState",z).filter("includedByState",A),B.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",B).directive("ngView",t)}(window,window.angular); -------------------------------------------------------------------------------- /www/lib/js/angular/angular-animate.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.25 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(F,e,O){'use strict';e.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(G,s,g){g=g.ngAnimateChildren;e.isString(g)&&0===g.length?s.data("$$ngAnimateChildren",!0):G.$watch(g,function(e){s.data("$$ngAnimateChildren",!!e)})}}).factory("$$animateReflow",["$$rAF","$document",function(e,s){return function(g){return e(function(){g()})}}]).config(["$provide","$animateProvider",function(G,s){function g(e){for(var g=0;g=y&&b>=v&&e()}var h=g(b);a=b.data(q);if(-1!=h.getAttribute("class").indexOf(d)&&a){var m="";u(d.split(" "),function(a,b){m+=(0 21 | * 22 | * See {@link ngSanitize.$sanitize `$sanitize`} for usage. 23 | */ 24 | 25 | /* 26 | * HTML Parser By Misko Hevery (misko@hevery.com) 27 | * based on: HTML Parser By John Resig (ejohn.org) 28 | * Original code by Erik Arvidsson, Mozilla Public License 29 | * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js 30 | * 31 | * // Use like so: 32 | * htmlParser(htmlString, { 33 | * start: function(tag, attrs, unary) {}, 34 | * end: function(tag) {}, 35 | * chars: function(text) {}, 36 | * comment: function(text) {} 37 | * }); 38 | * 39 | */ 40 | 41 | 42 | /** 43 | * @ngdoc service 44 | * @name $sanitize 45 | * @kind function 46 | * 47 | * @description 48 | * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are 49 | * then serialized back to properly escaped html string. This means that no unsafe input can make 50 | * it into the returned string, however, since our parser is more strict than a typical browser 51 | * parser, it's possible that some obscure input, which would be recognized as valid HTML by a 52 | * browser, won't make it through the sanitizer. 53 | * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and 54 | * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. 55 | * 56 | * @param {string} html Html input. 57 | * @returns {string} Sanitized html. 58 | * 59 | * @example 60 | 61 | 62 | 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(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). 110 | toBe('

an html\nclick here\nsnippet

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

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

"); 118 | }); 119 | 120 | it('should escape snippet without any filter', function() { 121 | expect(element(by.css('#bind-default div')).getInnerHtml()). 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 | element(by.model('snippet')).clear(); 129 | element(by.model('snippet')).sendKeys('new text'); 130 | expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). 131 | toBe('new text'); 132 | expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( 133 | 'new text'); 134 | expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( 135 | "new <b onclick=\"alert(1)\">text</b>"); 136 | }); 137 |
138 |
139 | */ 140 | function $SanitizeProvider() { 141 | this.$get = ['$$sanitizeUri', function($$sanitizeUri) { 142 | return function(html) { 143 | var buf = []; 144 | htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { 145 | return !/^unsafe/.test($$sanitizeUri(uri, isImage)); 146 | })); 147 | return buf.join(''); 148 | }; 149 | }]; 150 | } 151 | 152 | function sanitizeText(chars) { 153 | var buf = []; 154 | var writer = htmlSanitizeWriter(buf, angular.noop); 155 | writer.chars(chars); 156 | return buf.join(''); 157 | } 158 | 159 | 160 | // Regular Expressions for parsing tags and attributes 161 | var START_TAG_REGEXP = 162 | /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/, 163 | END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/, 164 | ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, 165 | BEGIN_TAG_REGEXP = /^/g, 168 | DOCTYPE_REGEXP = /]*?)>/i, 169 | CDATA_REGEXP = //g, 170 | SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 171 | // Match everything outside of normal chars and " (quote character) 172 | NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; 173 | 174 | 175 | // Good source of info about elements and attributes 176 | // http://dev.w3.org/html5/spec/Overview.html#semantics 177 | // http://simon.html5.org/html-elements 178 | 179 | // Safe Void Elements - HTML5 180 | // http://dev.w3.org/html5/spec/Overview.html#void-elements 181 | var voidElements = makeMap("area,br,col,hr,img,wbr"); 182 | 183 | // Elements that you can, intentionally, leave open (and which close themselves) 184 | // http://dev.w3.org/html5/spec/Overview.html#optional-tags 185 | var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), 186 | optionalEndTagInlineElements = makeMap("rp,rt"), 187 | optionalEndTagElements = angular.extend({}, 188 | optionalEndTagInlineElements, 189 | optionalEndTagBlockElements); 190 | 191 | // Safe Block Elements - HTML5 192 | var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + 193 | "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + 194 | "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); 195 | 196 | // Inline Elements - HTML5 197 | var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + 198 | "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + 199 | "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); 200 | 201 | 202 | // Special Elements (can contain anything) 203 | var specialElements = makeMap("script,style"); 204 | 205 | var validElements = angular.extend({}, 206 | voidElements, 207 | blockElements, 208 | inlineElements, 209 | optionalEndTagElements); 210 | 211 | //Attributes that have href and hence need to be sanitized 212 | var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); 213 | var validAttrs = angular.extend({}, uriAttrs, makeMap( 214 | 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ 215 | 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ 216 | 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ 217 | 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ 218 | 'valign,value,vspace,width')); 219 | 220 | function makeMap(str) { 221 | var obj = {}, items = str.split(','), i; 222 | for (i = 0; i < items.length; i++) obj[items[i]] = true; 223 | return obj; 224 | } 225 | 226 | 227 | /** 228 | * @example 229 | * htmlParser(htmlString, { 230 | * start: function(tag, attrs, unary) {}, 231 | * end: function(tag) {}, 232 | * chars: function(text) {}, 233 | * comment: function(text) {} 234 | * }); 235 | * 236 | * @param {string} html string 237 | * @param {object} handler 238 | */ 239 | function htmlParser( html, handler ) { 240 | if (typeof html !== 'string') { 241 | if (html === null || typeof html === 'undefined') { 242 | html = ''; 243 | } else { 244 | html = '' + html; 245 | } 246 | } 247 | var index, chars, match, stack = [], last = html, text; 248 | stack.last = function() { return stack[ stack.length - 1 ]; }; 249 | 250 | while ( html ) { 251 | text = ''; 252 | chars = true; 253 | 254 | // Make sure we're not in a script or style element 255 | if ( !stack.last() || !specialElements[ stack.last() ] ) { 256 | 257 | // Comment 258 | if ( html.indexOf("", index) === index) { 263 | if (handler.comment) handler.comment( html.substring( 4, index ) ); 264 | html = html.substring( index + 3 ); 265 | chars = false; 266 | } 267 | // DOCTYPE 268 | } else if ( DOCTYPE_REGEXP.test(html) ) { 269 | match = html.match( DOCTYPE_REGEXP ); 270 | 271 | if ( match ) { 272 | html = html.replace( match[0], ''); 273 | chars = false; 274 | } 275 | // end tag 276 | } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { 277 | match = html.match( END_TAG_REGEXP ); 278 | 279 | if ( match ) { 280 | html = html.substring( match[0].length ); 281 | match[0].replace( END_TAG_REGEXP, parseEndTag ); 282 | chars = false; 283 | } 284 | 285 | // start tag 286 | } else if ( BEGIN_TAG_REGEXP.test(html) ) { 287 | match = html.match( START_TAG_REGEXP ); 288 | 289 | if ( match ) { 290 | // We only have a valid start-tag if there is a '>'. 291 | if ( match[4] ) { 292 | html = html.substring( match[0].length ); 293 | match[0].replace( START_TAG_REGEXP, parseStartTag ); 294 | } 295 | chars = false; 296 | } else { 297 | // no ending tag found --- this piece should be encoded as an entity. 298 | text += '<'; 299 | html = html.substring(1); 300 | } 301 | } 302 | 303 | if ( chars ) { 304 | index = html.indexOf("<"); 305 | 306 | text += index < 0 ? html : html.substring( 0, index ); 307 | html = index < 0 ? "" : html.substring( index ); 308 | 309 | if (handler.chars) handler.chars( decodeEntities(text) ); 310 | } 311 | 312 | } else { 313 | html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), 314 | function(all, text){ 315 | text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); 316 | 317 | if (handler.chars) handler.chars( decodeEntities(text) ); 318 | 319 | return ""; 320 | }); 321 | 322 | parseEndTag( "", stack.last() ); 323 | } 324 | 325 | if ( html == last ) { 326 | throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + 327 | "of html: {0}", html); 328 | } 329 | last = html; 330 | } 331 | 332 | // Clean up any remaining tags 333 | parseEndTag(); 334 | 335 | function parseStartTag( tag, tagName, rest, unary ) { 336 | tagName = angular.lowercase(tagName); 337 | if ( blockElements[ tagName ] ) { 338 | while ( stack.last() && inlineElements[ stack.last() ] ) { 339 | parseEndTag( "", stack.last() ); 340 | } 341 | } 342 | 343 | if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { 344 | parseEndTag( "", tagName ); 345 | } 346 | 347 | unary = voidElements[ tagName ] || !!unary; 348 | 349 | if ( !unary ) 350 | stack.push( tagName ); 351 | 352 | var attrs = {}; 353 | 354 | rest.replace(ATTR_REGEXP, 355 | function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { 356 | var value = doubleQuotedValue 357 | || singleQuotedValue 358 | || unquotedValue 359 | || ''; 360 | 361 | attrs[name] = decodeEntities(value); 362 | }); 363 | if (handler.start) handler.start( tagName, attrs, unary ); 364 | } 365 | 366 | function parseEndTag( tag, tagName ) { 367 | var pos = 0, i; 368 | tagName = angular.lowercase(tagName); 369 | if ( tagName ) 370 | // Find the closest opened tag of the same type 371 | for ( pos = stack.length - 1; pos >= 0; pos-- ) 372 | if ( stack[ pos ] == tagName ) 373 | break; 374 | 375 | if ( pos >= 0 ) { 376 | // Close all the open elements, up the stack 377 | for ( i = stack.length - 1; i >= pos; i-- ) 378 | if (handler.end) handler.end( stack[ i ] ); 379 | 380 | // Remove the open elements from the stack 381 | stack.length = pos; 382 | } 383 | } 384 | } 385 | 386 | var hiddenPre=document.createElement("pre"); 387 | var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; 388 | /** 389 | * decodes all entities into regular string 390 | * @param value 391 | * @returns {string} A string with decoded entities. 392 | */ 393 | function decodeEntities(value) { 394 | if (!value) { return ''; } 395 | 396 | // Note: IE8 does not preserve spaces at the start/end of innerHTML 397 | // so we must capture them and reattach them afterward 398 | var parts = spaceRe.exec(value); 399 | var spaceBefore = parts[1]; 400 | var spaceAfter = parts[3]; 401 | var content = parts[2]; 402 | if (content) { 403 | hiddenPre.innerHTML=content.replace(//g, '>'); 434 | } 435 | 436 | /** 437 | * create an HTML/XML writer which writes to buffer 438 | * @param {Array} buf use buf.jain('') to get out sanitized html string 439 | * @returns {object} in the form of { 440 | * start: function(tag, attrs, unary) {}, 441 | * end: function(tag) {}, 442 | * chars: function(text) {}, 443 | * comment: function(text) {} 444 | * } 445 | */ 446 | function htmlSanitizeWriter(buf, uriValidator){ 447 | var ignore = false; 448 | var out = angular.bind(buf, buf.push); 449 | return { 450 | start: function(tag, attrs, unary){ 451 | tag = angular.lowercase(tag); 452 | if (!ignore && specialElements[tag]) { 453 | ignore = tag; 454 | } 455 | if (!ignore && validElements[tag] === true) { 456 | out('<'); 457 | out(tag); 458 | angular.forEach(attrs, function(value, key){ 459 | var lkey=angular.lowercase(key); 460 | var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); 461 | if (validAttrs[lkey] === true && 462 | (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { 463 | out(' '); 464 | out(key); 465 | out('="'); 466 | out(encodeEntities(value)); 467 | out('"'); 468 | } 469 | }); 470 | out(unary ? '/>' : '>'); 471 | } 472 | }, 473 | end: function(tag){ 474 | tag = angular.lowercase(tag); 475 | if (!ignore && validElements[tag] === true) { 476 | out(''); 479 | } 480 | if (tag == ignore) { 481 | ignore = false; 482 | } 483 | }, 484 | chars: function(chars){ 485 | if (!ignore) { 486 | out(encodeEntities(chars)); 487 | } 488 | } 489 | }; 490 | } 491 | 492 | 493 | // define ngSanitize module and register $sanitize service 494 | angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); 495 | 496 | /* global sanitizeText: false */ 497 | 498 | /** 499 | * @ngdoc filter 500 | * @name linky 501 | * @kind function 502 | * 503 | * @description 504 | * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and 505 | * plain email address links. 506 | * 507 | * Requires the {@link ngSanitize `ngSanitize`} module to be installed. 508 | * 509 | * @param {string} text Input text. 510 | * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. 511 | * @returns {string} Html-linkified text. 512 | * 513 | * @usage 514 | 515 | * 516 | * @example 517 | 518 | 519 | 531 |
532 | Snippet: 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 544 | 547 | 548 | 549 | 550 | 553 | 556 | 557 | 558 | 559 | 560 | 561 | 562 |
FilterSourceRendered
linky filter 542 |
<div ng-bind-html="snippet | linky">
</div>
543 |
545 |
546 |
linky target 551 |
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
552 |
554 |
555 |
no filter
<div ng-bind="snippet">
</div>
563 | 564 | 565 | it('should linkify the snippet with urls', function() { 566 | expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). 567 | toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + 568 | 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); 569 | expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); 570 | }); 571 | 572 | it('should not linkify snippet without the linky filter', function() { 573 | expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). 574 | toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + 575 | 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); 576 | expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); 577 | }); 578 | 579 | it('should update', function() { 580 | element(by.model('snippet')).clear(); 581 | element(by.model('snippet')).sendKeys('new http://link.'); 582 | expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). 583 | toBe('new http://link.'); 584 | expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); 585 | expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) 586 | .toBe('new http://link.'); 587 | }); 588 | 589 | it('should work with the target property', function() { 590 | expect(element(by.id('linky-target')). 591 | element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). 592 | toBe('http://angularjs.org/'); 593 | expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); 594 | }); 595 | 596 | 597 | */ 598 | angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { 599 | var LINKY_URL_REGEXP = 600 | /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"]/, 601 | MAILTO_REGEXP = /^mailto:/; 602 | 603 | return function(text, target) { 604 | if (!text) return text; 605 | var match; 606 | var raw = text; 607 | var html = []; 608 | var url; 609 | var i; 610 | while ((match = raw.match(LINKY_URL_REGEXP))) { 611 | // We can not end in these as they are sometimes found at the end of the sentence 612 | url = match[0]; 613 | // if we did not match ftp/http/mailto then assume mailto 614 | if (match[2] == match[3]) url = 'mailto:' + url; 615 | i = match.index; 616 | addText(raw.substr(0, i)); 617 | addLink(url, match[0].replace(MAILTO_REGEXP, '')); 618 | raw = raw.substring(i + match[0].length); 619 | } 620 | addText(raw); 621 | return $sanitize(html.join('')); 622 | 623 | function addText(text) { 624 | if (!text) { 625 | return; 626 | } 627 | html.push(sanitizeText(text)); 628 | } 629 | 630 | function addLink(url, text) { 631 | html.push(''); 640 | addText(text); 641 | html.push(''); 642 | } 643 | }; 644 | }]); 645 | 646 | 647 | })(window, window.angular); 648 | -------------------------------------------------------------------------------- /www/lib/js/angular/angular-sanitize.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.25 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(q,g,r){'use strict';function F(a){var d=[];t(d,g.noop).chars(a);return d.join("")}function m(a){var d={};a=a.split(",");var c;for(c=0;c=c;e--)d.end&&d.end(f[e]);f.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,l,f=[],n=a,h;for(f.last=function(){return f[f.length-1]};a;){h="";l=!0;if(f.last()&&y[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(a,b){b=b.replace(I,"$1").replace(J,"$1");d.chars&&d.chars(s(b));return""}),e("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(d.comment&&d.comment(a.substring(4, 8 | b)),a=a.substring(b+3),l=!1);else if(z.test(a)){if(b=a.match(z))a=a.replace(b[0],""),l=!1}else if(K.test(a)){if(b=a.match(A))a=a.substring(b[0].length),b[0].replace(A,e),l=!1}else L.test(a)&&((b=a.match(B))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(B,c)),l=!1):(h+="<",a=a.substring(1)));l&&(b=a.indexOf("<"),h+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),d.chars&&d.chars(s(h)))}if(a==n)throw M("badparse",a);n=a}e()}function s(a){if(!a)return"";var d=N.exec(a);a=d[1];var c=d[3];if(d=d[2])p.innerHTML= 9 | d.replace(//g,">")}function t(a,d){var c=!1,e=g.bind(a,a.push);return{start:function(a,l,f){a=g.lowercase(a);!c&&y[a]&&(c=a);c||!0!==D[a]||(e("<"),e(a),g.forEach(l,function(c,f){var k= 10 | g.lowercase(f),l="img"===a&&"src"===k||"background"===k;!0!==Q[k]||!0===E[k]&&!d(c,l)||(e(" "),e(f),e('="'),e(C(c)),e('"'))}),e(f?"/>":">"))},end:function(a){a=g.lowercase(a);c||!0!==D[a]||(e(""));a==c&&(c=!1)},chars:function(a){c||e(C(a))}}}var M=g.$$minErr("$sanitize"),B=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,A=/^<\/\s*([\w:-]+)[^>]*>/,H=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,L=/^]*?)>/i,J=/"]/,c=/^mailto:/;return function(e,b){function l(a){a&&k.push(F(a))}function f(a,c){k.push("');l(c);k.push("")} 14 | if(!e)return e;for(var n,h=e,k=[],m,p;n=h.match(d);)m=n[0],n[2]==n[3]&&(m="mailto:"+m),p=n.index,l(h.substr(0,p)),f(m,n[0].replace(c,"")),h=h.substring(p+n[0].length);l(h);return a(k.join(""))}}])})(window,window.angular); 15 | //# sourceMappingURL=angular-sanitize.min.js.map 16 | -------------------------------------------------------------------------------- /www/lib/js/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | var requirejs,require,define; 7 | (function(ca){function G(b){return"[object Function]"===M.call(b)}function H(b){return"[object Array]"===M.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&& 19 | (f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= 20 | this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f); 21 | if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval", 22 | "fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b, 23 | a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m, 24 | nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b, 25 | a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild= 26 | !0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!== 27 | d&&(!("."===g||".."===g)||1g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)): 34 | (g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl= 35 | Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b|| 36 | (b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this); 37 | -------------------------------------------------------------------------------- /www/lib/js/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/requirejs/text for details 5 | */ 6 | /*jslint regexp: true */ 7 | /*global require, XMLHttpRequest, ActiveXObject, 8 | define, window, process, Packages, 9 | java, location, Components, FileUtils */ 10 | 11 | define(['module'], function (module) { 12 | 'use strict'; 13 | 14 | var text, fs, Cc, Ci, xpcIsWindows, 15 | progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 16 | xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, 17 | bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, 18 | hasLocation = typeof location !== 'undefined' && location.href, 19 | defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), 20 | defaultHostName = hasLocation && location.hostname, 21 | defaultPort = hasLocation && (location.port || undefined), 22 | buildMap = {}, 23 | masterConfig = (module.config && module.config()) || {}; 24 | 25 | text = { 26 | version: '2.0.10', 27 | 28 | strip: function (content) { 29 | //Strips declarations so that external SVG and XML 30 | //documents can be added to a document without worry. Also, if the string 31 | //is an HTML document, only the part inside the body tag is returned. 32 | if (content) { 33 | content = content.replace(xmlRegExp, ""); 34 | var matches = content.match(bodyRegExp); 35 | if (matches) { 36 | content = matches[1]; 37 | } 38 | } else { 39 | content = ""; 40 | } 41 | return content; 42 | }, 43 | 44 | jsEscape: function (content) { 45 | return content.replace(/(['\\])/g, '\\$1') 46 | .replace(/[\f]/g, "\\f") 47 | .replace(/[\b]/g, "\\b") 48 | .replace(/[\n]/g, "\\n") 49 | .replace(/[\t]/g, "\\t") 50 | .replace(/[\r]/g, "\\r") 51 | .replace(/[\u2028]/g, "\\u2028") 52 | .replace(/[\u2029]/g, "\\u2029"); 53 | }, 54 | 55 | createXhr: masterConfig.createXhr || function () { 56 | //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 57 | var xhr, i, progId; 58 | if (typeof XMLHttpRequest !== "undefined") { 59 | return new XMLHttpRequest(); 60 | } else if (typeof ActiveXObject !== "undefined") { 61 | for (i = 0; i < 3; i += 1) { 62 | progId = progIds[i]; 63 | try { 64 | xhr = new ActiveXObject(progId); 65 | } catch (e) {} 66 | 67 | if (xhr) { 68 | progIds = [progId]; // so faster next time 69 | break; 70 | } 71 | } 72 | } 73 | 74 | return xhr; 75 | }, 76 | 77 | /** 78 | * Parses a resource name into its component parts. Resource names 79 | * look like: module/name.ext!strip, where the !strip part is 80 | * optional. 81 | * @param {String} name the resource name 82 | * @returns {Object} with properties "moduleName", "ext" and "strip" 83 | * where strip is a boolean. 84 | */ 85 | parseName: function (name) { 86 | var modName, ext, temp, 87 | strip = false, 88 | index = name.indexOf("."), 89 | isRelative = name.indexOf('./') === 0 || 90 | name.indexOf('../') === 0; 91 | 92 | if (index !== -1 && (!isRelative || index > 1)) { 93 | modName = name.substring(0, index); 94 | ext = name.substring(index + 1, name.length); 95 | } else { 96 | modName = name; 97 | } 98 | 99 | temp = ext || modName; 100 | index = temp.indexOf("!"); 101 | if (index !== -1) { 102 | //Pull off the strip arg. 103 | strip = temp.substring(index + 1) === "strip"; 104 | temp = temp.substring(0, index); 105 | if (ext) { 106 | ext = temp; 107 | } else { 108 | modName = temp; 109 | } 110 | } 111 | 112 | return { 113 | moduleName: modName, 114 | ext: ext, 115 | strip: strip 116 | }; 117 | }, 118 | 119 | xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, 120 | 121 | /** 122 | * Is an URL on another domain. Only works for browser use, returns 123 | * false in non-browser environments. Only used to know if an 124 | * optimized .js version of a text resource should be loaded 125 | * instead. 126 | * @param {String} url 127 | * @returns Boolean 128 | */ 129 | useXhr: function (url, protocol, hostname, port) { 130 | var uProtocol, uHostName, uPort, 131 | match = text.xdRegExp.exec(url); 132 | if (!match) { 133 | return true; 134 | } 135 | uProtocol = match[2]; 136 | uHostName = match[3]; 137 | 138 | uHostName = uHostName.split(':'); 139 | uPort = uHostName[1]; 140 | uHostName = uHostName[0]; 141 | 142 | return (!uProtocol || uProtocol === protocol) && 143 | (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) && 144 | ((!uPort && !uHostName) || uPort === port); 145 | }, 146 | 147 | finishLoad: function (name, strip, content, onLoad) { 148 | content = strip ? text.strip(content) : content; 149 | if (masterConfig.isBuild) { 150 | buildMap[name] = content; 151 | } 152 | onLoad(content); 153 | }, 154 | 155 | load: function (name, req, onLoad, config) { 156 | //Name has format: some.module.filext!strip 157 | //The strip part is optional. 158 | //if strip is present, then that means only get the string contents 159 | //inside a body tag in an HTML string. For XML/SVG content it means 160 | //removing the declarations so the content can be inserted 161 | //into the current doc without problems. 162 | 163 | // Do not bother with the work if a build and text will 164 | // not be inlined. 165 | if (config.isBuild && !config.inlineText) { 166 | onLoad(); 167 | return; 168 | } 169 | 170 | masterConfig.isBuild = config.isBuild; 171 | 172 | var parsed = text.parseName(name), 173 | nonStripName = parsed.moduleName + 174 | (parsed.ext ? '.' + parsed.ext : ''), 175 | url = req.toUrl(nonStripName), 176 | useXhr = (masterConfig.useXhr) || 177 | text.useXhr; 178 | 179 | // Do not load if it is an empty: url 180 | if (url.indexOf('empty:') === 0) { 181 | onLoad(); 182 | return; 183 | } 184 | 185 | //Load the text. Use XHR if possible and in a browser. 186 | if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { 187 | text.get(url, function (content) { 188 | text.finishLoad(name, parsed.strip, content, onLoad); 189 | }, function (err) { 190 | if (onLoad.error) { 191 | onLoad.error(err); 192 | } 193 | }); 194 | } else { 195 | //Need to fetch the resource across domains. Assume 196 | //the resource has been optimized into a JS module. Fetch 197 | //by the module name + extension, but do not include the 198 | //!strip part to avoid file system issues. 199 | req([nonStripName], function (content) { 200 | text.finishLoad(parsed.moduleName + '.' + parsed.ext, 201 | parsed.strip, content, onLoad); 202 | }); 203 | } 204 | }, 205 | 206 | write: function (pluginName, moduleName, write, config) { 207 | if (buildMap.hasOwnProperty(moduleName)) { 208 | var content = text.jsEscape(buildMap[moduleName]); 209 | write.asModule(pluginName + "!" + moduleName, 210 | "define(function () { return '" + 211 | content + 212 | "';});\n"); 213 | } 214 | }, 215 | 216 | writeFile: function (pluginName, moduleName, req, write, config) { 217 | var parsed = text.parseName(moduleName), 218 | extPart = parsed.ext ? '.' + parsed.ext : '', 219 | nonStripName = parsed.moduleName + extPart, 220 | //Use a '.js' file name so that it indicates it is a 221 | //script that can be loaded across domains. 222 | fileName = req.toUrl(parsed.moduleName + extPart) + '.js'; 223 | 224 | //Leverage own load() method to load plugin value, but only 225 | //write out values that do not have the strip argument, 226 | //to avoid any potential issues with ! in file names. 227 | text.load(nonStripName, req, function (value) { 228 | //Use own write() method to construct full module value. 229 | //But need to create shell that translates writeFile's 230 | //write() to the right interface. 231 | var textWrite = function (contents) { 232 | return write(fileName, contents); 233 | }; 234 | textWrite.asModule = function (moduleName, contents) { 235 | return write.asModule(moduleName, fileName, contents); 236 | }; 237 | 238 | text.write(pluginName, nonStripName, textWrite, config); 239 | }, config); 240 | } 241 | }; 242 | 243 | if (masterConfig.env === 'node' || (!masterConfig.env && 244 | typeof process !== "undefined" && 245 | process.versions && 246 | !!process.versions.node && 247 | !process.versions['node-webkit'])) { 248 | //Using special require.nodeRequire, something added by r.js. 249 | fs = require.nodeRequire('fs'); 250 | 251 | text.get = function (url, callback, errback) { 252 | try { 253 | var file = fs.readFileSync(url, 'utf8'); 254 | //Remove BOM (Byte Mark Order) from utf8 files if it is there. 255 | if (file.indexOf('\uFEFF') === 0) { 256 | file = file.substring(1); 257 | } 258 | callback(file); 259 | } catch (e) { 260 | errback(e); 261 | } 262 | }; 263 | } else if (masterConfig.env === 'xhr' || (!masterConfig.env && 264 | text.createXhr())) { 265 | text.get = function (url, callback, errback, headers) { 266 | var xhr = text.createXhr(), header; 267 | xhr.open('GET', url, true); 268 | 269 | //Allow plugins direct access to xhr headers 270 | if (headers) { 271 | for (header in headers) { 272 | if (headers.hasOwnProperty(header)) { 273 | xhr.setRequestHeader(header.toLowerCase(), headers[header]); 274 | } 275 | } 276 | } 277 | 278 | //Allow overrides specified in config 279 | if (masterConfig.onXhr) { 280 | masterConfig.onXhr(xhr, url); 281 | } 282 | 283 | xhr.onreadystatechange = function (evt) { 284 | var status, err; 285 | //Do not explicitly handle errors, those should be 286 | //visible via console output in the browser. 287 | if (xhr.readyState === 4) { 288 | status = xhr.status; 289 | if (status > 399 && status < 600) { 290 | //An http 4xx or 5xx error. Signal an error. 291 | err = new Error(url + ' HTTP status: ' + status); 292 | err.xhr = xhr; 293 | errback(err); 294 | } else { 295 | callback(xhr.responseText); 296 | } 297 | 298 | if (masterConfig.onXhrComplete) { 299 | masterConfig.onXhrComplete(xhr, url); 300 | } 301 | } 302 | }; 303 | xhr.send(null); 304 | }; 305 | } else if (masterConfig.env === 'rhino' || (!masterConfig.env && 306 | typeof Packages !== 'undefined' && typeof java !== 'undefined')) { 307 | //Why Java, why is this so awkward? 308 | text.get = function (url, callback) { 309 | var stringBuffer, line, 310 | encoding = "utf-8", 311 | file = new java.io.File(url), 312 | lineSeparator = java.lang.System.getProperty("line.separator"), 313 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 314 | content = ''; 315 | try { 316 | stringBuffer = new java.lang.StringBuffer(); 317 | line = input.readLine(); 318 | 319 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 320 | // http://www.unicode.org/faq/utf_bom.html 321 | 322 | // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 323 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 324 | if (line && line.length() && line.charAt(0) === 0xfeff) { 325 | // Eat the BOM, since we've already found the encoding on this file, 326 | // and we plan to concatenating this buffer with others; the BOM should 327 | // only appear at the top of a file. 328 | line = line.substring(1); 329 | } 330 | 331 | if (line !== null) { 332 | stringBuffer.append(line); 333 | } 334 | 335 | while ((line = input.readLine()) !== null) { 336 | stringBuffer.append(lineSeparator); 337 | stringBuffer.append(line); 338 | } 339 | //Make sure we return a JavaScript string and not a Java string. 340 | content = String(stringBuffer.toString()); //String 341 | } finally { 342 | input.close(); 343 | } 344 | callback(content); 345 | }; 346 | } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env && 347 | typeof Components !== 'undefined' && Components.classes && 348 | Components.interfaces)) { 349 | //Avert your gaze! 350 | Cc = Components.classes, 351 | Ci = Components.interfaces; 352 | Components.utils['import']('resource://gre/modules/FileUtils.jsm'); 353 | xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc); 354 | 355 | text.get = function (url, callback) { 356 | var inStream, convertStream, fileObj, 357 | readData = {}; 358 | 359 | if (xpcIsWindows) { 360 | url = url.replace(/\//g, '\\'); 361 | } 362 | 363 | fileObj = new FileUtils.File(url); 364 | 365 | //XPCOM, you so crazy 366 | try { 367 | inStream = Cc['@mozilla.org/network/file-input-stream;1'] 368 | .createInstance(Ci.nsIFileInputStream); 369 | inStream.init(fileObj, 1, 0, false); 370 | 371 | convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] 372 | .createInstance(Ci.nsIConverterInputStream); 373 | convertStream.init(inStream, "utf-8", inStream.available(), 374 | Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); 375 | 376 | convertStream.readString(inStream.available(), readData); 377 | convertStream.close(); 378 | inStream.close(); 379 | callback(readData.value); 380 | } catch (e) { 381 | throw new Error((fileObj && fileObj.path || '') + ': ' + e); 382 | } 383 | }; 384 | } 385 | return text; 386 | }); 387 | -------------------------------------------------------------------------------- /www/res/.pgbomit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/.pgbomit -------------------------------------------------------------------------------- /www/res/icon/android/icon-36-ldpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/android/icon-36-ldpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-48-mdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/android/icon-48-mdpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-72-hdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/android/icon-72-hdpi.png -------------------------------------------------------------------------------- /www/res/icon/android/icon-96-xhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/android/icon-96-xhdpi.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-48-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/bada-wac/icon-48-type5.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-50-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/bada-wac/icon-50-type3.png -------------------------------------------------------------------------------- /www/res/icon/bada-wac/icon-80-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/bada-wac/icon-80-type4.png -------------------------------------------------------------------------------- /www/res/icon/bada/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/bada/icon-128.png -------------------------------------------------------------------------------- /www/res/icon/blackberry/icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/blackberry/icon-80.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-57-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/ios/icon-57-2x.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/ios/icon-57.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-72-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/ios/icon-72-2x.png -------------------------------------------------------------------------------- /www/res/icon/ios/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/ios/icon-72.png -------------------------------------------------------------------------------- /www/res/icon/tizen/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/tizen/icon-128.png -------------------------------------------------------------------------------- /www/res/icon/webos/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/webos/icon-64.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-173-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/windows-phone/icon-173-tile.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/windows-phone/icon-48.png -------------------------------------------------------------------------------- /www/res/icon/windows-phone/icon-62-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/icon/windows-phone/icon-62-tile.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-hdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-hdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-hdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-hdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-ldpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-ldpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-ldpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-ldpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-mdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-mdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-mdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-mdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-xhdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-xhdpi-landscape.png -------------------------------------------------------------------------------- /www/res/screen/android/screen-xhdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/android/screen-xhdpi-portrait.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/bada-wac/screen-type3.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/bada-wac/screen-type4.png -------------------------------------------------------------------------------- /www/res/screen/bada-wac/screen-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/bada-wac/screen-type5.png -------------------------------------------------------------------------------- /www/res/screen/bada/screen-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/bada/screen-portrait.png -------------------------------------------------------------------------------- /www/res/screen/blackberry/screen-225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/blackberry/screen-225.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-ipad-landscape-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-ipad-landscape.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-ipad-portrait-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-ipad-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-ipad-portrait.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-iphone-landscape-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-iphone-landscape.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-iphone-portrait-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait-568h-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-iphone-portrait-568h-2x.png -------------------------------------------------------------------------------- /www/res/screen/ios/screen-iphone-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/ios/screen-iphone-portrait.png -------------------------------------------------------------------------------- /www/res/screen/tizen/README.md: -------------------------------------------------------------------------------- 1 | # Tizen Splash Screen 2 | 3 | Splash screens are unsupported on the Tizen platform. 4 | -------------------------------------------------------------------------------- /www/res/screen/webos/screen-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/webos/screen-64.png -------------------------------------------------------------------------------- /www/res/screen/windows-phone/screen-portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paldom/angular-ionic-requirejs-phonegap-seed/46f0cdba041dcc05bf47693c7e741de8b5dde700/www/res/screen/windows-phone/screen-portrait.jpg -------------------------------------------------------------------------------- /www/spec.html: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | Jasmine Spec Runner 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /www/spec/helper.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | afterEach(function() { 20 | document.getElementById('stage').innerHTML = ''; 21 | }); 22 | 23 | var helper = { 24 | trigger: function(obj, name) { 25 | var e = document.createEvent('Event'); 26 | e.initEvent(name, true, true); 27 | obj.dispatchEvent(e); 28 | }, 29 | getComputedStyle: function(querySelector, property) { 30 | var element = document.querySelector(querySelector); 31 | return window.getComputedStyle(element).getPropertyValue(property); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /www/spec/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | describe('app', function() { 20 | describe('initialize', function() { 21 | it('should bind deviceready', function() { 22 | runs(function() { 23 | spyOn(app, 'onDeviceReady'); 24 | app.initialize(); 25 | helper.trigger(window.document, 'deviceready'); 26 | }); 27 | 28 | waitsFor(function() { 29 | return (app.onDeviceReady.calls.length > 0); 30 | }, 'onDeviceReady should be called once', 500); 31 | 32 | runs(function() { 33 | expect(app.onDeviceReady).toHaveBeenCalled(); 34 | }); 35 | }); 36 | }); 37 | 38 | describe('onDeviceReady', function() { 39 | it('should report that it fired', function() { 40 | spyOn(app, 'receivedEvent'); 41 | app.onDeviceReady(); 42 | expect(app.receivedEvent).toHaveBeenCalledWith('deviceready'); 43 | }); 44 | }); 45 | 46 | describe('receivedEvent', function() { 47 | beforeEach(function() { 48 | var el = document.getElementById('stage'); 49 | el.innerHTML = ['
', 50 | '

Listening

', 51 | '

Received

', 52 | '
'].join('\n'); 53 | }); 54 | 55 | it('should hide the listening element', function() { 56 | app.receivedEvent('deviceready'); 57 | var displayStyle = helper.getComputedStyle('#deviceready .listening', 'display'); 58 | expect(displayStyle).toEqual('none'); 59 | }); 60 | 61 | it('should show the received element', function() { 62 | app.receivedEvent('deviceready'); 63 | var displayStyle = helper.getComputedStyle('#deviceready .received', 'display'); 64 | expect(displayStyle).toEqual('block'); 65 | }); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /www/spec/lib/jasmine-1.2.0/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /www/spec/lib/jasmine-1.2.0/jasmine-html.js: -------------------------------------------------------------------------------- 1 | jasmine.HtmlReporterHelpers = {}; 2 | 3 | jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { 4 | var el = document.createElement(type); 5 | 6 | for (var i = 2; i < arguments.length; i++) { 7 | var child = arguments[i]; 8 | 9 | if (typeof child === 'string') { 10 | el.appendChild(document.createTextNode(child)); 11 | } else { 12 | if (child) { 13 | el.appendChild(child); 14 | } 15 | } 16 | } 17 | 18 | for (var attr in attrs) { 19 | if (attr == "className") { 20 | el[attr] = attrs[attr]; 21 | } else { 22 | el.setAttribute(attr, attrs[attr]); 23 | } 24 | } 25 | 26 | return el; 27 | }; 28 | 29 | jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { 30 | var results = child.results(); 31 | var status = results.passed() ? 'passed' : 'failed'; 32 | if (results.skipped) { 33 | status = 'skipped'; 34 | } 35 | 36 | return status; 37 | }; 38 | 39 | jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { 40 | var parentDiv = this.dom.summary; 41 | var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; 42 | var parent = child[parentSuite]; 43 | 44 | if (parent) { 45 | if (typeof this.views.suites[parent.id] == 'undefined') { 46 | this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); 47 | } 48 | parentDiv = this.views.suites[parent.id].element; 49 | } 50 | 51 | parentDiv.appendChild(childElement); 52 | }; 53 | 54 | 55 | jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { 56 | for(var fn in jasmine.HtmlReporterHelpers) { 57 | ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; 58 | } 59 | }; 60 | 61 | jasmine.HtmlReporter = function(_doc) { 62 | var self = this; 63 | var doc = _doc || window.document; 64 | 65 | var reporterView; 66 | 67 | var dom = {}; 68 | 69 | // Jasmine Reporter Public Interface 70 | self.logRunningSpecs = false; 71 | 72 | self.reportRunnerStarting = function(runner) { 73 | var specs = runner.specs() || []; 74 | 75 | if (specs.length == 0) { 76 | return; 77 | } 78 | 79 | createReporterDom(runner.env.versionString()); 80 | doc.body.appendChild(dom.reporter); 81 | 82 | reporterView = new jasmine.HtmlReporter.ReporterView(dom); 83 | reporterView.addSpecs(specs, self.specFilter); 84 | }; 85 | 86 | self.reportRunnerResults = function(runner) { 87 | reporterView && reporterView.complete(); 88 | }; 89 | 90 | self.reportSuiteResults = function(suite) { 91 | reporterView.suiteComplete(suite); 92 | }; 93 | 94 | self.reportSpecStarting = function(spec) { 95 | if (self.logRunningSpecs) { 96 | self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); 97 | } 98 | }; 99 | 100 | self.reportSpecResults = function(spec) { 101 | reporterView.specComplete(spec); 102 | }; 103 | 104 | self.log = function() { 105 | var console = jasmine.getGlobal().console; 106 | if (console && console.log) { 107 | if (console.log.apply) { 108 | console.log.apply(console, arguments); 109 | } else { 110 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie 111 | } 112 | } 113 | }; 114 | 115 | self.specFilter = function(spec) { 116 | if (!focusedSpecName()) { 117 | return true; 118 | } 119 | 120 | return spec.getFullName().indexOf(focusedSpecName()) === 0; 121 | }; 122 | 123 | return self; 124 | 125 | function focusedSpecName() { 126 | var specName; 127 | 128 | (function memoizeFocusedSpec() { 129 | if (specName) { 130 | return; 131 | } 132 | 133 | var paramMap = []; 134 | var params = doc.location.search.substring(1).split('&'); 135 | 136 | for (var i = 0; i < params.length; i++) { 137 | var p = params[i].split('='); 138 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); 139 | } 140 | 141 | specName = paramMap.spec; 142 | })(); 143 | 144 | return specName; 145 | } 146 | 147 | function createReporterDom(version) { 148 | dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, 149 | dom.banner = self.createDom('div', { className: 'banner' }, 150 | self.createDom('span', { className: 'title' }, "Jasmine "), 151 | self.createDom('span', { className: 'version' }, version)), 152 | 153 | dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), 154 | dom.alert = self.createDom('div', {className: 'alert'}), 155 | dom.results = self.createDom('div', {className: 'results'}, 156 | dom.summary = self.createDom('div', { className: 'summary' }), 157 | dom.details = self.createDom('div', { id: 'details' })) 158 | ); 159 | } 160 | }; 161 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) { 162 | this.startedAt = new Date(); 163 | this.runningSpecCount = 0; 164 | this.completeSpecCount = 0; 165 | this.passedCount = 0; 166 | this.failedCount = 0; 167 | this.skippedCount = 0; 168 | 169 | this.createResultsMenu = function() { 170 | this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, 171 | this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), 172 | ' | ', 173 | this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); 174 | 175 | this.summaryMenuItem.onclick = function() { 176 | dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); 177 | }; 178 | 179 | this.detailsMenuItem.onclick = function() { 180 | showDetails(); 181 | }; 182 | }; 183 | 184 | this.addSpecs = function(specs, specFilter) { 185 | this.totalSpecCount = specs.length; 186 | 187 | this.views = { 188 | specs: {}, 189 | suites: {} 190 | }; 191 | 192 | for (var i = 0; i < specs.length; i++) { 193 | var spec = specs[i]; 194 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); 195 | if (specFilter(spec)) { 196 | this.runningSpecCount++; 197 | } 198 | } 199 | }; 200 | 201 | this.specComplete = function(spec) { 202 | this.completeSpecCount++; 203 | 204 | if (isUndefined(this.views.specs[spec.id])) { 205 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); 206 | } 207 | 208 | var specView = this.views.specs[spec.id]; 209 | 210 | switch (specView.status()) { 211 | case 'passed': 212 | this.passedCount++; 213 | break; 214 | 215 | case 'failed': 216 | this.failedCount++; 217 | break; 218 | 219 | case 'skipped': 220 | this.skippedCount++; 221 | break; 222 | } 223 | 224 | specView.refresh(); 225 | this.refresh(); 226 | }; 227 | 228 | this.suiteComplete = function(suite) { 229 | var suiteView = this.views.suites[suite.id]; 230 | if (isUndefined(suiteView)) { 231 | return; 232 | } 233 | suiteView.refresh(); 234 | }; 235 | 236 | this.refresh = function() { 237 | 238 | if (isUndefined(this.resultsMenu)) { 239 | this.createResultsMenu(); 240 | } 241 | 242 | // currently running UI 243 | if (isUndefined(this.runningAlert)) { 244 | this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"}); 245 | dom.alert.appendChild(this.runningAlert); 246 | } 247 | this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); 248 | 249 | // skipped specs UI 250 | if (isUndefined(this.skippedAlert)) { 251 | this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"}); 252 | } 253 | 254 | this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; 255 | 256 | if (this.skippedCount === 1 && isDefined(dom.alert)) { 257 | dom.alert.appendChild(this.skippedAlert); 258 | } 259 | 260 | // passing specs UI 261 | if (isUndefined(this.passedAlert)) { 262 | this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"}); 263 | } 264 | this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); 265 | 266 | // failing specs UI 267 | if (isUndefined(this.failedAlert)) { 268 | this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); 269 | } 270 | this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); 271 | 272 | if (this.failedCount === 1 && isDefined(dom.alert)) { 273 | dom.alert.appendChild(this.failedAlert); 274 | dom.alert.appendChild(this.resultsMenu); 275 | } 276 | 277 | // summary info 278 | this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); 279 | this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; 280 | }; 281 | 282 | this.complete = function() { 283 | dom.alert.removeChild(this.runningAlert); 284 | 285 | this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; 286 | 287 | if (this.failedCount === 0) { 288 | dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); 289 | } else { 290 | showDetails(); 291 | } 292 | 293 | dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); 294 | }; 295 | 296 | return this; 297 | 298 | function showDetails() { 299 | if (dom.reporter.className.search(/showDetails/) === -1) { 300 | dom.reporter.className += " showDetails"; 301 | } 302 | } 303 | 304 | function isUndefined(obj) { 305 | return typeof obj === 'undefined'; 306 | } 307 | 308 | function isDefined(obj) { 309 | return !isUndefined(obj); 310 | } 311 | 312 | function specPluralizedFor(count) { 313 | var str = count + " spec"; 314 | if (count > 1) { 315 | str += "s" 316 | } 317 | return str; 318 | } 319 | 320 | }; 321 | 322 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); 323 | 324 | 325 | jasmine.HtmlReporter.SpecView = function(spec, dom, views) { 326 | this.spec = spec; 327 | this.dom = dom; 328 | this.views = views; 329 | 330 | this.symbol = this.createDom('li', { className: 'pending' }); 331 | this.dom.symbolSummary.appendChild(this.symbol); 332 | 333 | this.summary = this.createDom('div', { className: 'specSummary' }, 334 | this.createDom('a', { 335 | className: 'description', 336 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()), 337 | title: this.spec.getFullName() 338 | }, this.spec.description) 339 | ); 340 | 341 | this.detail = this.createDom('div', { className: 'specDetail' }, 342 | this.createDom('a', { 343 | className: 'description', 344 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()), 345 | title: this.spec.getFullName() 346 | }, this.spec.getFullName()) 347 | ); 348 | }; 349 | 350 | jasmine.HtmlReporter.SpecView.prototype.status = function() { 351 | return this.getSpecStatus(this.spec); 352 | }; 353 | 354 | jasmine.HtmlReporter.SpecView.prototype.refresh = function() { 355 | this.symbol.className = this.status(); 356 | 357 | switch (this.status()) { 358 | case 'skipped': 359 | break; 360 | 361 | case 'passed': 362 | this.appendSummaryToSuiteDiv(); 363 | break; 364 | 365 | case 'failed': 366 | this.appendSummaryToSuiteDiv(); 367 | this.appendFailureDetail(); 368 | break; 369 | } 370 | }; 371 | 372 | jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { 373 | this.summary.className += ' ' + this.status(); 374 | this.appendToSummary(this.spec, this.summary); 375 | }; 376 | 377 | jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { 378 | this.detail.className += ' ' + this.status(); 379 | 380 | var resultItems = this.spec.results().getItems(); 381 | var messagesDiv = this.createDom('div', { className: 'messages' }); 382 | 383 | for (var i = 0; i < resultItems.length; i++) { 384 | var result = resultItems[i]; 385 | 386 | if (result.type == 'log') { 387 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); 388 | } else if (result.type == 'expect' && result.passed && !result.passed()) { 389 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); 390 | 391 | if (result.trace.stack) { 392 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); 393 | } 394 | } 395 | } 396 | 397 | if (messagesDiv.childNodes.length > 0) { 398 | this.detail.appendChild(messagesDiv); 399 | this.dom.details.appendChild(this.detail); 400 | } 401 | }; 402 | 403 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { 404 | this.suite = suite; 405 | this.dom = dom; 406 | this.views = views; 407 | 408 | this.element = this.createDom('div', { className: 'suite' }, 409 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description) 410 | ); 411 | 412 | this.appendToSummary(this.suite, this.element); 413 | }; 414 | 415 | jasmine.HtmlReporter.SuiteView.prototype.status = function() { 416 | return this.getSpecStatus(this.suite); 417 | }; 418 | 419 | jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { 420 | this.element.className += " " + this.status(); 421 | }; 422 | 423 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); 424 | 425 | /* @deprecated Use jasmine.HtmlReporter instead 426 | */ 427 | jasmine.TrivialReporter = function(doc) { 428 | this.document = doc || document; 429 | this.suiteDivs = {}; 430 | this.logRunningSpecs = false; 431 | }; 432 | 433 | jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { 434 | var el = document.createElement(type); 435 | 436 | for (var i = 2; i < arguments.length; i++) { 437 | var child = arguments[i]; 438 | 439 | if (typeof child === 'string') { 440 | el.appendChild(document.createTextNode(child)); 441 | } else { 442 | if (child) { el.appendChild(child); } 443 | } 444 | } 445 | 446 | for (var attr in attrs) { 447 | if (attr == "className") { 448 | el[attr] = attrs[attr]; 449 | } else { 450 | el.setAttribute(attr, attrs[attr]); 451 | } 452 | } 453 | 454 | return el; 455 | }; 456 | 457 | jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { 458 | var showPassed, showSkipped; 459 | 460 | this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, 461 | this.createDom('div', { className: 'banner' }, 462 | this.createDom('div', { className: 'logo' }, 463 | this.createDom('span', { className: 'title' }, "Jasmine"), 464 | this.createDom('span', { className: 'version' }, runner.env.versionString())), 465 | this.createDom('div', { className: 'options' }, 466 | "Show ", 467 | showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), 468 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), 469 | showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), 470 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") 471 | ) 472 | ), 473 | 474 | this.runnerDiv = this.createDom('div', { className: 'runner running' }, 475 | this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), 476 | this.runnerMessageSpan = this.createDom('span', {}, "Running..."), 477 | this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) 478 | ); 479 | 480 | this.document.body.appendChild(this.outerDiv); 481 | 482 | var suites = runner.suites(); 483 | for (var i = 0; i < suites.length; i++) { 484 | var suite = suites[i]; 485 | var suiteDiv = this.createDom('div', { className: 'suite' }, 486 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), 487 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); 488 | this.suiteDivs[suite.id] = suiteDiv; 489 | var parentDiv = this.outerDiv; 490 | if (suite.parentSuite) { 491 | parentDiv = this.suiteDivs[suite.parentSuite.id]; 492 | } 493 | parentDiv.appendChild(suiteDiv); 494 | } 495 | 496 | this.startedAt = new Date(); 497 | 498 | var self = this; 499 | showPassed.onclick = function(evt) { 500 | if (showPassed.checked) { 501 | self.outerDiv.className += ' show-passed'; 502 | } else { 503 | self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); 504 | } 505 | }; 506 | 507 | showSkipped.onclick = function(evt) { 508 | if (showSkipped.checked) { 509 | self.outerDiv.className += ' show-skipped'; 510 | } else { 511 | self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); 512 | } 513 | }; 514 | }; 515 | 516 | jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { 517 | var results = runner.results(); 518 | var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; 519 | this.runnerDiv.setAttribute("class", className); 520 | //do it twice for IE 521 | this.runnerDiv.setAttribute("className", className); 522 | var specs = runner.specs(); 523 | var specCount = 0; 524 | for (var i = 0; i < specs.length; i++) { 525 | if (this.specFilter(specs[i])) { 526 | specCount++; 527 | } 528 | } 529 | var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); 530 | message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; 531 | this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); 532 | 533 | this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); 534 | }; 535 | 536 | jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { 537 | var results = suite.results(); 538 | var status = results.passed() ? 'passed' : 'failed'; 539 | if (results.totalCount === 0) { // todo: change this to check results.skipped 540 | status = 'skipped'; 541 | } 542 | this.suiteDivs[suite.id].className += " " + status; 543 | }; 544 | 545 | jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { 546 | if (this.logRunningSpecs) { 547 | this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); 548 | } 549 | }; 550 | 551 | jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { 552 | var results = spec.results(); 553 | var status = results.passed() ? 'passed' : 'failed'; 554 | if (results.skipped) { 555 | status = 'skipped'; 556 | } 557 | var specDiv = this.createDom('div', { className: 'spec ' + status }, 558 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), 559 | this.createDom('a', { 560 | className: 'description', 561 | href: '?spec=' + encodeURIComponent(spec.getFullName()), 562 | title: spec.getFullName() 563 | }, spec.description)); 564 | 565 | 566 | var resultItems = results.getItems(); 567 | var messagesDiv = this.createDom('div', { className: 'messages' }); 568 | for (var i = 0; i < resultItems.length; i++) { 569 | var result = resultItems[i]; 570 | 571 | if (result.type == 'log') { 572 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); 573 | } else if (result.type == 'expect' && result.passed && !result.passed()) { 574 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); 575 | 576 | if (result.trace.stack) { 577 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); 578 | } 579 | } 580 | } 581 | 582 | if (messagesDiv.childNodes.length > 0) { 583 | specDiv.appendChild(messagesDiv); 584 | } 585 | 586 | this.suiteDivs[spec.suite.id].appendChild(specDiv); 587 | }; 588 | 589 | jasmine.TrivialReporter.prototype.log = function() { 590 | var console = jasmine.getGlobal().console; 591 | if (console && console.log) { 592 | if (console.log.apply) { 593 | console.log.apply(console, arguments); 594 | } else { 595 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie 596 | } 597 | } 598 | }; 599 | 600 | jasmine.TrivialReporter.prototype.getLocation = function() { 601 | return this.document.location; 602 | }; 603 | 604 | jasmine.TrivialReporter.prototype.specFilter = function(spec) { 605 | var paramMap = {}; 606 | var params = this.getLocation().search.substring(1).split('&'); 607 | for (var i = 0; i < params.length; i++) { 608 | var p = params[i].split('='); 609 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); 610 | } 611 | 612 | if (!paramMap.spec) { 613 | return true; 614 | } 615 | return spec.getFullName().indexOf(paramMap.spec) === 0; 616 | }; 617 | -------------------------------------------------------------------------------- /www/spec/lib/jasmine-1.2.0/jasmine.css: -------------------------------------------------------------------------------- 1 | body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } 2 | 3 | #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } 4 | #HTMLReporter a { text-decoration: none; } 5 | #HTMLReporter a:hover { text-decoration: underline; } 6 | #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } 7 | #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } 8 | #HTMLReporter #jasmine_content { position: fixed; right: 100%; } 9 | #HTMLReporter .version { color: #aaaaaa; } 10 | #HTMLReporter .banner { margin-top: 14px; } 11 | #HTMLReporter .duration { color: #aaaaaa; float: right; } 12 | #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } 13 | #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } 14 | #HTMLReporter .symbolSummary li.passed { font-size: 14px; } 15 | #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } 16 | #HTMLReporter .symbolSummary li.failed { line-height: 9px; } 17 | #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } 18 | #HTMLReporter .symbolSummary li.skipped { font-size: 14px; } 19 | #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } 20 | #HTMLReporter .symbolSummary li.pending { line-height: 11px; } 21 | #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } 22 | #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 23 | #HTMLReporter .runningAlert { background-color: #666666; } 24 | #HTMLReporter .skippedAlert { background-color: #aaaaaa; } 25 | #HTMLReporter .skippedAlert:first-child { background-color: #333333; } 26 | #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } 27 | #HTMLReporter .passingAlert { background-color: #a6b779; } 28 | #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } 29 | #HTMLReporter .failingAlert { background-color: #cf867e; } 30 | #HTMLReporter .failingAlert:first-child { background-color: #b03911; } 31 | #HTMLReporter .results { margin-top: 14px; } 32 | #HTMLReporter #details { display: none; } 33 | #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } 34 | #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } 35 | #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } 36 | #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } 37 | #HTMLReporter.showDetails .summary { display: none; } 38 | #HTMLReporter.showDetails #details { display: block; } 39 | #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } 40 | #HTMLReporter .summary { margin-top: 14px; } 41 | #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } 42 | #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } 43 | #HTMLReporter .summary .specSummary.failed a { color: #b03911; } 44 | #HTMLReporter .description + .suite { margin-top: 0; } 45 | #HTMLReporter .suite { margin-top: 14px; } 46 | #HTMLReporter .suite a { color: #333333; } 47 | #HTMLReporter #details .specDetail { margin-bottom: 28px; } 48 | #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } 49 | #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } 50 | #HTMLReporter .resultMessage span.result { display: block; } 51 | #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } 52 | 53 | #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } 54 | #TrivialReporter a:visited, #TrivialReporter a { color: #303; } 55 | #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } 56 | #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } 57 | #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } 58 | #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } 59 | #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } 60 | #TrivialReporter .runner.running { background-color: yellow; } 61 | #TrivialReporter .options { text-align: right; font-size: .8em; } 62 | #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } 63 | #TrivialReporter .suite .suite { margin: 5px; } 64 | #TrivialReporter .suite.passed { background-color: #dfd; } 65 | #TrivialReporter .suite.failed { background-color: #fdd; } 66 | #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } 67 | #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } 68 | #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } 69 | #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } 70 | #TrivialReporter .spec.skipped { background-color: #bbb; } 71 | #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } 72 | #TrivialReporter .passed { background-color: #cfc; display: none; } 73 | #TrivialReporter .failed { background-color: #fbb; } 74 | #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } 75 | #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } 76 | #TrivialReporter .resultMessage .mismatch { color: black; } 77 | #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } 78 | #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } 79 | #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } 80 | #TrivialReporter #jasmine_content { position: fixed; right: 100%; } 81 | #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } 82 | -------------------------------------------------------------------------------- /www/templates/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | This is a sample seed project for the Ionic Framework. Please cut it up and make it your own. Check out the 6 | docs 7 | for more info. 8 |

9 |

10 | Questions? Hit up the 11 | forum. 12 |

13 |

14 | Find a bug? Create an 15 | issue. 16 |

17 |

18 | What to help improve Ionic? 19 | Contribute. 20 |

21 |

22 | Stay up-to-date with the Ionic 23 | newsletterand 24 | twitteraccount. 25 |

26 |

27 | MIT Licensed. Happy coding. 28 |

29 |

30 |

Angular seed app: v 31 | 32 |
33 |

34 |

35 | Showing of 'interpolate' filter: {{ 'Current version is v%VERSION%.' | interpolate }} 36 |

37 |
38 |
39 | -------------------------------------------------------------------------------- /www/templates/adopt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 8 | 12 | Subscribe To Newsletter 13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /www/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 9 | 13 |
14 | 15 |
16 | 17 |
18 | 21 |
22 | 23 |
24 | 25 |
26 |
-------------------------------------------------------------------------------- /www/templates/pet-detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

{{ pet.description }}

4 |

5 | All Pets 6 |

7 |
8 |
9 | -------------------------------------------------------------------------------- /www/templates/pet-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

{{pet.title}}

8 |

{{pet.description}}

9 |
10 | 11 |
12 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /www/templates/tabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | --------------------------------------------------------------------------------