├── .gitignore ├── README.md ├── config.xml ├── css ├── index.css ├── topcoat-mobile-dark.min.css └── topcoat-mobile-light.min.css ├── font ├── LICENSE.txt ├── SourceCodePro-Black.otf ├── SourceCodePro-Bold.otf ├── SourceCodePro-ExtraLight.otf ├── SourceCodePro-Light.otf ├── SourceCodePro-Regular.otf ├── SourceCodePro-Semibold.otf ├── SourceSansPro-Black.otf ├── SourceSansPro-BlackIt.otf ├── SourceSansPro-Bold.otf ├── SourceSansPro-BoldIt.otf ├── SourceSansPro-ExtraLight.otf ├── SourceSansPro-ExtraLightIt.otf ├── SourceSansPro-It.otf ├── SourceSansPro-Light.otf ├── SourceSansPro-LightIt.otf ├── SourceSansPro-Regular.otf ├── SourceSansPro-Semibold.otf └── SourceSansPro-SemiboldIt.otf ├── icon.png ├── img ├── bg_dark.png ├── breadcrumb.png ├── camera-highlight.svg ├── camera.svg ├── checkbox_checked.png ├── checkbox_checked_dark.png ├── checkbox_unchecked.png ├── checkbox_unchecked_dark.png ├── checkmark_bw.svg ├── dark-combo-box-bg.png ├── dark-combo-box-bg2x.png ├── dark-grips.png ├── dark-sprites2x.png ├── drop-down-triangle-dark.png ├── drop-down-triangle.png ├── hamburger_bw.svg ├── hamburger_dark.svg ├── hamburger_light.svg ├── light-combo-box-bg.png ├── light-combo-box-bg2x.png ├── light-grips.png ├── light-sprites2x.png ├── pop-up-triangle-dark.png ├── pop-up-triangle.png ├── search-bg.png ├── search-bg2x.png ├── search.svg ├── search_bw.svg ├── search_dark.svg ├── search_light.svg ├── spinner.png └── spinner2x.png ├── index.html ├── js ├── index.js ├── modules.js ├── phonegap.facebook.inappbrowser.js ├── zepto.min.js └── zepto.touch.js ├── modules.sh ├── res ├── icon │ ├── android │ │ ├── drawable-hdpi-icon.png │ │ ├── drawable-ldpi-icon.png │ │ ├── drawable-mdpi-icon.png │ │ ├── drawable-xhdpi-icon.png │ │ ├── drawable-xxhdpi-icon.png │ │ └── drawable-xxxhdpi-icon.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 │ ├── drawable-land-hdpi-screen.png │ ├── drawable-land-ldpi-screen.png │ ├── drawable-land-mdpi-screen.png │ ├── drawable-land-xhdpi-screen.png │ ├── drawable-land-xxhdpi-screen.png │ ├── drawable-land-xxxhdpi-screen.png │ ├── drawable-port-hdpi-screen.png │ ├── drawable-port-ldpi-screen.png │ ├── drawable-port-mdpi-screen.png │ ├── drawable-port-xhdpi-screen.png │ ├── drawable-port-xxhdpi-screen.png │ ├── drawable-port-xxxhdpi-screen.png │ ├── 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 ├── serve.sh └── sync-gateway-config.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store* 2 | Thumbs.db* 3 | ~* 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⚠️ This repo is obsolete. It was built against a version of Couchbase Lite that reached end of life years ago. 2 | 3 | # Todo Lite 4 | 5 | A shared todo list application to demonstrate the features of [Couchbase Lite](http://github.com/couchbase/mobile). 6 | 7 | ## Install 8 | 9 | To run this application, you'll need the Xcode developer package, or the Android SDK, and the PhoneGap toolchain. 10 | 11 | First create an empty PhoneGap app container using the [PhoneGap npm package](https://npmjs.org/package/phonegap). 12 | 13 | ```sh 14 | npm install -g phonegap 15 | phonegap create todo-lite com.couchbase.TodoLite TodoLite 16 | cd todo-lite 17 | ``` 18 | 19 | Now install the PhoneGap plugins required to make it run. This activates Couchbase Lite, the camera, and the InAppBrowser. 20 | 21 | ```sh 22 | phonegap plugin add https://github.com/couchbaselabs/Couchbase-Lite-PhoneGap-Plugin.git 23 | phonegap plugin add cordova-plugin-camera 24 | phonegap plugin add https://github.com/apache/cordova-plugin-inappbrowser.git 25 | phonegap plugin add cordova-plugin-network-information 26 | ``` 27 | 28 | If you're using PhoneGap 5.0 or higher, you'll also need to install the Apache Cordova whitelist plugin to communicate with external services: 29 | 30 | ```sh 31 | phonegap local plugin add cordova-plugin-whitelist 32 | ``` 33 | 34 | Now replace the generated application with the Todo Lite source code. 35 | 36 | ```sh 37 | rm -rf www 38 | git clone https://github.com/couchbaselabs/TodoLite-PhoneGap.git www 39 | ``` 40 | 41 | That's it, now you are ready to run the app: 42 | 43 | ```sh 44 | phonegap run ios 45 | ``` 46 | 47 | or 48 | 49 | ```sh 50 | phonegap run android 51 | ``` 52 | 53 | This will launch the app in your iOS or Android Simulator. If you want to launch the app on an iOS device, open the project in Xcode. From the project directory, you can run: 54 | 55 | ```sh 56 | open platforms/ios/TodoLite.xcodeproj/ 57 | ``` 58 | 59 | Do note that the Xcode project is only updated by the `phonegap` command line tool, so you must run `phonegap run ios` or `phonegap build ios` before it will pick up any changes made in the `www` directory. 60 | 61 | At compile time, you may run into the following error message for Android: 62 | 63 | ``` 64 | Error: duplicate files during packaging of APK 65 | ``` 66 | 67 | To resolve this, you must extend the Gradle build file for Android as outlined in the official [Apache Cordova documentation](https://cordova.apache.org/docs/en/5.0.0/guide_platforms_android_tools.md.html). 68 | 69 | Create **platforms/android/build-extras.gradle** in your project and add the following: 70 | 71 | ``` 72 | // workaround for "duplicate files during packaging of APK" issue 73 | // see https://groups.google.com/d/msg/adt-dev/bl5Rc4Szpzg/wC8cylTWuIEJ 74 | android { 75 | packagingOptions { 76 | exclude 'META-INF/ASL2.0' 77 | exclude 'META-INF/LICENSE' 78 | exclude 'META-INF/NOTICE' 79 | } 80 | } 81 | ``` 82 | 83 | #### Troubleshoot Latest PhoneGap 6.x on Android 84 | 85 | By launching app by `phonegap run android`, phonegap could fail with printing following message. 86 | ``` 87 | Error: Could not find gradle wrapper within Android SDK. Might need to update your Android SDK. 88 | Looked here: /Users/hideki/java/android-sdk-macosx/tools/templates/gradle/wrapper 89 | ``` 90 | 91 | solution: 92 | 1. update Phonegap android plugin 93 | ``` 94 | phonegap platform rm android 95 | phonegap platform add android@latest 96 | ``` 97 | 2. Update gradle version in `build.gradle` files. Both top level and application level build.gradle file 98 | ``` 99 | dependencies { 100 | classpath 'com.android.tools.build:gradle:2.3.3' 101 | ... 102 | } 103 | ``` 104 | 105 | ## Running your own Sync Gateway server 106 | 107 | In `www/js/index.js` there is a value for `syncUrl` which is set to a remote server hosted by Couchbase as a convenience. You can easily provision your own server either by running your own instance of [Couchbase Sync Gateway](https://github.com/couchbase/sync_gateway) or by creating a server in [the experimental Couchbase cloud.](http://console.couchbasecloud.com/) 108 | 109 | If you are running your own server, launch it by pointing it at the `sync-gateway-config.json` that is shipped as part of this repository. If you are launching a Sync Gateway instance in the cloud, the only configuration you'll need to provide is to copy the sync function from that JSON file into the web UI. 110 | 111 | ## Release Notes / TODO 112 | 113 | * Currently support for Android is limited by a few minor API compatiblity issues. These are probably fixed by the time you are reading this. 114 | * Redraw flash should be avoided. This is especially apparent on long lists. 115 | * Lists are too wide in portrait mode on iPad 116 | * The app won't detect if you get logged out (cookie expires) -- need testing. 117 | 118 | ## Community 119 | 120 | If you got this far, please [join our mailing list](https://groups.google.com/forum/#!forum/mobile-couchbase) and let us know how it went. Or just [send a tweet.](https://twitter.com/intent/tweet?text=I'm%20using%20@Couchbase%20Lite%20with%20@PhoneGap) 121 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | TodoLite 4 | 5 | Hello World sample application that responds to the deviceready event. 6 | 7 | 8 | PhoneGap Team 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 | -------------------------------------------------------------------------------- /css/index.css: -------------------------------------------------------------------------------- 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 | 20 | body { 21 | /*font-size:200%;*/ 22 | } 23 | 24 | header { 25 | position: fixed; 26 | top: 0; 27 | left: 0; 28 | width: 100%; 29 | z-index: 100; 30 | } 31 | 32 | #scrollable { 33 | margin-top:8rem; 34 | } 35 | 36 | form { 37 | padding:8px; 38 | } 39 | 40 | form input { 41 | width:100%; 42 | } 43 | 44 | .camera { 45 | background: transparent url(../img/camera.svg); 46 | background-repeat: no-repeat; 47 | background-size: contain; 48 | width: 30px; 49 | height: 30px; 50 | position:absolute; 51 | right:1rem; 52 | } 53 | 54 | .camera.image { 55 | background: transparent url(../img/camera-highlight.svg); 56 | } 57 | 58 | .todo-list-name { 59 | text-overflow: ellipsis; 60 | overflow: hidden; 61 | white-space: nowrap; 62 | } 63 | 64 | img.todo-image { 65 | width: 100%; 66 | } 67 | 68 | label.todo-list-item { 69 | width: -webkit-calc(100% - 30px); 70 | text-overflow: ellipsis; 71 | overflow: hidden; 72 | white-space: nowrap; 73 | float:left; 74 | } 75 | 76 | br.clear { 77 | height: 0; 78 | clear: both; 79 | } 80 | 81 | .topcoat-button.todo-small { 82 | line-height: 2rem; 83 | padding: 0 0.6rem 2px 0.6rem; 84 | font-size: 28px; 85 | letter-spacing: 0; 86 | } 87 | 88 | .topcoat-navigation-bar__item.todo-padded { 89 | padding-top:1rem; 90 | } 91 | 92 | .topcoat-button.todo-delete { 93 | position:absolute; 94 | right:1rem; 95 | line-height: 2rem; 96 | display:none; 97 | } 98 | 99 | .topcoat-button.todo-login { 100 | display:none; 101 | } 102 | 103 | .topcoat-navigation-bar__title.todo-unbold { 104 | font-weight: 100; 105 | } 106 | 107 | 108 | -------------------------------------------------------------------------------- /css/topcoat-mobile-dark.min.css: -------------------------------------------------------------------------------- 1 | .button{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.button--disabled{opacity:.3;cursor:default;pointer-events:none}.button,.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.button--disabled,.topcoat-button:disabled,.topcoat-button.is-disabled,.topcoat-button--quiet:disabled,.topcoat-button--quiet.is-disabled,.topcoat-button--large:disabled,.topcoat-button--large.is-disabled,.topcoat-button--large--quiet:disabled,.topcoat-button--large--quiet.is-disabled,.topcoat-button--cta:disabled,.topcoat-button--cta.is-disabled,.topcoat-button--large-cta:disabled,.topcoat-button--large--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{padding:0 1.25rem;font-size:16px;line-height:3rem;letter-spacing:1px;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);vertical-align:top;background-color:#595b5b;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.12);box-shadow:inset 0 1px rgba(255,255,255,.12);border:1px solid rgba(0,0,0,.36);-webkit-border-radius:6px;border-radius:6px}.topcoat-button:active,.topcoat-button.is-active,.topcoat-button--large:active,.topcoat-button--large.is-active{background-color:#404141;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.18);box-shadow:inset 0 1px rgba(0,0,0,.18)}.topcoat-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--quiet:active,.topcoat-button--quiet.is-active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet.is-active{color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);background-color:#404141;border:1px solid rgba(0,0,0,.36);-webkit-box-shadow:inset 0 1px rgba(0,0,0,.18);box-shadow:inset 0 1px rgba(0,0,0,.18)}.topcoat-button--large,.topcoat-button--large--quiet{font-size:1.3rem;line-height:4rem}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #143250;background-color:#288edf;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.36);box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:active,.topcoat-button--cta.is-active,.topcoat-button--large--cta:active,.topcoat-button--large--cta.is-active{background-color:#1976c3;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--large--cta{font-size:1.3rem;line-height:4rem}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after{content:'';position:absolute}.checkbox:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox,.topcoat-checkbox{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label,.topcoat-checkbox__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled,.topcoat-checkbox__label:disabled,.topcoat-checkbox__label.is-disabled{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after,.topcoat-checkbox:before,.topcoat-checkbox:after{content:'';position:absolute}.checkbox:before,.topcoat-checkbox:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.topcoat-checkbox{height:2rem}input[type=checkbox]{height:2rem;width:2rem;margin-top:0;margin-right:-2rem;margin-bottom:-2rem;margin-left:0}input[type=checkbox]:checked+.topcoat-checkbox:after,.topcoat-checkbox__label.is-active>.topcoat-checkbox:after{opacity:1}.topcoat-checkbox__label{line-height:2rem}.topcoat-checkbox:before{width:2rem;height:2rem;background:#595b5b;border:1px solid rgba(0,0,0,.36);-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.12);box-shadow:inset 0 1px rgba(255,255,255,.12)}.topcoat-checkbox{width:2rem;height:2rem}.topcoat-checkbox:after{top:0;opacity:0;width:28px;height:11px;background:transparent;border:7px solid #fff;border-width:7px;border-top:0;border-right:0;-webkit-border-radius:2px;border-radius:2px;-webkit-transform:rotate(-50deg);-moz-transform:rotate(-50deg);-o-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg)}input[type=checkbox]:focus+.topcoat-checkbox:before,.topcoat-checkbox__label.is-focused>.topcoat-checkbox:before{border:1px solid #0940fd;-webkit-box-shadow:0 0 0 2px #6fb5f1;box-shadow:0 0 0 2px #6fb5f1}.input{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0}.list-container{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch}.list{padding:0;margin:0;list-style-type:none}.list-item{margin:0;padding:0}.topcoat-list__container{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch;border-top:1px solid #2f3234;border-bottom:1px solid #eff1f1;background-color:#444849}.topcoat-list__header{margin:0;padding:4px 20px;font-size:.9em;font-weight:400;background-color:#3b3e40;color:#868888;text-shadow:0 -1px 0 rgba(0,0,0,.3);border-top:solid 1px rgba(255,255,255,.1);border-bottom:solid 1px rgba(255,255,255,.05)}.topcoat-list{padding:0;margin:0;list-style-type:none;border-top:1px solid #2f3234;color:#c6c8c8}.topcoat-list__item{margin:0;padding:0;padding:1.25rem;border-top:1px solid #5e6061;border-bottom:1px solid #2f3234}.topcoat-list__item:first-child{border-top:1px solid rgba(0,0,0,.05)}.navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:nowrap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0}.navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.topcoat-navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:nowrap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;height:4rem;padding-left:1rem;padding-right:1rem;background:#595b5b;color:#fff;-webkit-box-shadow:inset 0 -1px #333434,0 1px rgba(0,0,0,.15);box-shadow:inset 0 -1px #333434,0 1px rgba(0,0,0,.15)}.topcoat-navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;margin:0;line-height:4rem;vertical-align:top}.topcoat-navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:1.3rem;font-weight:400;color:#fff}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after{content:'';position:absolute;-webkit-border-radius:100%;border-radius:100%}.radio-button:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.radio-button--disabled{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button,.topcoat-radio-button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label,.topcoat-radio-button__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after,.topcoat-radio-button:before,.topcoat-radio-button:after{content:'';position:absolute;-webkit-border-radius:100%;border-radius:100%}.radio-button:after,.topcoat-radio-button:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before,.topcoat-radio-button:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.radio-button--disabled,.topcoat-radio-button__label:disabled,.topcoat-radio-button__label.is-disabled{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{height:2rem;width:2rem;margin-top:0;margin-right:-2rem;margin-bottom:-2rem;margin-left:0}input[type=radio]:checked+.topcoat-radio-button:after{opacity:1}.topcoat-radio-button__label{color:#c6c8c8;line-height:2rem}.topcoat-radio-button:before{width:2rem;height:2rem;background:#595b5b;border:1px solid rgba(0,0,0,.36);-webkit-box-shadow:inset 0 1px rgba(255,255,255,.12);box-shadow:inset 0 1px rgba(255,255,255,.12)}.topcoat-radio-button{position:relative;width:2rem;height:2rem}.topcoat-radio-button:after{opacity:0;width:1rem;height:1rem;background:#fff;border:1px solid rgba(255,255,255,.1);-webkit-box-shadow:0 1px rgba(255,255,255,.5);box-shadow:0 1px rgba(255,255,255,.5)}input[type=radio]:focus+.topcoat-radio-button:before,.topcoat-radio-button__label.is-focused>.topcoat-radio-button:before{border:1px solid #0940fd;-webkit-box-shadow:0 0 0 2px #6fb5f1;box-shadow:0 0 0 2px #6fb5f1}.topcoat-search-input,.topcoat-search-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0;height:3rem;border:1px solid rgba(0,0,0,.36);background-color:#595b5b;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.18);box-shadow:inset 0 1px rgba(0,0,0,.18);color:#c6c8c8;-webkit-appearance:none;padding:0 0 0 2.7em;-webkit-border-radius:30px;border-radius:30px;background-image:url(../img/search_light.svg);background-position:1em center;background-repeat:no-repeat;-webkit-background-size:16px;-moz-background-size:16px;background-size:16px}.topcoat-search-input:focus,.topcoat-search-input--large:focus{background-color:#fff;color:#000}.topcoat-search-input::-webkit-search-cancel-button,.topcoat-search-input::-webkit-search-decoration{margin-right:5px}.topcoat-search-input:focus::-webkit-input-placeholder,.topcoat-search-input:focus::-webkit-input-placeholder{color:#c6c8c8}.topcoat-search-input:disabled,.topcoat-search-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-search-input--large{height:4rem;font-size:1.3rem;font-weight:200;padding-left:2.8em;-webkit-border-radius:40px;border-radius:40px;background-position:1.2em center;-webkit-background-size:1.3rem;-moz-background-size:1.3rem;background-size:1.3rem}.topcoat-search-input--large:disabled,.topcoat-search-input--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input,.topcoat-text-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0;height:3rem;padding:0 1.25rem;border:1px solid rgba(0,0,0,.36);-webkit-border-radius:6px;border-radius:6px;background-color:#595b5b;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.18);box-shadow:inset 0 1px rgba(0,0,0,.18);color:#c6c8c8}.topcoat-text-input:focus{background-color:#fff;color:#000}.topcoat-text-input:disabled,.topcoat-text-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input--large{height:4rem;font-size:1.3rem}.topcoat-text-input--large:focus{background-color:#fff;color:#000}.topcoat-text-input--large.is-disabled,.topcoat-text-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}.textarea{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0}.topcoat-textarea,.topcoat-textarea--large{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0;padding:2rem;font-size:2.5rem;font-weight:200;-webkit-border-radius:6px;border-radius:6px;line-height:3rem;border:1px solid rgba(0,0,0,.36);background-color:#595b5b;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.18);box-shadow:inset 0 1px rgba(0,0,0,.18);color:#c6c8c8}.topcoat-textarea:focus,.topcoat-textarea--large:focus{background-color:#fff;color:#000}.topcoat-textarea--large{font-size:3rem;line-height:4rem}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Regular.otf)}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Light.otf);font-weight:200}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Semibold.otf);font-weight:600}body{margin:0;padding:0;background:#3a3f42 url(../img/bg_dark.png) repeat-x;color:#000;font:16px "Source Sans",helvetica,arial,sans-serif;font-weight:200;text-rendering:optimizeLegibility}:focus{outline-color:transparent;outline-style:none}.topcoat-icon--menu-stack{background:url(../img/hamburger_light.svg) no-repeat;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover}.quarter{width:25%}.half{width:50%}.three-quarters{width:75%}.third{width:33.333%}.two-thirds{width:66.666%}.full{width:100%}.left{text-align:left}.center{text-align:center}.right{text-align:right}.reset-ui{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden} -------------------------------------------------------------------------------- /css/topcoat-mobile-light.min.css: -------------------------------------------------------------------------------- 1 | .button{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.button--disabled{opacity:.3;cursor:default;pointer-events:none}.button,.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.button--disabled,.topcoat-button:disabled,.topcoat-button.is-disabled,.topcoat-button--quiet:disabled,.topcoat-button--quiet.is-disabled,.topcoat-button--large:disabled,.topcoat-button--large.is-disabled,.topcoat-button--large--quiet:disabled,.topcoat-button--large--quiet.is-disabled,.topcoat-button--cta:disabled,.topcoat-button--cta.is-disabled,.topcoat-button--large-cta:disabled,.topcoat-button--large--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{padding:0 1.25rem;font-size:16px;line-height:3rem;letter-spacing:1px;color:#454545;text-shadow:0 1px #fff;vertical-align:top;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px}.topcoat-button:active,.topcoat-button.is-active,.topcoat-button--large:active,.topcoat-button--large.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--quiet:active,.topcoat-button--quiet.is-active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet.is-active{color:#454545;text-shadow:0 1px #fff;background-color:#d3d7d7;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--large,.topcoat-button--large--quiet{font-size:1.3rem;line-height:4rem}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #143250;background-color:#288edf;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.36);box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:active,.topcoat-button--cta.is-active,.topcoat-button--large--cta:active,.topcoat-button--large--cta.is-active{background-color:#0380e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--large--cta{font-size:1.3rem;line-height:4rem}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after{content:'';position:absolute}.checkbox:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox,.topcoat-checkbox{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label,.topcoat-checkbox__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled,.topcoat-checkbox__label:disabled,.topcoat-checkbox__label.is-disabled{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after,.topcoat-checkbox:before,.topcoat-checkbox:after{content:'';position:absolute}.checkbox:before,.topcoat-checkbox:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.topcoat-checkbox{height:2rem}input[type=checkbox]{height:2rem;width:2rem;margin-top:0;margin-right:-2rem;margin-bottom:-2rem;margin-left:0}input[type=checkbox]:checked+.topcoat-checkbox:after,.topcoat-checkbox__label.is-active>.topcoat-checkbox:after{opacity:1}.topcoat-checkbox__label{line-height:2rem}.topcoat-checkbox:before{width:2rem;height:2rem;background:#e5e9e8;border:1px solid #a5a8a8;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff}.topcoat-checkbox{width:2rem;height:2rem}.topcoat-checkbox:after{top:0;opacity:0;width:28px;height:11px;background:transparent;border:3px solid #666;border-width:7px;border-top:0;border-right:0;-webkit-border-radius:2px;border-radius:2px;-webkit-transform:rotate(-50deg);-moz-transform:rotate(-50deg);-o-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg)}input[type=checkbox]:focus+.topcoat-checkbox:before,.topcoat-checkbox__label.is-focused>.topcoat-checkbox:before{border:1px solid #0940fd;-webkit-box-shadow:0 0 0 2px #6fb5f1;box-shadow:0 0 0 2px #6fb5f1}.input{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0}.list-container{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch}.list{padding:0;margin:0;list-style-type:none}.list-item{margin:0;padding:0}.topcoat-list__container{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch;border-top:1px solid #bcbfbf;border-bottom:1px solid #eff1f1;background-color:#dfe2e2}.topcoat-list__header{margin:0;padding:4px 20px;font-size:.9em;font-weight:400;background-color:#cccfcf;color:#656565;text-shadow:0 1px 0 rgba(255,255,255,.5);border-top:solid 1px rgba(255,255,255,.5);border-bottom:solid 1px rgba(255,255,255,.23)}.topcoat-list{padding:0;margin:0;list-style-type:none;border-top:1px solid #bcbfbf;color:#454545}.topcoat-list__item{margin:0;padding:0;padding:1.25rem;border-top:1px solid #eff1f1;border-bottom:1px solid #bcbfbf}.topcoat-list__item:first-child{border-top:1px solid rgba(0,0,0,.05)}.navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:nowrap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0}.navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.topcoat-navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:nowrap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;height:4rem;padding-left:1rem;padding-right:1rem;background:#e5e9e8;color:#000;-webkit-box-shadow:inset 0 -1px #b9bcbc,0 1px rgba(0,0,0,.95);box-shadow:inset 0 -1px #b9bcbc,0 1px rgba(0,0,0,.95)}.topcoat-navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;margin:0;line-height:4rem;vertical-align:top}.topcoat-navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:1.3rem;font-weight:400;color:#000}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after{content:'';position:absolute;-webkit-border-radius:100%;border-radius:100%}.radio-button:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.radio-button--disabled{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button,.topcoat-radio-button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label,.topcoat-radio-button__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after,.topcoat-radio-button:before,.topcoat-radio-button:after{content:'';position:absolute;-webkit-border-radius:100%;border-radius:100%}.radio-button:after,.topcoat-radio-button:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before,.topcoat-radio-button:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box}.radio-button--disabled,.topcoat-radio-button__label:disabled,.topcoat-radio-button__label.is-disabled{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{height:2rem;width:2rem;margin-top:0;margin-right:-2rem;margin-bottom:-2rem;margin-left:0}input[type=radio]:checked+.topcoat-radio-button:after{opacity:1}.topcoat-radio-button__label{color:#454545;line-height:2rem}.topcoat-radio-button:before{width:2rem;height:2rem;background:#e5e9e8;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff}.topcoat-radio-button{position:relative;width:2rem;height:2rem}.topcoat-radio-button:after{opacity:0;width:1rem;height:1rem;background:#666;border:1px solid rgba(0,0,0,.1);-webkit-box-shadow:0 1px rgba(255,255,255,.5);box-shadow:0 1px rgba(255,255,255,.5)}input[type=radio]:focus+.topcoat-radio-button:before,.topcoat-radio-button__label.is-focused>.topcoat-radio-button:before{border:1px solid #0940fd;-webkit-box-shadow:0 0 0 2px #6fb5f1;box-shadow:0 0 0 2px #6fb5f1}.topcoat-search-input,.topcoat-search-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0;height:3rem;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545;-webkit-appearance:none;padding:0 0 0 2.7em;-webkit-border-radius:30px;border-radius:30px;background-image:url(../img/search.svg);background-position:1em center;background-repeat:no-repeat;-webkit-background-size:16px;-moz-background-size:16px;background-size:16px}.topcoat-search-input:focus,.topcoat-search-input--large:focus{background-color:#fff;color:#000}.topcoat-search-input::-webkit-search-cancel-button,.topcoat-search-input::-webkit-search-decoration{margin-right:5px}.topcoat-search-input:focus::-webkit-input-placeholder,.topcoat-search-input:focus::-webkit-input-placeholder{color:#c6c8c8}.topcoat-search-input:disabled,.topcoat-search-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-search-input--large{height:4rem;font-size:1.3rem;font-weight:200;padding-left:2.8em;-webkit-border-radius:40px;border-radius:40px;background-position:1.2em center;-webkit-background-size:1.3rem;-moz-background-size:1.3rem;background-size:1.3rem}.topcoat-search-input--large:disabled,.topcoat-search-input--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input,.topcoat-text-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;vertical-align:top;outline:0;height:3rem;padding:0 1.25rem;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545}.topcoat-text-input:focus{background-color:#fff;color:#000}.topcoat-text-input:disabled,.topcoat-text-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input--large{height:4rem;font-size:1.3rem}.topcoat-text-input--large:focus{background-color:#fff;color:#000}.topcoat-text-input--large.is-disabled,.topcoat-text-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}.textarea{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0}.topcoat-textarea,.topcoat-textarea--large{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0;padding:2rem;font-size:2.5rem;font-weight:200;-webkit-border-radius:6px;border-radius:6px;line-height:3rem;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545}.topcoat-textarea:focus,.topcoat-textarea--large:focus{background-color:#fff;color:#000}.topcoat-textarea--large{font-size:3rem;line-height:4rem}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Regular.otf)}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Light.otf);font-weight:200}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Semibold.otf);font-weight:600}body{margin:0;padding:0;background:#dfe2e2;color:#000;font:16px "Source Sans",helvetica,arial,sans-serif;font-weight:200;text-rendering:optimizeLegibility}:focus{outline-color:transparent;outline-style:none}.topcoat-icon--menu-stack{background:url(../img/hamburger_dark.svg) no-repeat;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover}.quarter{width:25%}.half{width:50%}.three-quarters{width:75%}.third{width:33.333%}.two-thirds{width:66.666%}.full{width:100%}.left{text-align:left}.center{text-align:center}.right{text-align:right}.reset-ui{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden} -------------------------------------------------------------------------------- /font/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /font/SourceCodePro-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-Black.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-Bold.otf -------------------------------------------------------------------------------- /font/SourceCodePro-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-ExtraLight.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-Light.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceCodePro-Semibold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-Black.otf -------------------------------------------------------------------------------- /font/SourceSansPro-BlackIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-BlackIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-Bold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-BoldIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-BoldIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-ExtraLight.otf -------------------------------------------------------------------------------- /font/SourceSansPro-ExtraLightIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-ExtraLightIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-It.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-It.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-Light.otf -------------------------------------------------------------------------------- /font/SourceSansPro-LightIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-LightIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-Regular.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-Semibold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-SemiboldIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/font/SourceSansPro-SemiboldIt.otf -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/icon.png -------------------------------------------------------------------------------- /img/bg_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/bg_dark.png -------------------------------------------------------------------------------- /img/breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/breadcrumb.png -------------------------------------------------------------------------------- /img/camera-highlight.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /img/camera.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /img/checkbox_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/checkbox_checked.png -------------------------------------------------------------------------------- /img/checkbox_checked_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/checkbox_checked_dark.png -------------------------------------------------------------------------------- /img/checkbox_unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/checkbox_unchecked.png -------------------------------------------------------------------------------- /img/checkbox_unchecked_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/checkbox_unchecked_dark.png -------------------------------------------------------------------------------- /img/checkmark_bw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | ]> 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /img/dark-combo-box-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/dark-combo-box-bg.png -------------------------------------------------------------------------------- /img/dark-combo-box-bg2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/dark-combo-box-bg2x.png -------------------------------------------------------------------------------- /img/dark-grips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/dark-grips.png -------------------------------------------------------------------------------- /img/dark-sprites2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/dark-sprites2x.png -------------------------------------------------------------------------------- /img/drop-down-triangle-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/drop-down-triangle-dark.png -------------------------------------------------------------------------------- /img/drop-down-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/drop-down-triangle.png -------------------------------------------------------------------------------- /img/light-combo-box-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/light-combo-box-bg.png -------------------------------------------------------------------------------- /img/light-combo-box-bg2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/light-combo-box-bg2x.png -------------------------------------------------------------------------------- /img/light-grips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/light-grips.png -------------------------------------------------------------------------------- /img/light-sprites2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/light-sprites2x.png -------------------------------------------------------------------------------- /img/pop-up-triangle-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/pop-up-triangle-dark.png -------------------------------------------------------------------------------- /img/pop-up-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/pop-up-triangle.png -------------------------------------------------------------------------------- /img/search-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/search-bg.png -------------------------------------------------------------------------------- /img/search-bg2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/search-bg2x.png -------------------------------------------------------------------------------- /img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Slice 1 4 | Created with Sketch (http://www.bohemiancoding.com/sketch) 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/search_bw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | ]> 9 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /img/search_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | ]> 9 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /img/search_light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Slice 1 4 | Created with Sketch (http://www.bohemiancoding.com/sketch) 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/spinner.png -------------------------------------------------------------------------------- /img/spinner2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/img/spinner2x.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Todo Lite 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 60 | 72 | 94 | 115 | 147 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /js/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 | 20 | 21 | var coax = require("coax"), 22 | fastclick = require("fastclick"), 23 | appDbName = "todo" 24 | 25 | new fastclick.FastClick(document.body) 26 | 27 | document.addEventListener("deviceready", onDeviceReady, false) 28 | 29 | //var REMOTE_SYNC_URL = "http://localhost:4984/todolite" 30 | var REMOTE_SYNC_URL = "http://demo.mobile.couchbase.com/todolite" 31 | 32 | /* 33 | Initialize the app, connect to the database, draw the initial UI 34 | */ 35 | 36 | // run on device ready, call setupConfig kick off application logic 37 | // with appReady. 38 | 39 | function onDeviceReady() { 40 | setupConfig(function(err){ 41 | if (err) { 42 | alert(err) 43 | return console.log("err "+JSON.stringify(err)) 44 | } 45 | connectToChanges() 46 | goIndex() 47 | triggerSync(function(err) { 48 | if (err) {console.log("error on sync"+ JSON.stringify(err))} 49 | }) 50 | }) 51 | }; 52 | 53 | // function placeholder replaced by whatever should be running when the 54 | // change comes in. Used to trigger display updates. 55 | window.dbChanged = function(){} 56 | 57 | // call window.dbChanged each time the database changes. Use it to 58 | // update the display when local or remote updates happen. 59 | function connectToChanges() { 60 | config.db.changes({since : config.info.update_seq}, function(err, change){ 61 | lastSeq = change.seq 62 | log("change", err, change) 63 | window.dbChanged() 64 | }) 65 | } 66 | 67 | /* 68 | Error handling UI 69 | */ 70 | 71 | function loginErr(err) { 72 | if (err.reason) { 73 | alert("Can't login: "+err.reason); 74 | } else { 75 | alert("Login error: "+JSON.stringify(err)) 76 | } 77 | } 78 | 79 | function logoutError(error) { 80 | if (error.reason) { 81 | alert( "Can't Logout: " + error.reason ) 82 | } else { 83 | alert( "Logout Error: " + JSON.stringify( error ) ) 84 | } 85 | } 86 | 87 | /* 88 | The index UI lists the available todo lists and lets you create new ones. 89 | */ 90 | 91 | function drawContent(html) { 92 | scroll(0,0) 93 | $("#content").html(html) 94 | } 95 | 96 | function goIndex() { 97 | drawContent(config.t.index()) 98 | $("#content form").submit(function(e) { 99 | e.preventDefault() 100 | var doc = jsonform(this) 101 | doc.type = "list" 102 | doc.created_at = new Date() 103 | if (config.user && config.user.email) { 104 | // the the device owner owns lists they create 105 | doc.owner = "p:"+config.user.user_id 106 | } 107 | config.db.post(doc, function(err, ok) { 108 | $("#content form input").val("") 109 | }) 110 | }) 111 | // If you click a list, 112 | $("#scrollable").on("click", "li", function() { 113 | var id = $(this).attr("data-id"); 114 | goList(id) 115 | }) 116 | // offer the sign in screen to logged out users 117 | if (!config.user) { 118 | $(".todo-login").show().click(function(){ 119 | doFirstLogin(function(err) { 120 | if (err) {return loginErr(err)} 121 | goIndex() 122 | }) 123 | }) 124 | } else { 125 | $( ".todo-login" ).show().click( function() { 126 | doFacebookLogout( config.user.access_token, function(error, data) { 127 | if (error) { return logoutError( error ) } 128 | // Logout Success 129 | alert( "You are now logged out!" ) 130 | $( ".todo-login" ).off( "click" ) 131 | $( ".todo-login" ).show().click( function() { 132 | doFirstLogin( function( error ) { 133 | if (error) { return logoutError( error ) } 134 | goIndex() 135 | } ) 136 | } ) 137 | } ) 138 | } ) 139 | } 140 | // when the database changes, update the UI to reflect new lists 141 | window.dbChanged = function() { 142 | config.views(["lists", {descending : true}], function(err, view) { 143 | log("lists", view) 144 | $("#scrollable").html(config.t.indexList(view)) 145 | $("#scrollable li").on("swipeRight", function() { 146 | var id = $(this).attr("data-id") 147 | $(this).find("button").show().click(function(){ 148 | deleteItem(id) 149 | return false; 150 | }) 151 | }) 152 | }) 153 | } 154 | window.dbChanged() 155 | } 156 | 157 | /* 158 | The list UI lets you create todo tasks and check them off or delete them. 159 | It also links to a screen for sharing each list with a different set of friends. 160 | */ 161 | 162 | function goList(id) { 163 | config.db.get(id, function(err, doc){ 164 | drawContent(config.t.list(doc)) 165 | 166 | $("#content .todo-index").click(function(){ 167 | goIndex() 168 | }) 169 | 170 | $("#content .todo-share").click(function(){ 171 | doShare(id) 172 | }) 173 | 174 | $("#content form").submit(function(e) { 175 | e.preventDefault() 176 | var doc = jsonform(this) 177 | doc.type = "task" 178 | doc.list_id = id 179 | doc.updated_at = doc.created_at = new Date() 180 | config.db.post(doc, function(err, ok) { 181 | $("#content form input").val("") 182 | }) 183 | }) 184 | 185 | $("#scrollable").on("click", "li", function(e) { 186 | var id = $(this).attr("data-id") 187 | if ($(e.target).hasClass("camera")) { 188 | if ($(e.target).hasClass("image")) { 189 | goImage(id) 190 | } else { 191 | doCamera(id) 192 | } 193 | } else { 194 | toggleChecked(id) 195 | } 196 | }) 197 | 198 | window.dbChanged = function() { 199 | config.views(["tasks", { 200 | startkey : [id, {}], 201 | endkey : [id], 202 | descending : true 203 | }], function(err, view) { 204 | log("tasks", view) 205 | $("#scrollable").html(config.t.listItems(view)) 206 | $("#scrollable li").on("swipeRight", function() { 207 | var id = $(this).attr("data-id") 208 | $(this).find("button").show().click(function(){ 209 | deleteItem(id) 210 | }) 211 | }) 212 | }) 213 | } 214 | window.dbChanged() 215 | }) 216 | } 217 | 218 | function deleteItem(id) { 219 | log("delete", id) 220 | config.db.get(id, function(err, doc){ 221 | doc._deleted = true; 222 | config.db.put(id, doc, function(){}) 223 | }) 224 | } 225 | 226 | function toggleChecked(id) { 227 | log("toggle", id) 228 | config.db.get(id, function(err, doc){ 229 | doc.checked = !doc.checked 230 | doc.updated_at = new Date() 231 | config.db.put(id, doc, function(){}) 232 | }) 233 | } 234 | 235 | function doCamera(id) { 236 | log("camera", id) 237 | if (!(navigator.camera && navigator.camera.getPicture)) {return} 238 | 239 | navigator.camera.getPicture(function(imageData) { 240 | config.db(id, function(err, doc){ 241 | doc._attachments = { 242 | "image" : { 243 | content_type : "image/jpg", 244 | data : imageData 245 | } 246 | } 247 | config.db.post(doc, function(err, ok) {}) 248 | }) 249 | }, function(message) { // onFail 250 | }, { 251 | quality: 50, 252 | targetWidth : 1000, 253 | targetHeight : 1000, 254 | destinationType: Camera.DestinationType.DATA_URL 255 | }); 256 | } 257 | 258 | /* 259 | Display a photo for an task if it exists. 260 | */ 261 | 262 | function goImage(id) { 263 | window.dbChanged = function(){} 264 | config.db(id, function(err, doc){ 265 | doc.image_path = config.db([id,"image"]).pax.toString() 266 | drawContent(config.t.image(doc)) 267 | $("#content .todo-image-back").click(function(){ 268 | goList(doc.list_id) 269 | }) 270 | $("#content .todo-image-del").click(function(){ 271 | delete doc.image_path 272 | delete doc._attachments["image"] 273 | config.db.post(doc, function(err, ok) { 274 | goList(doc.list_id) 275 | }) 276 | }) 277 | }) 278 | } 279 | 280 | /* 281 | The sharing and login management stuff 282 | */ 283 | 284 | function doShare(id) { 285 | if (!config.user) { 286 | doFirstLogin(function(err) { 287 | if (err) { 288 | return loginErr(err) 289 | } 290 | log("login done", err, config.user) 291 | goShare(id) 292 | }) 293 | } else { 294 | goShare(id) 295 | } 296 | } 297 | 298 | function goShare(id) { 299 | window.dbChanged = function(){} 300 | config.db(id, function(err, doc) { 301 | config.views("profiles", function(err, view){ 302 | view.title = doc.title 303 | 304 | // fold over the view and mark members as checked 305 | var members = (doc.members || []).concat(doc.owner); 306 | 307 | for (var i = view.rows.length - 1; i >= 0; i--) { 308 | var row = view.rows[i] 309 | for (var j = members.length - 1; j >= 0; j--) { 310 | var member = members[j] 311 | log("row", row.id, member) 312 | if (row.id == member) { 313 | row.checked = "checked" 314 | } 315 | }; 316 | }; 317 | 318 | drawContent(config.t.share(view)) 319 | 320 | $("#content .todo-share-back").click(function(){ 321 | goList(id) 322 | }) 323 | 324 | $("#scrollable").on("click", "li", function() { 325 | var user = $(this).attr("data-id"); 326 | if (user !== doc.owner) { 327 | toggleShare(doc, user, function(){ 328 | goShare(id) 329 | }) 330 | } else { 331 | goShare(id) 332 | } 333 | }) 334 | }) 335 | }) 336 | } 337 | 338 | function toggleShare(doc, user, cb) { 339 | doc.members = doc.members || []; 340 | var i = doc.members.indexOf(user) 341 | if (i === -1) { 342 | doc.members.push(user) 343 | } else { 344 | doc.members.splice(i,1) 345 | } 346 | log("members", doc.members) 347 | config.db.post(doc, cb) 348 | } 349 | 350 | /* 351 | Login and setup existing data for user account 352 | */ 353 | 354 | function doFirstLogin(cb) { 355 | doFacebook(function(err, data){ 356 | if (err) {return cb(err)} 357 | config.setUser(data, function(err, ok){ 358 | if (err) {return cb(err)} 359 | registerFacebookToken(function(err,ok){ 360 | log("registerFacebookToken done "+JSON.stringify(err)) 361 | if (err) { 362 | log("registerFacebookToken err "+JSON.stringify([err, ok])) 363 | return cb(err) 364 | } 365 | createMyProfile(function(err){ 366 | log("createMyProfile done "+JSON.stringify(err)) 367 | addMyUsernameToAllLists(function(err) { 368 | log("addMyUsernameToAllLists done "+JSON.stringify(err)) 369 | if (err) {return cb(err)} 370 | triggerSync(function(err, ok){ 371 | log("triggerSync done "+JSON.stringify(err)) 372 | cb(err, ok) 373 | }) 374 | }) 375 | }) 376 | }) 377 | }) 378 | }) 379 | } 380 | 381 | function registerFacebookToken(cb) { 382 | var registerData = { 383 | remote_url : config.site.syncUrl, 384 | email : config.user.email, 385 | access_token : config.user.access_token 386 | } 387 | log("registerFacebookToken POST "+JSON.stringify(registerData)) 388 | coax.post([config.server, "_facebook_token"], registerData, cb) 389 | } 390 | 391 | function addMyUsernameToAllLists(cb) { 392 | config.views(["lists", {include_docs : true}], function(err, view) { 393 | if (err) {return cb(err)} 394 | var docs = []; 395 | view.rows.forEach(function(row) { 396 | row.doc.owner = "p:"+config.user.user_id 397 | docs.push(row.doc) 398 | }) 399 | config.db.post("_bulk_docs", {docs:docs}, function(err, ok) { 400 | log("updated all docs", err, ok) 401 | cb(err, ok) 402 | }) 403 | }) 404 | } 405 | 406 | function createMyProfile(cb) { 407 | log("createMyProfile user "+JSON.stringify(config.user)) 408 | var profileData = JSON.parse(JSON.stringify(config.user)) 409 | profileData.type = "profile" 410 | profileData.user_id = config.user.user_id 411 | delete profileData.email 412 | log("createMyProfile put "+JSON.stringify(profileData)) 413 | config.db.put("p:"+profileData.user_id, profileData, cb) 414 | } 415 | 416 | /* 417 | Get user email address from Facebook, and access code to verify on Sync Gateway 418 | */ 419 | 420 | 421 | function doFacebook(cb) { 422 | if (navigator && navigator.connection) { 423 | log("connection "+navigator.connection.type) 424 | if (navigator.connection.type == "none") { 425 | return cb({reason : "No network connection"}) 426 | } 427 | } 428 | 429 | // TODO should pull from config? 430 | FacebookInAppBrowser.settings.appId = "501518809925546" 431 | FacebookInAppBrowser.settings.redirectUrl = 'http://console.couchbasecloud.com/index/' 432 | FacebookInAppBrowser.settings.permissions = 'email' 433 | FacebookInAppBrowser.login(function(err, accessToken){ 434 | if (err) {return cb(err)} 435 | getFacebookUserInfo(accessToken, function(err, data) { 436 | if (err) {return cb(err)} 437 | log("got facebook user info", data) 438 | cb(false, data) 439 | }) 440 | }) 441 | } 442 | 443 | function doFacebookLogout(token, cb) { 444 | if (navigator && navigator.connection) { 445 | log( "connection " + navigator.connection.type ) 446 | if (navigator.connection.type == "none") { return cb( { 447 | reason : "No network connection" 448 | } ) } 449 | } 450 | FacebookInAppBrowser.settings.appId = "501518809925546" 451 | FacebookInAppBrowser.settings.redirectUrl = 'http://console.couchbasecloud.com/index/' 452 | FacebookInAppBrowser.settings.permissions = 'email' 453 | FacebookInAppBrowser.logout( token, function(err, data) { 454 | if (err) { return cb( err ) } 455 | log( "Logged out of facebook" ); 456 | config.user = null; 457 | cb( false, data ); 458 | } ) 459 | } 460 | 461 | function getFacebookUserInfo(token, cb) { 462 | var url = "https://graph.facebook.com/me?fields=id,name,email&access_token="+token 463 | coax.get(url, function(err, data) { 464 | if (err) {return cb(err)} 465 | data.access_token = token 466 | cb(false, data) 467 | }) 468 | } 469 | 470 | function getNewFacebookToken(cb) { 471 | log("getNewFacebookToken") 472 | // should be like doFirstLogin() but modify the user and 473 | // doesn't need to put the owner on all the lists. 474 | 475 | doFacebook(function(err, data){ 476 | if (err) {return cb(err)} 477 | config.setUser(data, function(err, ok){ 478 | if (err) {return cb(err)} 479 | registerFacebookToken(cb) 480 | }) 481 | }) 482 | } 483 | 484 | /* 485 | Sync Manager: this is run on first login, and on every app boot after that. 486 | 487 | The way it works is with an initial single push replication. When that 488 | completes, we know we have a valid connection, so we can trigger a continuous 489 | push and pull 490 | 491 | */ 492 | 493 | function triggerSync(cb, retryCount) { 494 | if (!config.user) { 495 | return log("no user") 496 | } 497 | var remote = { 498 | url : config.site.syncUrl, 499 | auth : {facebook : {email : config.user.email}} // why is this email? 500 | }, 501 | push = { 502 | source : appDbName, 503 | target : remote, 504 | continuous : true 505 | }, pull = { 506 | target : appDbName, 507 | source : remote, 508 | continuous : true 509 | }, 510 | 511 | pushSync = syncManager(config.server, push), 512 | pullSync = syncManager(config.server, pull) 513 | 514 | log("pushSync", push) 515 | 516 | if (typeof retryCount == "undefined") { 517 | retryCount = 3 518 | } 519 | 520 | var challenged = false; 521 | function authChallenge() { 522 | if (challenged) {return} 523 | challenged = true; 524 | pushSync.cancel(function(err, ok) { 525 | pullSync.cancel(function(err, ok) { 526 | if (retryCount == 0) {return cb("sync retry limit reached")} 527 | retryCount-- 528 | getNewFacebookToken(function(err, ok) { 529 | if (err) { 530 | return loginErr(err) 531 | } 532 | triggerSync(cb, retryCount) 533 | }) 534 | }) 535 | }) 536 | } 537 | 538 | pushSync.on("auth-challenge", authChallenge) 539 | pullSync.on("auth-challenge", authChallenge) 540 | 541 | pushSync.on("error", function(err){ 542 | if (challenged) {return} 543 | cb(err) 544 | }) 545 | pushSync.on("connected", function(){ 546 | pullSync.start() 547 | }) 548 | pullSync.on("error", function(err){ 549 | if (challenged) {return} 550 | cb(err) 551 | }) 552 | pullSync.on("connected", function(){ 553 | cb() 554 | }) 555 | // setTimeout(function(){ 556 | pushSync.start() 557 | // }, 10000) 558 | } 559 | 560 | /* 561 | The config functions don't have any visibile UI, they are used 562 | for application bootstrap and then by later state. The result of 563 | the config setup is stored in `window.config` for easy access. 564 | */ 565 | 566 | function setupConfig(done) { 567 | // get CBL url 568 | if (!window.cblite) { 569 | return done('Couchbase Lite not installed') 570 | } 571 | 572 | var mustache = require("mustache"), 573 | t = {} 574 | 575 | $('script[type="text/mustache"]').each(function() { 576 | var id = this.id.split('-') 577 | id.pop() 578 | t[id.join('-')] = mustache.compile(this.innerHTML.replace(/^\s+|\s+$/g,'')) 579 | }); 580 | 581 | cblite.getURL(function(err, url) { 582 | console.log("getURL: " + JSON.stringify([err, url])) 583 | if (err) {return done(err)} 584 | 585 | if (!/Apple/.test(navigator.userAgent)) { 586 | // this helps on Android < 4.4 587 | // otherwise basic auth doesn't work 588 | var xmlHttp = new XMLHttpRequest() 589 | xmlHttp.open( 'GET', url, false ) 590 | xmlHttp.send( null ) 591 | console.log( 'XMLHttpRequest get: ' + xmlHttp.responseText ) 592 | } 593 | 594 | window.server = coax(url); 595 | var db = coax([url, appDbName]); 596 | setupDb(db, function(err, info){ 597 | if (err) {return done(err)} 598 | setupViews(db, function(err, views){ 599 | if (err) {return done(err)} 600 | getUser(db, function(err, user) { 601 | if (err) {return done(err)} 602 | window.config = { 603 | site : { 604 | syncUrl : REMOTE_SYNC_URL 605 | }, 606 | user : user, 607 | setUser : function(newUser, cb) { 608 | if (window.config.user) { 609 | if (config.user.user_id !== newUser.id) { 610 | return cb("already logged in as "+config.user.user_id) 611 | } else { 612 | // we got a new facebook token 613 | config.user.access_token = newUser.access_token 614 | db.put("_local/user", config.user, function(err, ok){ 615 | if (err) {return cb(err)} 616 | log("updateUser ok") 617 | config.user._rev = ok.rev 618 | cb() 619 | }) 620 | } 621 | } else { 622 | newUser.user_id = newUser.id 623 | log("setUser "+JSON.stringify(newUser)) 624 | db.put("_local/user", newUser, function(err, ok){ 625 | if (err) {return cb(err)} 626 | log("setUser ok") 627 | window.config.user = newUser 628 | cb() 629 | }) 630 | } 631 | }, 632 | db : db, 633 | s : coax(url), 634 | info : info, 635 | views : views, 636 | server : url, 637 | t : t 638 | } 639 | if (window.config.user) { 640 | registerFacebookToken(done) 641 | } else { 642 | done(false) 643 | } 644 | }) 645 | }) 646 | }) 647 | }) 648 | 649 | function setupDb(db, cb) { 650 | db.get(function(err, res, body){ 651 | console.log(JSON.stringify(["before create db put", err, res, body])) 652 | db.put(function(err, res, body){ 653 | db.get(cb) 654 | }) 655 | }) 656 | } 657 | 658 | function setupViews(db, cb) { 659 | var design = "_design/todo10" 660 | db.put(design, { 661 | views : { 662 | lists : { 663 | map : function(doc) { 664 | if (doc.type == "list" && doc.created_at && doc.title) { 665 | emit(doc.created_at, doc.title) 666 | } 667 | }.toString() 668 | }, 669 | tasks : { 670 | map : function(doc) { 671 | if (doc.type == "task" && doc.created_at && doc.title && doc.list_id) { 672 | emit([doc.list_id, doc.created_at], 673 | { 674 | checked : doc.checked ? "checked" : "", 675 | title : doc.title, 676 | image : (doc._attachments && doc._attachments["image"]) 677 | }) 678 | } 679 | }.toString() 680 | }, 681 | profiles : { 682 | map : function(doc){ 683 | if (doc.type == "profile" && doc.user_id && doc.name) { 684 | emit(doc.name) 685 | } 686 | }.toString() 687 | } 688 | } 689 | }, function(){ 690 | cb(false, db([design, "_view"])) 691 | }) 692 | } 693 | 694 | function getUser(db, cb) { 695 | db.get("_local/user", function(err, doc) { 696 | var user = false; 697 | if (!err) { 698 | user = doc; 699 | } 700 | cb(false, user) 701 | }) 702 | }; 703 | } 704 | 705 | /* END APP */ 706 | 707 | /* 708 | * Helpers that aren't in a node module and thus aren't in the `modules.js` file 709 | * 710 | * 711 | * 712 | * 713 | * 714 | */ 715 | 716 | function jsonform(elem) { 717 | var o = {}, list = $(elem).serializeArray(); 718 | for (var i = list.length - 1; i >= 0; i--) { 719 | var name = list[i].name, value = list[i].value; 720 | if (o[name]) { 721 | if (!o[name].push) { 722 | o[name] = [o[name]]; 723 | } 724 | o[name].push(value); 725 | } else { 726 | o[name] = value; 727 | } 728 | }; 729 | return o; 730 | }; 731 | 732 | /* 733 | Sync manager module TODO extract to NPM 734 | */ 735 | 736 | function syncManager(serverUrl, syncDefinition) { 737 | var handlers = {} 738 | 739 | function callHandlers(name, data) { 740 | (handlers[name]||[]).forEach(function(h){ 741 | h(data) 742 | }) 743 | } 744 | 745 | function doCancelPost(cb) { 746 | var cancelDef = JSON.parse(JSON.stringify(syncDefinition)) 747 | cancelDef.cancel = true 748 | coax.post([serverUrl, "_replicate"], cancelDef, function(err, info){ 749 | if (err) { 750 | callHandlers("error", err) 751 | if (cb) {cb(err, info)} 752 | } else { 753 | callHandlers("cancelled", info) 754 | if (cb) {cb(err, info)} 755 | } 756 | }) 757 | } 758 | 759 | function doStartPost() { 760 | var tooLate; 761 | function pollForStatus(info, wait) { 762 | if (wait) { 763 | setTimeout(function() { 764 | tooLate = true 765 | }, wait) 766 | } 767 | processTaskInfo(info.session_id, function(done){ 768 | if (!done && !tooLate) { 769 | setTimeout(function() { 770 | pollForStatus(info) 771 | }, 200) 772 | } else if (tooLate) { 773 | callHandlers("error", "timeout") 774 | } 775 | }) 776 | } 777 | 778 | var callBack; 779 | if (syncDefinition.continuous) { 780 | // auth errors not detected for continuous sync 781 | // we could use _active_tasks?feed=continuous for this 782 | // but we don't need that code for this app... 783 | callBack = function(err, info) { 784 | log("continuous sync callBack", err, info, syncDefinition) 785 | if (err) { 786 | callHandlers("error", err) 787 | } else { 788 | pollForStatus(info, 10000) 789 | callHandlers("started", info) 790 | } 791 | } 792 | } else { // non-continuous 793 | callBack = function(err, info) { 794 | log("sync callBack", err, info, syncDefinition) 795 | if (err) { 796 | if (info.status == 401) { 797 | err.status = info.status; 798 | callHandlers("auth-challenge", err) 799 | } else { 800 | err.status = info.status; 801 | callHandlers("error", err) 802 | } 803 | } else { 804 | callHandlers("connected", info) 805 | } 806 | 807 | } 808 | } 809 | log("start sync"+ JSON.stringify(syncDefinition)) 810 | coax.post([serverUrl, "_replicate"], syncDefinition, callBack) 811 | // coax.post([serverUrl, "_replicator"], syncDefinition, callBack) 812 | } 813 | 814 | function processTaskInfo(id, cb) { 815 | taskInfo(id, function(err, task) { 816 | if (err) {return cb(err)} 817 | log("task", task) 818 | 819 | publicAPI.task = task 820 | if (task.error && task.error[0] == 401) { 821 | cb(true) 822 | callHandlers("auth-challenge", {status : 401, error : task.error[1]}) 823 | } else if (task.error && task.error[0] == 502) { 824 | cb(true) 825 | callHandlers("auth-challenge", {status : 502, error : task.error[1]}) 826 | } else if (task.status == "Idle" || task.status == "Stopped" || (/Processed/.test(task.status) && !/Processed 0/.test(task.status))) { 827 | cb(true) 828 | callHandlers("connected", task) 829 | } else if (/Processed 0 \/ 0 changes/.test(task.status)) { 830 | // cb(false) // keep polling? (or does this mean we are connected?) 831 | cb(true) 832 | callHandlers("connected", task) 833 | } else { 834 | cb(false) // not done 835 | } 836 | }) 837 | } 838 | 839 | function taskInfo(id, cb) { 840 | coax([serverUrl,"_active_tasks"], function(err, tasks) { 841 | var me; 842 | for (var i = tasks.length - 1; i >= 0; i--) { 843 | if (tasks[i].task == id) { 844 | me = tasks[i] 845 | } 846 | } 847 | cb(false, me); 848 | }) 849 | } 850 | 851 | var publicAPI = { 852 | start : doStartPost, 853 | cancel : doCancelPost, 854 | on : function(name, cb) { 855 | handlers[name] = handlers[name] || [] 856 | handlers[name].push(cb) 857 | } 858 | } 859 | return publicAPI; 860 | } 861 | 862 | 863 | // pluggable logger 864 | function log() { 865 | console.log.apply(console, arguments) 866 | } 867 | -------------------------------------------------------------------------------- /js/phonegap.facebook.inappbrowser.js: -------------------------------------------------------------------------------- 1 | // via https://github.com/caiovaccaro/phonegap.facebook.inappbrowser 2 | ;(function() { 3 | 4 | FacebookInAppBrowser = { 5 | 6 | settings: { 7 | appId: '', 8 | redirectUrl: '', 9 | permissions: '' 10 | } 11 | 12 | , login: function(successCallback) { 13 | 14 | if(this.settings.appId === '' || this.settings.redirectUrl === '') { 15 | console.log('[FacebookInAppBrowser] You need to set up your app id and redirect url.'); 16 | return false; 17 | } 18 | 19 | var authorize_url = "https://m.facebook.com/dialog/oauth?"; 20 | authorize_url += "client_id=" + this.settings.appId; 21 | authorize_url += "&redirect_uri=" + this.settings.redirectUrl; 22 | authorize_url += "&display=touch"; 23 | authorize_url += "&response_type=token"; 24 | authorize_url += "&type=user_agent"; 25 | 26 | if(this.settings.permissions !== '') { 27 | authorize_url += "&scope=" + this.settings.permissions; 28 | } 29 | 30 | var faceView, workaround = false, access_token = null, redirectUrl = this.settings.redirectUrl; 31 | callback = function(location) { 32 | console.log("[FacebookInAppBrowser] Event 'loadstart': " + JSON.stringify(location)); 33 | 34 | if (location.url.indexOf("https://m./") == 0) { 35 | // workaround for facebook bug introduced 8/27 36 | var newLoc = location.url.replace("https://m./", "https://m.facebook.com/") 37 | console.log("[FacebookInAppBrowser] workaround goto "+newLoc) 38 | // faceView.executeScript({code : 'window.location = "'+newLoc+'"'}) 39 | workaround = true; 40 | faceView.close() 41 | faceView = window.open(newLoc, '_blank', 'location=no'); 42 | faceView.addEventListener('loadstart', callback); 43 | faceView.addEventListener('exit', onExit); 44 | } 45 | 46 | if (location.url.indexOf("access_token") !== -1) { 47 | // Success 48 | access_token = location.url.match(/access_token=(.*)$/)[1].split('&expires_in')[0]; 49 | console.log("[FacebookInAppBrowser] Logged in. Token: " + access_token); 50 | faceView.close(); 51 | 52 | successCallback(false, access_token); 53 | } 54 | 55 | if (location.url.indexOf("error_reason=user_denied") !== -1) { 56 | // User denied 57 | userDenied = true; 58 | console.log('[FacebookInAppBrowser] User denied Facebook Login.'); 59 | successCallback({reason : "User denied Facebook Login."}); 60 | faceView.close(); 61 | } 62 | }, 63 | onExit = function() { 64 | if (workaround) { 65 | workaround = false 66 | return; 67 | } 68 | if(access_token === null && userDenied === false) { 69 | // InAppBrowser was closed and we don't have an app id 70 | successCallback({reason : "Not logged into Facebook."}); 71 | 72 | } 73 | 74 | userDenied = false; 75 | 76 | }, 77 | userDenied = false; 78 | 79 | faceView = window.open(authorize_url, '_blank', 'location=no'); 80 | faceView.addEventListener('loadstart', callback); 81 | faceView.addEventListener('exit', onExit); 82 | 83 | 84 | 85 | } 86 | 87 | , invite: function(inviteText, successCallback, errorCallback) { 88 | 89 | if(typeof inviteText === 'undefined') { 90 | console.log('[FacebookInAppBrowser] inviteText is a required parameter.'); 91 | return false; 92 | } 93 | 94 | var obj = this; 95 | 96 | var request_url = "https://m.facebook.com/dialog/apprequests?"; 97 | request_url += "app_id=" + this.settings.appId; 98 | request_url += "&redirect_uri=" + this.settings.redirectUrl; 99 | request_url += "&display=touch"; 100 | request_url += "&message=" + inviteText; 101 | 102 | request_url = encodeURI(request_url); 103 | 104 | console.log('[FacebookInAppBrowser] Invite, URL: ' + request_url); 105 | 106 | var faceView, 107 | callback = function(location) { 108 | console.log("[FacebookInAppBrowser] Event 'loadstart': " + JSON.stringify(location)); 109 | 110 | if(location.url == request_url) { 111 | 112 | // Do nothing 113 | 114 | } else if (location.url.indexOf("?request=") !== -1) { 115 | // Success 116 | faceView.close(); 117 | 118 | if(typeof successCallback !== 'undefined' && typeof successCallback === 'function') { 119 | successCallback(); 120 | } 121 | 122 | } else if(location.url.indexOf('error_code=') !== -1) { 123 | // Error 124 | faceView.close(); 125 | 126 | if(typeof errorCallback !== 'undefined' && typeof errorCallback === 'function') { 127 | errorCallback(); 128 | } 129 | 130 | } else if(location.url === obj.settings.redirectUrl + '#_=_') { 131 | // User clicked Cancel 132 | face.close(); 133 | 134 | } 135 | 136 | }; 137 | 138 | faceView = window.open(request_url, '_blank', 'location=no'); 139 | faceView.addEventListener('loadstart', callback); 140 | 141 | } 142 | 143 | , logout: function(access_token, afterCallback) { 144 | 145 | var logout_url = encodeURI("https://www.facebook.com/logout.php?next=" + this.settings.redirectUrl + "&access_token=" + access_token); 146 | var obj = this; 147 | 148 | var face = window.open(logout_url, '_blank', 'hidden=yes,location=no'), 149 | callback = function(location) { 150 | console.log("[FacebookInAppBrowser] Event 'loadstart': " + JSON.stringify(location)); 151 | 152 | if(location.url == logout_url) { 153 | 154 | // Do nothing 155 | 156 | } else if(location.url === obj.settings.redirectUrl + '#_=_' || location.url === obj.settings.redirectUrl) { 157 | 158 | face.close(); 159 | 160 | if(typeof afterCallback !== 'undefined' && typeof afterCallback === 'function') { 161 | 162 | afterCallback(); 163 | 164 | } 165 | 166 | } 167 | 168 | }; 169 | 170 | face.addEventListener('loadstart', callback); 171 | 172 | } 173 | 174 | }; 175 | 176 | }).call(this); 177 | -------------------------------------------------------------------------------- /js/zepto.min.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ 2 | (function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) -------------------------------------------------------------------------------- /js/zepto.touch.js: -------------------------------------------------------------------------------- 1 | // Zepto.js 2 | // (c) 2010-2012 Thomas Fuchs 3 | // Zepto.js may be freely distributed under the MIT license. 4 | 5 | ;(function($){ 6 | var touch = {}, 7 | touchTimeout, tapTimeout, swipeTimeout, 8 | longTapDelay = 750, longTapTimeout 9 | 10 | function parentIfText(node) { 11 | return 'tagName' in node ? node : node.parentNode 12 | } 13 | 14 | function swipeDirection(x1, x2, y1, y2) { 15 | var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2) 16 | return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') 17 | } 18 | 19 | function longTap() { 20 | longTapTimeout = null 21 | if (touch.last) { 22 | touch.el.trigger('longTap') 23 | touch = {} 24 | } 25 | } 26 | 27 | function cancelLongTap() { 28 | if (longTapTimeout) clearTimeout(longTapTimeout) 29 | longTapTimeout = null 30 | } 31 | 32 | function cancelAll() { 33 | if (touchTimeout) clearTimeout(touchTimeout) 34 | if (tapTimeout) clearTimeout(tapTimeout) 35 | if (swipeTimeout) clearTimeout(swipeTimeout) 36 | if (longTapTimeout) clearTimeout(longTapTimeout) 37 | touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null 38 | touch = {} 39 | } 40 | 41 | $(document).ready(function(){ 42 | var now, delta 43 | 44 | $(document.body) 45 | .bind('touchstart', function(e){ 46 | now = Date.now() 47 | delta = now - (touch.last || now) 48 | touch.el = $(parentIfText(e.touches[0].target)) 49 | touchTimeout && clearTimeout(touchTimeout) 50 | touch.x1 = e.touches[0].pageX 51 | touch.y1 = e.touches[0].pageY 52 | if (delta > 0 && delta <= 250) touch.isDoubleTap = true 53 | touch.last = now 54 | longTapTimeout = setTimeout(longTap, longTapDelay) 55 | }) 56 | .bind('touchmove', function(e){ 57 | cancelLongTap() 58 | touch.x2 = e.touches[0].pageX 59 | touch.y2 = e.touches[0].pageY 60 | if (Math.abs(touch.x1 - touch.x2) > 10) 61 | e.preventDefault() 62 | }) 63 | .bind('touchend', function(e){ 64 | cancelLongTap() 65 | 66 | // swipe 67 | if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) || 68 | (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)) 69 | 70 | swipeTimeout = setTimeout(function() { 71 | touch.el.trigger('swipe') 72 | touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2))) 73 | touch = {} 74 | }, 0) 75 | 76 | // normal tap 77 | else if ('last' in touch) 78 | 79 | // delay by one tick so we can cancel the 'tap' event if 'scroll' fires 80 | // ('tap' fires before 'scroll') 81 | tapTimeout = setTimeout(function() { 82 | 83 | // trigger universal 'tap' with the option to cancelTouch() 84 | // (cancelTouch cancels processing of single vs double taps for faster 'tap' response) 85 | var event = $.Event('tap') 86 | event.cancelTouch = cancelAll 87 | touch.el.trigger(event) 88 | 89 | // trigger double tap immediately 90 | if (touch.isDoubleTap) { 91 | touch.el.trigger('doubleTap') 92 | touch = {} 93 | } 94 | 95 | // trigger single tap after 250ms of inactivity 96 | else { 97 | touchTimeout = setTimeout(function(){ 98 | touchTimeout = null 99 | touch.el.trigger('singleTap') 100 | touch = {} 101 | }, 250) 102 | } 103 | 104 | }, 0) 105 | 106 | }) 107 | .bind('touchcancel', cancelAll) 108 | 109 | $(window).bind('scroll', cancelAll) 110 | }) 111 | 112 | ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){ 113 | $.fn[m] = function(callback){ return this.bind(m, callback) } 114 | }) 115 | })(Zepto) 116 | -------------------------------------------------------------------------------- /modules.sh: -------------------------------------------------------------------------------- 1 | browserify -r coax -r fastclick -r mustache > js/modules.js 2 | -------------------------------------------------------------------------------- /res/icon/android/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /res/icon/android/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /res/icon/android/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /res/icon/android/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /res/icon/android/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /res/icon/android/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/android/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /res/icon/bada-wac/icon-48-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/bada-wac/icon-48-type5.png -------------------------------------------------------------------------------- /res/icon/bada-wac/icon-50-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/bada-wac/icon-50-type3.png -------------------------------------------------------------------------------- /res/icon/bada-wac/icon-80-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/bada-wac/icon-80-type4.png -------------------------------------------------------------------------------- /res/icon/bada/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/bada/icon-128.png -------------------------------------------------------------------------------- /res/icon/blackberry/icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/blackberry/icon-80.png -------------------------------------------------------------------------------- /res/icon/ios/icon-57-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/ios/icon-57-2x.png -------------------------------------------------------------------------------- /res/icon/ios/icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/ios/icon-57.png -------------------------------------------------------------------------------- /res/icon/ios/icon-72-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/ios/icon-72-2x.png -------------------------------------------------------------------------------- /res/icon/ios/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/ios/icon-72.png -------------------------------------------------------------------------------- /res/icon/tizen/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/tizen/icon-128.png -------------------------------------------------------------------------------- /res/icon/webos/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/webos/icon-64.png -------------------------------------------------------------------------------- /res/icon/windows-phone/icon-173-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/windows-phone/icon-173-tile.png -------------------------------------------------------------------------------- /res/icon/windows-phone/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/windows-phone/icon-48.png -------------------------------------------------------------------------------- /res/icon/windows-phone/icon-62-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/icon/windows-phone/icon-62-tile.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /res/screen/android/screen-hdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-hdpi-landscape.png -------------------------------------------------------------------------------- /res/screen/android/screen-hdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-hdpi-portrait.png -------------------------------------------------------------------------------- /res/screen/android/screen-ldpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-ldpi-landscape.png -------------------------------------------------------------------------------- /res/screen/android/screen-ldpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-ldpi-portrait.png -------------------------------------------------------------------------------- /res/screen/android/screen-mdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-mdpi-landscape.png -------------------------------------------------------------------------------- /res/screen/android/screen-mdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-mdpi-portrait.png -------------------------------------------------------------------------------- /res/screen/android/screen-xhdpi-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-xhdpi-landscape.png -------------------------------------------------------------------------------- /res/screen/android/screen-xhdpi-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/android/screen-xhdpi-portrait.png -------------------------------------------------------------------------------- /res/screen/bada-wac/screen-type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/bada-wac/screen-type3.png -------------------------------------------------------------------------------- /res/screen/bada-wac/screen-type4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/bada-wac/screen-type4.png -------------------------------------------------------------------------------- /res/screen/bada-wac/screen-type5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/bada-wac/screen-type5.png -------------------------------------------------------------------------------- /res/screen/bada/screen-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/bada/screen-portrait.png -------------------------------------------------------------------------------- /res/screen/blackberry/screen-225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/blackberry/screen-225.png -------------------------------------------------------------------------------- /res/screen/ios/screen-ipad-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-ipad-landscape-2x.png -------------------------------------------------------------------------------- /res/screen/ios/screen-ipad-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-ipad-landscape.png -------------------------------------------------------------------------------- /res/screen/ios/screen-ipad-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-ipad-portrait-2x.png -------------------------------------------------------------------------------- /res/screen/ios/screen-ipad-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-ipad-portrait.png -------------------------------------------------------------------------------- /res/screen/ios/screen-iphone-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-iphone-landscape-2x.png -------------------------------------------------------------------------------- /res/screen/ios/screen-iphone-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-iphone-landscape.png -------------------------------------------------------------------------------- /res/screen/ios/screen-iphone-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-iphone-portrait-2x.png -------------------------------------------------------------------------------- /res/screen/ios/screen-iphone-portrait-568h-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-iphone-portrait-568h-2x.png -------------------------------------------------------------------------------- /res/screen/ios/screen-iphone-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/ios/screen-iphone-portrait.png -------------------------------------------------------------------------------- /res/screen/tizen/README.md: -------------------------------------------------------------------------------- 1 | # Tizen Splash Screen 2 | 3 | Splash screens are unsupported on the Tizen platform. 4 | -------------------------------------------------------------------------------- /res/screen/webos/screen-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/webos/screen-64.png -------------------------------------------------------------------------------- /res/screen/windows-phone/screen-portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/TodoLite-PhoneGap/594cc21b615fdd80ecc6c38397f0dcd9eec0e637/res/screen/windows-phone/screen-portrait.jpg -------------------------------------------------------------------------------- /serve.sh: -------------------------------------------------------------------------------- 1 | http-server . 2 | -------------------------------------------------------------------------------- /sync-gateway-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": ["*"], 3 | "facebook": { "register": true }, 4 | "databases": { 5 | "todolite": { 6 | "server": "walrus:", 7 | "users": { 8 | "GUEST": {"disabled": true} 9 | }, 10 | "sync": ` 11 | function(doc, oldDoc) { 12 | // NOTE this function is the same across the iOS, Android, and PhoneGap versions. 13 | if (doc.type == "task") { 14 | if (!doc.list_id) { 15 | throw({forbidden : "Items must have a list_id."}); 16 | } 17 | channel("list-"+doc.list_id); 18 | } else if (doc.type == "list" || (doc._deleted && oldDoc && oldDoc.type == "list")) { 19 | // Make sure that the owner propery exists: 20 | var owner = oldDoc ? oldDoc.owner : doc.owner; 21 | if (!owner) { 22 | throw({forbidden : "List must have an owner."}); 23 | } 24 | 25 | // Make sure that only the owner of the list can update the list: 26 | if (doc.owner && owner != doc.owner) { 27 | throw({forbidden : "Cannot change owner for lists."}); 28 | } 29 | 30 | var ownerName = owner.substring(owner.indexOf(":")+1); 31 | requireUser(ownerName); 32 | 33 | var ch = "list-"+doc._id; 34 | if (!doc._deleted) { 35 | channel(ch); 36 | } 37 | 38 | // Grant owner access to the channel: 39 | access(ownerName, ch); 40 | 41 | // Grant shared members access to the channel: 42 | var members = !doc._deleted ? doc.members : oldDoc.members; 43 | if (Array.isArray(members)) { 44 | var memberNames = []; 45 | for (var i = members.length - 1; i >= 0; i--) { 46 | memberNames.push(members[i].substring(members[i].indexOf(":")+1)) 47 | }; 48 | access(memberNames, ch); 49 | } 50 | } else if (doc.type == "profile") { 51 | channel("profiles"); 52 | var user = doc._id.substring(doc._id.indexOf(":")+1); 53 | if (user !== doc.user_id) { 54 | throw({forbidden : "Profile user_id must match docid."}); 55 | } 56 | requireUser(user); 57 | access(user, "profiles"); 58 | } 59 | } 60 | ` 61 | } 62 | } 63 | } 64 | --------------------------------------------------------------------------------