Quellcode durchsuchen

Re-adding Ionic project, fixing project name and attributes of project directory

David Leonard vor 10 Jahren
Ursprung
Commit
ed3c027403
100 geänderte Dateien mit 123545 neuen und 74 gelöschten Zeilen
  1. 3 0
      ionic/.bowerrc
  2. 6 0
      ionic/.gitignore
  3. 26 0
      ionic/README.md
  4. 7 0
      ionic/bower.json
  5. 49 0
      ionic/config.xml
  6. 50 0
      ionic/gulpfile.js
  7. 83 0
      ionic/hooks/README.md
  8. 94 0
      ionic/hooks/after_prepare/010_add_platform_class.js
  9. 4 0
      ionic/ionic.project
  10. 21 0
      ionic/package.json
  11. 11 0
      ionic/plugins/ios.json
  12. BIN
      ionic/resources/android/icon/drawable-hdpi-icon.png
  13. BIN
      ionic/resources/android/icon/drawable-ldpi-icon.png
  14. BIN
      ionic/resources/android/icon/drawable-mdpi-icon.png
  15. BIN
      ionic/resources/android/icon/drawable-xhdpi-icon.png
  16. BIN
      ionic/resources/android/icon/drawable-xxhdpi-icon.png
  17. BIN
      ionic/resources/android/icon/drawable-xxxhdpi-icon.png
  18. BIN
      ionic/resources/android/splash/drawable-land-hdpi-screen.png
  19. BIN
      ionic/resources/android/splash/drawable-land-ldpi-screen.png
  20. BIN
      ionic/resources/android/splash/drawable-land-mdpi-screen.png
  21. BIN
      ionic/resources/android/splash/drawable-land-xhdpi-screen.png
  22. BIN
      ionic/resources/android/splash/drawable-land-xxhdpi-screen.png
  23. BIN
      ionic/resources/android/splash/drawable-land-xxxhdpi-screen.png
  24. BIN
      ionic/resources/android/splash/drawable-port-hdpi-screen.png
  25. BIN
      ionic/resources/android/splash/drawable-port-ldpi-screen.png
  26. BIN
      ionic/resources/android/splash/drawable-port-mdpi-screen.png
  27. BIN
      ionic/resources/android/splash/drawable-port-xhdpi-screen.png
  28. BIN
      ionic/resources/android/splash/drawable-port-xxhdpi-screen.png
  29. BIN
      ionic/resources/android/splash/drawable-port-xxxhdpi-screen.png
  30. BIN
      ionic/resources/icon.png
  31. BIN
      ionic/resources/ios/icon/icon-40.png
  32. BIN
      ionic/resources/ios/icon/icon-40@2x.png
  33. BIN
      ionic/resources/ios/icon/icon-50.png
  34. BIN
      ionic/resources/ios/icon/icon-50@2x.png
  35. BIN
      ionic/resources/ios/icon/icon-60.png
  36. BIN
      ionic/resources/ios/icon/icon-60@2x.png
  37. BIN
      ionic/resources/ios/icon/icon-60@3x.png
  38. BIN
      ionic/resources/ios/icon/icon-72.png
  39. BIN
      ionic/resources/ios/icon/icon-72@2x.png
  40. BIN
      ionic/resources/ios/icon/icon-76.png
  41. BIN
      ionic/resources/ios/icon/icon-76@2x.png
  42. BIN
      ionic/resources/ios/icon/icon-small.png
  43. BIN
      ionic/resources/ios/icon/icon-small@2x.png
  44. BIN
      ionic/resources/ios/icon/icon-small@3x.png
  45. BIN
      ionic/resources/ios/icon/icon.png
  46. BIN
      ionic/resources/ios/icon/icon@2x.png
  47. BIN
      ionic/resources/ios/splash/Default-568h@2x~iphone.png
  48. BIN
      ionic/resources/ios/splash/Default-667h.png
  49. BIN
      ionic/resources/ios/splash/Default-736h.png
  50. BIN
      ionic/resources/ios/splash/Default-Landscape-736h.png
  51. BIN
      ionic/resources/ios/splash/Default-Landscape@2x~ipad.png
  52. BIN
      ionic/resources/ios/splash/Default-Landscape~ipad.png
  53. BIN
      ionic/resources/ios/splash/Default-Portrait@2x~ipad.png
  54. BIN
      ionic/resources/ios/splash/Default-Portrait~ipad.png
  55. BIN
      ionic/resources/ios/splash/Default@2x~iphone.png
  56. BIN
      ionic/resources/ios/splash/Default~iphone.png
  57. BIN
      ionic/resources/splash.png
  58. 23 0
      ionic/scss/ionic.app.scss
  59. 1 0
      ionic/www/css/style.css
  60. BIN
      ionic/www/img/ionic.png
  61. 0 32
      ionic/www/index.html
  62. 72 0
      ionic/www/js/app.js
  63. 0 42
      ionic/www/js/controllers.js
  64. 5 0
      ionic/www/js/services.js
  65. 7600 0
      ionic/www/lib/ionic/css/ionic.css
  66. 23 0
      ionic/www/lib/ionic/css/ionic.min.css
  67. BIN
      ionic/www/lib/ionic/fonts/ionicons.eot
  68. 2230 0
      ionic/www/lib/ionic/fonts/ionicons.svg
  69. BIN
      ionic/www/lib/ionic/fonts/ionicons.ttf
  70. BIN
      ionic/www/lib/ionic/fonts/ionicons.woff
  71. 4232 0
      ionic/www/lib/ionic/js/angular-ui/angular-ui-router.js
  72. 7 0
      ionic/www/lib/ionic/js/angular-ui/angular-ui-router.min.js
  73. 2137 0
      ionic/www/lib/ionic/js/angular/angular-animate.js
  74. 33 0
      ionic/www/lib/ionic/js/angular/angular-animate.min.js
  75. 667 0
      ionic/www/lib/ionic/js/angular/angular-resource.js
  76. 13 0
      ionic/www/lib/ionic/js/angular/angular-resource.min.js
  77. 681 0
      ionic/www/lib/ionic/js/angular/angular-sanitize.js
  78. 16 0
      ionic/www/lib/ionic/js/angular/angular-sanitize.min.js
  79. 26130 0
      ionic/www/lib/ionic/js/angular/angular.js
  80. 250 0
      ionic/www/lib/ionic/js/angular/angular.min.js
  81. 13121 0
      ionic/www/lib/ionic/js/ionic-angular.js
  82. 18 0
      ionic/www/lib/ionic/js/ionic-angular.min.js
  83. 54615 0
      ionic/www/lib/ionic/js/ionic.bundle.js
  84. 386 0
      ionic/www/lib/ionic/js/ionic.bundle.min.js
  85. 8269 0
      ionic/www/lib/ionic/js/ionic.js
  86. 17 0
      ionic/www/lib/ionic/js/ionic.min.js
  87. 170 0
      ionic/www/lib/ionic/scss/_action-sheet.scss
  88. 48 0
      ionic/www/lib/ionic/scss/_animations.scss
  89. 24 0
      ionic/www/lib/ionic/scss/_backdrop.scss
  90. 62 0
      ionic/www/lib/ionic/scss/_badge.scss
  91. 404 0
      ionic/www/lib/ionic/scss/_bar.scss
  92. 54 0
      ionic/www/lib/ionic/scss/_button-bar.scss
  93. 252 0
      ionic/www/lib/ionic/scss/_button.scss
  94. 176 0
      ionic/www/lib/ionic/scss/_checkbox.scss
  95. 314 0
      ionic/www/lib/ionic/scss/_form.scss
  96. 151 0
      ionic/www/lib/ionic/scss/_grid.scss
  97. 815 0
      ionic/www/lib/ionic/scss/_items.scss
  98. 125 0
      ionic/www/lib/ionic/scss/_list.scss
  99. 50 0
      ionic/www/lib/ionic/scss/_loading.scss
  100. 0 0
      ionic/www/lib/ionic/scss/_menu.scss

+ 3 - 0
ionic/.bowerrc

@@ -0,0 +1,3 @@
+{
+  "directory": "www/lib"
+}

+ 6 - 0
ionic/.gitignore

@@ -0,0 +1,6 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+node_modules/
+platforms/
+plugins/

+ 26 - 0
ionic/README.md

@@ -0,0 +1,26 @@
+Ionic App Base
+=====================
+
+A starting project for Ionic that optionally supports using custom SCSS.
+
+## Using this project
+
+We recommend using the [Ionic CLI](https://github.com/driftyco/ionic-cli) to create new Ionic projects that are based on this project but use a ready-made starter template.
+
+For example, to start a new Ionic project with the default tabs interface, make sure the `ionic` utility is installed:
+
+```bash
+$ npm install -g ionic
+```
+
+Then run:
+
+```bash
+$ ionic start myProject tabs
+```
+
+More info on this can be found on the Ionic [Getting Started](http://ionicframework.com/getting-started) page and the [Ionic CLI](https://github.com/driftyco/ionic-cli) repo.
+
+## Issues
+Issues have been disabled on this repo, if you do find an issue or have a question consider posting it on the [Ionic Forum](http://forum.ionicframework.com/).  Or else if there is truly an error, follow our guidelines for [submitting an issue](http://ionicframework.com/submit-issue/) to the main Ionic repository.
+

+ 7 - 0
ionic/bower.json

@@ -0,0 +1,7 @@
+{
+  "name": "HelloIonic",
+  "private": "true",
+  "devDependencies": {
+    "ionic": "driftyco/ionic-bower#1.0.0-rc.2"
+  }
+}

+ 49 - 0
ionic/config.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<widget id="com.ionicframework.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+  <name>HelloCordova</name>
+  <description>
+        An Ionic Framework and Cordova project.
+    </description>
+  <author email="hi@ionicframework" href="http://ionicframework.com/">
+      Ionic Framework Team
+    </author>
+  <content src="index.html"/>
+  <access origin="*"/>
+  <preference name="webviewbounce" value="false"/>
+  <preference name="UIWebViewBounce" value="false"/>
+  <preference name="DisallowOverscroll" value="true"/>
+  <preference name="BackupWebStorage" value="none"/>
+  <preference name="SplashScreen" value="screen"/>
+  <preference name="SplashScreenDelay" value="3000"/>
+  <feature name="StatusBar">
+    <param name="ios-package" value="CDVStatusBar" onload="true"/>
+  </feature>
+  <platform name="ios">
+    <icon src="resources/ios/icon/icon.png" width="57" height="57"/>
+    <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
+    <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
+    <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
+    <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
+    <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
+    <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
+    <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
+    <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
+    <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
+    <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
+    <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
+    <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
+    <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
+    <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
+    <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
+    <splash src="resources/ios/splash/Default-568h@2x~iphone.png" height="1136" width="640"/>
+    <splash src="resources/ios/splash/Default-667h.png" height="1334" width="750"/>
+    <splash src="resources/ios/splash/Default-736h.png" height="2208" width="1242"/>
+    <splash src="resources/ios/splash/Default-Landscape-736h.png" height="1242" width="2208"/>
+    <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" height="1536" width="2048"/>
+    <splash src="resources/ios/splash/Default-Landscape~ipad.png" height="768" width="1024"/>
+    <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" height="2048" width="1536"/>
+    <splash src="resources/ios/splash/Default-Portrait~ipad.png" height="1024" width="768"/>
+    <splash src="resources/ios/splash/Default@2x~iphone.png" height="960" width="640"/>
+    <splash src="resources/ios/splash/Default~iphone.png" height="480" width="320"/>
+  </platform>
+</widget>

+ 50 - 0
ionic/gulpfile.js

@@ -0,0 +1,50 @@
+var gulp = require('gulp');
+var gutil = require('gulp-util');
+var bower = require('bower');
+var concat = require('gulp-concat');
+var sass = require('gulp-sass');
+var minifyCss = require('gulp-minify-css');
+var rename = require('gulp-rename');
+var sh = require('shelljs');
+
+var paths = {
+  sass: ['./scss/**/*.scss']
+};
+
+gulp.task('default', ['sass']);
+
+gulp.task('sass', function(done) {
+  gulp.src('./scss/ionic.app.scss')
+    .pipe(sass())
+    .pipe(gulp.dest('./www/css/'))
+    .pipe(minifyCss({
+      keepSpecialComments: 0
+    }))
+    .pipe(rename({ extname: '.min.css' }))
+    .pipe(gulp.dest('./www/css/'))
+    .on('end', done);
+});
+
+gulp.task('watch', function() {
+  gulp.watch(paths.sass, ['sass']);
+});
+
+gulp.task('install', ['git-check'], function() {
+  return bower.commands.install()
+    .on('log', function(data) {
+      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
+    });
+});
+
+gulp.task('git-check', function(done) {
+  if (!sh.which('git')) {
+    console.log(
+      '  ' + gutil.colors.red('Git is not installed.'),
+      '\n  Git, the version control system, is required to download Ionic.',
+      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
+      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
+    );
+    process.exit(1);
+  }
+  done();
+});

+ 83 - 0
ionic/hooks/README.md

@@ -0,0 +1,83 @@
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+# Cordova Hooks
+
+This directory may contain scripts used to customize cordova commands. This
+directory used to exist at `.cordova/hooks`, but has now been moved to the
+project root. Any scripts you add to these directories will be executed before
+and after the commands corresponding to the directory name. Useful for
+integrating your own build systems or integrating with version control systems.
+
+__Remember__: Make your scripts executable.
+
+## Hook Directories
+The following subdirectories will be used for hooks:
+
+    after_build/
+    after_compile/
+    after_docs/
+    after_emulate/
+    after_platform_add/
+    after_platform_rm/
+    after_platform_ls/
+    after_plugin_add/
+    after_plugin_ls/
+    after_plugin_rm/
+    after_plugin_search/
+    after_prepare/
+    after_run/
+    after_serve/
+    before_build/
+    before_compile/
+    before_docs/
+    before_emulate/
+    before_platform_add/
+    before_platform_rm/
+    before_platform_ls/
+    before_plugin_add/
+    before_plugin_ls/
+    before_plugin_rm/
+    before_plugin_search/
+    before_prepare/
+    before_run/
+    before_serve/
+    pre_package/ <-- Windows 8 and Windows Phone only.
+
+## Script Interface
+
+All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
+
+* CORDOVA_VERSION - The version of the Cordova-CLI.
+* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
+* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
+* CORDOVA_HOOK - Path to the hook that is being executed.
+* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
+
+If a script returns a non-zero exit code, then the parent cordova command will be aborted.
+
+
+## Writing hooks
+
+We highly recommend writting your hooks using Node.js so that they are
+cross-platform. Some good examples are shown here:
+
+[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
+

+ 94 - 0
ionic/hooks/after_prepare/010_add_platform_class.js

@@ -0,0 +1,94 @@
+#!/usr/bin/env node
+
+// Add Platform Class
+// v1.0
+// Automatically adds the platform class to the body tag
+// after the `prepare` command. By placing the platform CSS classes
+// directly in the HTML built for the platform, it speeds up
+// rendering the correct layout/style for the specific platform
+// instead of waiting for the JS to figure out the correct classes.
+
+var fs = require('fs');
+var path = require('path');
+
+var rootdir = process.argv[2];
+
+function addPlatformBodyTag(indexPath, platform) {
+  // add the platform class to the body tag
+  try {
+    var platformClass = 'platform-' + platform;
+    var cordovaClass = 'platform-cordova platform-webview';
+
+    var html = fs.readFileSync(indexPath, 'utf8');
+
+    var bodyTag = findBodyTag(html);
+    if(!bodyTag) return; // no opening body tag, something's wrong
+
+    if(bodyTag.indexOf(platformClass) > -1) return; // already added
+
+    var newBodyTag = bodyTag;
+
+    var classAttr = findClassAttr(bodyTag);
+    if(classAttr) {
+      // body tag has existing class attribute, add the classname
+      var endingQuote = classAttr.substring(classAttr.length-1);
+      var newClassAttr = classAttr.substring(0, classAttr.length-1);
+      newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
+      newBodyTag = bodyTag.replace(classAttr, newClassAttr);
+
+    } else {
+      // add class attribute to the body tag
+      newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
+    }
+
+    html = html.replace(bodyTag, newBodyTag);
+
+    fs.writeFileSync(indexPath, html, 'utf8');
+
+    process.stdout.write('add to body class: ' + platformClass + '\n');
+  } catch(e) {
+    process.stdout.write(e);
+  }
+}
+
+function findBodyTag(html) {
+  // get the body tag
+  try{
+    return html.match(/<body(?=[\s>])(.*?)>/gi)[0];
+  }catch(e){}
+}
+
+function findClassAttr(bodyTag) {
+  // get the body tag's class attribute
+  try{
+    return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
+  }catch(e){}
+}
+
+if (rootdir) {
+
+  // go through each of the platform directories that have been prepared
+  var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
+
+  for(var x=0; x<platforms.length; x++) {
+    // open up the index.html file at the www root
+    try {
+      var platform = platforms[x].trim().toLowerCase();
+      var indexPath;
+
+      if(platform == 'android') {
+        indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');
+      } else {
+        indexPath = path.join('platforms', platform, 'www', 'index.html');
+      }
+
+      if(fs.existsSync(indexPath)) {
+        addPlatformBodyTag(indexPath, platform);
+      }
+
+    } catch(e) {
+      process.stdout.write(e);
+    }
+  }
+
+}

+ 4 - 0
ionic/ionic.project

@@ -0,0 +1,4 @@
+{
+  "name": "ionic",
+  "app_id": ""
+}

+ 21 - 0
ionic/package.json

@@ -0,0 +1,21 @@
+{
+  "name": "ionic-project",
+  "version": "1.0.0",
+  "description": "An Ionic project",
+  "dependencies": {
+    "gulp": "^3.5.6",
+    "gulp-sass": "^1.3.3",
+    "gulp-concat": "^2.2.0",
+    "gulp-minify-css": "^0.3.0",
+    "gulp-rename": "^1.2.0"
+  },
+  "devDependencies": {
+    "bower": "^1.3.3",
+    "gulp-util": "^2.2.14",
+    "shelljs": "^0.3.0"
+  },
+  "cordovaPlugins": [],
+  "cordovaPlatforms": [
+    "ios"
+  ]
+}

+ 11 - 0
ionic/plugins/ios.json

@@ -0,0 +1,11 @@
+{
+    "prepare_queue": {
+        "installed": [],
+        "uninstalled": []
+    },
+    "config_munge": {
+        "files": {}
+    },
+    "installed_plugins": {},
+    "dependent_plugins": {}
+}

BIN
ionic/resources/android/icon/drawable-hdpi-icon.png


BIN
ionic/resources/android/icon/drawable-ldpi-icon.png


BIN
ionic/resources/android/icon/drawable-mdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xhdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xxhdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xxxhdpi-icon.png


BIN
ionic/resources/android/splash/drawable-land-hdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-ldpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-mdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xxxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-hdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-ldpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-mdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xxxhdpi-screen.png


BIN
ionic/resources/icon.png


BIN
ionic/resources/ios/icon/icon-40.png


BIN
ionic/resources/ios/icon/icon-40@2x.png


BIN
ionic/resources/ios/icon/icon-50.png


BIN
ionic/resources/ios/icon/icon-50@2x.png


BIN
ionic/resources/ios/icon/icon-60.png


BIN
ionic/resources/ios/icon/icon-60@2x.png


BIN
ionic/resources/ios/icon/icon-60@3x.png


BIN
ionic/resources/ios/icon/icon-72.png


BIN
ionic/resources/ios/icon/icon-72@2x.png


BIN
ionic/resources/ios/icon/icon-76.png


BIN
ionic/resources/ios/icon/icon-76@2x.png


BIN
ionic/resources/ios/icon/icon-small.png


BIN
ionic/resources/ios/icon/icon-small@2x.png


BIN
ionic/resources/ios/icon/icon-small@3x.png


BIN
ionic/resources/ios/icon/icon.png


BIN
ionic/resources/ios/icon/icon@2x.png


BIN
ionic/resources/ios/splash/Default-568h@2x~iphone.png


BIN
ionic/resources/ios/splash/Default-667h.png


BIN
ionic/resources/ios/splash/Default-736h.png


BIN
ionic/resources/ios/splash/Default-Landscape-736h.png


BIN
ionic/resources/ios/splash/Default-Landscape@2x~ipad.png


BIN
ionic/resources/ios/splash/Default-Landscape~ipad.png


BIN
ionic/resources/ios/splash/Default-Portrait@2x~ipad.png


BIN
ionic/resources/ios/splash/Default-Portrait~ipad.png


BIN
ionic/resources/ios/splash/Default@2x~iphone.png


BIN
ionic/resources/ios/splash/Default~iphone.png


BIN
ionic/resources/splash.png


+ 23 - 0
ionic/scss/ionic.app.scss

@@ -0,0 +1,23 @@
+/*
+To customize the look and feel of Ionic, you can override the variables
+in ionic's _variables.scss file.
+
+For example, you might change some of the default colors:
+
+$light:                           #fff !default;
+$stable:                          #f8f8f8 !default;
+$positive:                        #387ef5 !default;
+$calm:                            #11c1f3 !default;
+$balanced:                        #33cd5f !default;
+$energized:                       #ffc900 !default;
+$assertive:                       #ef473a !default;
+$royal:                           #886aea !default;
+$dark:                            #444 !default;
+*/
+
+// The path for our ionicons font files, relative to the built CSS in www/css
+$ionicons-font-path: "../lib/ionic/fonts" !default;
+
+// Include all of Ionic
+@import "www/lib/ionic/scss/ionic";
+

+ 1 - 0
ionic/www/css/style.css

@@ -0,0 +1 @@
+/* Empty. Add your own CSS if you like */

BIN
ionic/www/img/ionic.png


+ 0 - 32
ionic/www/index.html

@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
-    <title></title>
-
-    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
-    <link href="css/style.css" rel="stylesheet">
-
-    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
-    <link href="css/ionic.app.css" rel="stylesheet">
-    -->
-
-    <!-- ionic/angularjs js -->
-    <script src="lib/ionic/js/ionic.bundle.js"></script>
-    <script src="lib/ionic/js/angular/angular-resource.min.js"></script>
-
-    <!-- cordova script (this will be a 404 during development) -->
-    <script src="cordova.js"></script>
-
-    <!-- your app's js -->
-    <script src="js/app.js"></script>
-    <script src="js/controllers.js"></script>
-    <script src="js/services.js"></script>
-    
-  </head>
-
-  <body ng-app="starter">
-    <ion-nav-view></ion-nav-view>
-  </body>
-</html>

+ 72 - 0
ionic/www/js/app.js

@@ -0,0 +1,72 @@
+// Ionic Starter App
+
+// angular.module is a global place for creating, registering and retrieving Angular modules
+// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
+// the 2nd parameter is an array of 'requires'
+// 'starter.controllers' is found in controllers.js
+angular.module('starter', ['ionic', 'starter.controllers'])
+
+.run(function($ionicPlatform) {
+  $ionicPlatform.ready(function() {
+    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
+    // for form inputs)
+    if (window.cordova && window.cordova.plugins.Keyboard) {
+      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
+    }
+    if (window.StatusBar) {
+      // org.apache.cordova.statusbar required
+      StatusBar.styleDefault();
+    }
+  });
+})
+
+.config(function($stateProvider, $urlRouterProvider) {
+  $stateProvider
+
+  .state('app', {
+    url: "/app",
+    abstract: true,
+    templateUrl: "templates/menu.html",
+    controller: 'AppCtrl'
+  })
+
+  .state('app.search', {
+    url: "/search",
+    views: {
+      'menuContent': {
+        templateUrl: "templates/search.html"
+      }
+    }
+  })
+
+  .state('app.browse', {
+    url: "/browse",
+    views: {
+      'menuContent': {
+        templateUrl: "templates/browse.html"
+      }
+    }
+  })
+    .state('app.sessions', {
+    url: "/sessions",
+    views: {
+        'menuContent': {
+            templateUrl: "templates/sessions.html",
+            controller: 'SessionsCtrl'
+        }
+    }
+  })
+
+  .state('app.session', {
+    url: "/sessions/:sessionId",
+    views: {
+        'menuContent': {
+          templateUrl: "templates/session.html",
+          controller: 'SessionCtrl'
+      }
+    }
+  });
+
+  // if none of the above states are matched, use this as the fallback
+  $urlRouterProvider.otherwise('/app/sessions');
+});

+ 0 - 42
ionic/www/js/controllers.js

@@ -1,42 +0,0 @@
-angular.module('starter.controllers', ['starter.services'])
-
-.controller('AppCtrl', function($scope, $ionicModal, $timeout) {
-  // Form data for the login modal
-  $scope.loginData = {};
-
-  // Create the login modal that we will use later
-  $ionicModal.fromTemplateUrl('templates/login.html', {
-    scope: $scope
-  }).then(function(modal) {
-    $scope.modal = modal;
-  });
-
-  // Triggered in the login modal to close it
-  $scope.closeLogin = function() {
-    $scope.modal.hide();
-  };
-
-  // Open the login modal
-  $scope.login = function() {
-    $scope.modal.show();
-  };
-
-  // Perform the login action when the user submits the login form
-  $scope.doLogin = function() {
-    console.log('Doing login', $scope.loginData);
-
-    // Simulate a login delay. Remove this and replace with your login
-    // code if using a login system
-    $timeout(function() {
-      $scope.closeLogin();
-    }, 1000);
-  };
-})
-
-.controller('SessionsCtrl', function($scope, Session) {
-    $scope.sessions = Session.query();
-})
-
-.controller('SessionCtrl', function($scope, $stateParams, Session) {
-    $scope.session = Session.get({sessionId: $stateParams.sessionId});
-});

+ 5 - 0
ionic/www/js/services.js

@@ -0,0 +1,5 @@
+angular.module('starter.services', ['ngResource'])
+
+.factory('Session', function ($resource) {
+    return $resource('http://127.0.0.1:8000/hackathon/snippets/');
+});

Datei-Diff unterdrückt, da er zu groß ist
+ 7600 - 0
ionic/www/lib/ionic/css/ionic.css


Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
ionic/www/lib/ionic/css/ionic.min.css


BIN
ionic/www/lib/ionic/fonts/ionicons.eot


Datei-Diff unterdrückt, da er zu groß ist
+ 2230 - 0
ionic/www/lib/ionic/fonts/ionicons.svg


BIN
ionic/www/lib/ionic/fonts/ionicons.ttf


BIN
ionic/www/lib/ionic/fonts/ionicons.woff


Datei-Diff unterdrückt, da er zu groß ist
+ 4232 - 0
ionic/www/lib/ionic/js/angular-ui/angular-ui-router.js


Datei-Diff unterdrückt, da er zu groß ist
+ 7 - 0
ionic/www/lib/ionic/js/angular-ui/angular-ui-router.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 2137 - 0
ionic/www/lib/ionic/js/angular/angular-animate.js


Datei-Diff unterdrückt, da er zu groß ist
+ 33 - 0
ionic/www/lib/ionic/js/angular/angular-animate.min.js


+ 667 - 0
ionic/www/lib/ionic/js/angular/angular-resource.js

@@ -0,0 +1,667 @@
+/**
+ * @license AngularJS v1.3.13
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+var $resourceMinErr = angular.$$minErr('$resource');
+
+// Helper functions and regex to lookup a dotted path on an object
+// stopping at undefined/null.  The path must be composed of ASCII
+// identifiers (just like $parse)
+var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;
+
+function isValidDottedPath(path) {
+  return (path != null && path !== '' && path !== 'hasOwnProperty' &&
+      MEMBER_NAME_REGEX.test('.' + path));
+}
+
+function lookupDottedPath(obj, path) {
+  if (!isValidDottedPath(path)) {
+    throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path);
+  }
+  var keys = path.split('.');
+  for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) {
+    var key = keys[i];
+    obj = (obj !== null) ? obj[key] : undefined;
+  }
+  return obj;
+}
+
+/**
+ * Create a shallow copy of an object and clear other fields from the destination
+ */
+function shallowClearAndCopy(src, dst) {
+  dst = dst || {};
+
+  angular.forEach(dst, function(value, key) {
+    delete dst[key];
+  });
+
+  for (var key in src) {
+    if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
+      dst[key] = src[key];
+    }
+  }
+
+  return dst;
+}
+
+/**
+ * @ngdoc module
+ * @name ngResource
+ * @description
+ *
+ * # ngResource
+ *
+ * The `ngResource` module provides interaction support with RESTful services
+ * via the $resource service.
+ *
+ *
+ * <div doc-module-components="ngResource"></div>
+ *
+ * See {@link ngResource.$resource `$resource`} for usage.
+ */
+
+/**
+ * @ngdoc service
+ * @name $resource
+ * @requires $http
+ *
+ * @description
+ * A factory which creates a resource object that lets you interact with
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
+ *
+ * The returned resource object has action methods which provide high-level behaviors without
+ * the need to interact with the low level {@link ng.$http $http} service.
+ *
+ * Requires the {@link ngResource `ngResource`} module to be installed.
+ *
+ * By default, trailing slashes will be stripped from the calculated URLs,
+ * which can pose problems with server backends that do not expect that
+ * behavior.  This can be disabled by configuring the `$resourceProvider` like
+ * this:
+ *
+ * ```js
+     app.config(['$resourceProvider', function($resourceProvider) {
+       // Don't strip trailing slashes from calculated URLs
+       $resourceProvider.defaults.stripTrailingSlashes = false;
+     }]);
+ * ```
+ *
+ * @param {string} url A parametrized URL template with parameters prefixed by `:` as in
+ *   `/user/:username`. If you are using a URL with a port number (e.g.
+ *   `http://example.com:8080/api`), it will be respected.
+ *
+ *   If you are using a url with a suffix, just add the suffix, like this:
+ *   `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`
+ *   or even `$resource('http://example.com/resource/:resource_id.:format')`
+ *   If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
+ *   collapsed down to a single `.`.  If you need this sequence to appear and not collapse then you
+ *   can escape it with `/\.`.
+ *
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
+ *   `actions` methods. If any of the parameter value is a function, it will be executed every time
+ *   when a param value needs to be obtained for a request (unless the param was overridden).
+ *
+ *   Each key value in the parameter object is first bound to url template if present and then any
+ *   excess keys are appended to the url search query after the `?`.
+ *
+ *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
+ *   URL `/path/greet?salutation=Hello`.
+ *
+ *   If the parameter value is prefixed with `@` then the value for that parameter will be extracted
+ *   from the corresponding property on the `data` object (provided when calling an action method).  For
+ *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
+ *   will be `data.someProp`.
+ *
+ * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend
+ *   the default set of resource actions. The declaration should be created in the format of {@link
+ *   ng.$http#usage $http.config}:
+ *
+ *       {action1: {method:?, params:?, isArray:?, headers:?, ...},
+ *        action2: {method:?, params:?, isArray:?, headers:?, ...},
+ *        ...}
+ *
+ *   Where:
+ *
+ *   - **`action`** – {string} – The name of action. This name becomes the name of the method on
+ *     your resource object.
+ *   - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,
+ *     `DELETE`, `JSONP`, etc).
+ *   - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of
+ *     the parameter value is a function, it will be executed every time when a param value needs to
+ *     be obtained for a request (unless the param was overridden).
+ *   - **`url`** – {string} – action specific `url` override. The url templating is supported just
+ *     like for the resource-level urls.
+ *   - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,
+ *     see `returns` section.
+ *   - **`transformRequest`** –
+ *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ *     transform function or an array of such functions. The transform function takes the http
+ *     request body and headers and returns its transformed (typically serialized) version.
+ *     By default, transformRequest will contain one function that checks if the request data is
+ *     an object and serializes to using `angular.toJson`. To prevent this behavior, set
+ *     `transformRequest` to an empty array: `transformRequest: []`
+ *   - **`transformResponse`** –
+ *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ *     transform function or an array of such functions. The transform function takes the http
+ *     response body and headers and returns its transformed (typically deserialized) version.
+ *     By default, transformResponse will contain one function that checks if the response looks like
+ *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set
+ *     `transformResponse` to an empty array: `transformResponse: []`
+ *   - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
+ *     GET request, otherwise if a cache instance built with
+ *     {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
+ *     caching.
+ *   - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
+ *     should abort the request when resolved.
+ *   - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
+ *     XHR object. See
+ *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)
+ *     for more information.
+ *   - **`responseType`** - `{string}` - see
+ *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
+ *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
+ *     `response` and `responseError`. Both `response` and `responseError` interceptors get called
+ *     with `http response` object. See {@link ng.$http $http interceptors}.
+ *
+ * @param {Object} options Hash with custom settings that should extend the
+ *   default `$resourceProvider` behavior.  The only supported option is
+ *
+ *   Where:
+ *
+ *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing
+ *   slashes from any calculated URL will be stripped. (Defaults to true.)
+ *
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
+ *   optionally extended with custom `actions`. The default set contains these actions:
+ *   ```js
+ *   { 'get':    {method:'GET'},
+ *     'save':   {method:'POST'},
+ *     'query':  {method:'GET', isArray:true},
+ *     'remove': {method:'DELETE'},
+ *     'delete': {method:'DELETE'} };
+ *   ```
+ *
+ *   Calling these methods invoke an {@link ng.$http} with the specified http method,
+ *   destination and parameters. When the data is returned from the server then the object is an
+ *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it
+ *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
+ *   read, update, delete) on server-side data like this:
+ *   ```js
+ *   var User = $resource('/user/:userId', {userId:'@id'});
+ *   var user = User.get({userId:123}, function() {
+ *     user.abc = true;
+ *     user.$save();
+ *   });
+ *   ```
+ *
+ *   It is important to realize that invoking a $resource object method immediately returns an
+ *   empty reference (object or array depending on `isArray`). Once the data is returned from the
+ *   server the existing reference is populated with the actual data. This is a useful trick since
+ *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
+ *   object results in no rendering, once the data arrives from the server then the object is
+ *   populated with the data and the view automatically re-renders itself showing the new data. This
+ *   means that in most cases one never has to write a callback function for the action methods.
+ *
+ *   The action methods on the class object or instance object can be invoked with the following
+ *   parameters:
+ *
+ *   - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
+ *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
+ *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`
+ *
+ *   Success callback is called with (value, responseHeaders) arguments. Error callback is called
+ *   with (httpResponse) argument.
+ *
+ *   Class actions return empty instance (with additional properties below).
+ *   Instance actions return promise of the action.
+ *
+ *   The Resource instances and collection have these additional properties:
+ *
+ *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
+ *     instance or collection.
+ *
+ *     On success, the promise is resolved with the same resource instance or collection object,
+ *     updated with data from server. This makes it easy to use in
+ *     {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
+ *     rendering until the resource(s) are loaded.
+ *
+ *     On failure, the promise is resolved with the {@link ng.$http http response} object, without
+ *     the `resource` property.
+ *
+ *     If an interceptor object was provided, the promise will instead be resolved with the value
+ *     returned by the interceptor.
+ *
+ *   - `$resolved`: `true` after first server interaction is completed (either with success or
+ *      rejection), `false` before that. Knowing if the Resource has been resolved is useful in
+ *      data-binding.
+ *
+ * @example
+ *
+ * # Credit card resource
+ *
+ * ```js
+     // Define CreditCard class
+     var CreditCard = $resource('/user/:userId/card/:cardId',
+      {userId:123, cardId:'@id'}, {
+       charge: {method:'POST', params:{charge:true}}
+      });
+
+     // We can retrieve a collection from the server
+     var cards = CreditCard.query(function() {
+       // GET: /user/123/card
+       // server returns: [ {id:456, number:'1234', name:'Smith'} ];
+
+       var card = cards[0];
+       // each item is an instance of CreditCard
+       expect(card instanceof CreditCard).toEqual(true);
+       card.name = "J. Smith";
+       // non GET methods are mapped onto the instances
+       card.$save();
+       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
+       // server returns: {id:456, number:'1234', name: 'J. Smith'};
+
+       // our custom method is mapped as well.
+       card.$charge({amount:9.99});
+       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
+     });
+
+     // we can create an instance as well
+     var newCard = new CreditCard({number:'0123'});
+     newCard.name = "Mike Smith";
+     newCard.$save();
+     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
+     // server returns: {id:789, number:'0123', name: 'Mike Smith'};
+     expect(newCard.id).toEqual(789);
+ * ```
+ *
+ * The object returned from this function execution is a resource "class" which has "static" method
+ * for each action in the definition.
+ *
+ * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
+ * `headers`.
+ * When the data is returned from the server then the object is an instance of the resource type and
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
+ * operations (create, read, update, delete) on server-side data.
+
+   ```js
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(user) {
+       user.abc = true;
+       user.$save();
+     });
+   ```
+ *
+ * It's worth noting that the success callback for `get`, `query` and other methods gets passed
+ * in the response that came from the server as well as $http header getter function, so one
+ * could rewrite the above example and get access to http headers as:
+ *
+   ```js
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(u, getResponseHeaders){
+       u.abc = true;
+       u.$save(function(u, putResponseHeaders) {
+         //u => saved user object
+         //putResponseHeaders => $http header getter
+       });
+     });
+   ```
+ *
+ * You can also access the raw `$http` promise via the `$promise` property on the object returned
+ *
+   ```
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123})
+         .$promise.then(function(user) {
+           $scope.user = user;
+         });
+   ```
+
+ * # Creating a custom 'PUT' request
+ * In this example we create a custom method on our resource to make a PUT request
+ * ```js
+ *    var app = angular.module('app', ['ngResource', 'ngRoute']);
+ *
+ *    // Some APIs expect a PUT request in the format URL/object/ID
+ *    // Here we are creating an 'update' method
+ *    app.factory('Notes', ['$resource', function($resource) {
+ *    return $resource('/notes/:id', null,
+ *        {
+ *            'update': { method:'PUT' }
+ *        });
+ *    }]);
+ *
+ *    // In our controller we get the ID from the URL using ngRoute and $routeParams
+ *    // We pass in $routeParams and our Notes factory along with $scope
+ *    app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
+                                      function($scope, $routeParams, Notes) {
+ *    // First get a note object from the factory
+ *    var note = Notes.get({ id:$routeParams.id });
+ *    $id = note.id;
+ *
+ *    // Now call update passing in the ID first then the object you are updating
+ *    Notes.update({ id:$id }, note);
+ *
+ *    // This will PUT /notes/ID with the note object in the request payload
+ *    }]);
+ * ```
+ */
+angular.module('ngResource', ['ng']).
+  provider('$resource', function() {
+    var provider = this;
+
+    this.defaults = {
+      // Strip slashes by default
+      stripTrailingSlashes: true,
+
+      // Default actions configuration
+      actions: {
+        'get': {method: 'GET'},
+        'save': {method: 'POST'},
+        'query': {method: 'GET', isArray: true},
+        'remove': {method: 'DELETE'},
+        'delete': {method: 'DELETE'}
+      }
+    };
+
+    this.$get = ['$http', '$q', function($http, $q) {
+
+      var noop = angular.noop,
+        forEach = angular.forEach,
+        extend = angular.extend,
+        copy = angular.copy,
+        isFunction = angular.isFunction;
+
+      /**
+       * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+       * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set
+       * (pchar) allowed in path segments:
+       *    segment       = *pchar
+       *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+       *    pct-encoded   = "%" HEXDIG HEXDIG
+       *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+       *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+       *                     / "*" / "+" / "," / ";" / "="
+       */
+      function encodeUriSegment(val) {
+        return encodeUriQuery(val, true).
+          replace(/%26/gi, '&').
+          replace(/%3D/gi, '=').
+          replace(/%2B/gi, '+');
+      }
+
+
+      /**
+       * This method is intended for encoding *key* or *value* parts of query component. We need a
+       * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't
+       * have to be encoded per http://tools.ietf.org/html/rfc3986:
+       *    query       = *( pchar / "/" / "?" )
+       *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+       *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+       *    pct-encoded   = "%" HEXDIG HEXDIG
+       *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+       *                     / "*" / "+" / "," / ";" / "="
+       */
+      function encodeUriQuery(val, pctEncodeSpaces) {
+        return encodeURIComponent(val).
+          replace(/%40/gi, '@').
+          replace(/%3A/gi, ':').
+          replace(/%24/g, '$').
+          replace(/%2C/gi, ',').
+          replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
+      }
+
+      function Route(template, defaults) {
+        this.template = template;
+        this.defaults = extend({}, provider.defaults, defaults);
+        this.urlParams = {};
+      }
+
+      Route.prototype = {
+        setUrlParams: function(config, params, actionUrl) {
+          var self = this,
+            url = actionUrl || self.template,
+            val,
+            encodedVal;
+
+          var urlParams = self.urlParams = {};
+          forEach(url.split(/\W/), function(param) {
+            if (param === 'hasOwnProperty') {
+              throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
+            }
+            if (!(new RegExp("^\\d+$").test(param)) && param &&
+              (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
+              urlParams[param] = true;
+            }
+          });
+          url = url.replace(/\\:/g, ':');
+
+          params = params || {};
+          forEach(self.urlParams, function(_, urlParam) {
+            val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
+            if (angular.isDefined(val) && val !== null) {
+              encodedVal = encodeUriSegment(val);
+              url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
+                return encodedVal + p1;
+              });
+            } else {
+              url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
+                  leadingSlashes, tail) {
+                if (tail.charAt(0) == '/') {
+                  return tail;
+                } else {
+                  return leadingSlashes + tail;
+                }
+              });
+            }
+          });
+
+          // strip trailing slashes and set the url (unless this behavior is specifically disabled)
+          if (self.defaults.stripTrailingSlashes) {
+            url = url.replace(/\/+$/, '') || '/';
+          }
+
+          // then replace collapse `/.` if found in the last URL path segment before the query
+          // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
+          url = url.replace(/\/\.(?=\w+($|\?))/, '.');
+          // replace escaped `/\.` with `/.`
+          config.url = url.replace(/\/\\\./, '/.');
+
+
+          // set params - delegate param encoding to $http
+          forEach(params, function(value, key) {
+            if (!self.urlParams[key]) {
+              config.params = config.params || {};
+              config.params[key] = value;
+            }
+          });
+        }
+      };
+
+
+      function resourceFactory(url, paramDefaults, actions, options) {
+        var route = new Route(url, options);
+
+        actions = extend({}, provider.defaults.actions, actions);
+
+        function extractParams(data, actionParams) {
+          var ids = {};
+          actionParams = extend({}, paramDefaults, actionParams);
+          forEach(actionParams, function(value, key) {
+            if (isFunction(value)) { value = value(); }
+            ids[key] = value && value.charAt && value.charAt(0) == '@' ?
+              lookupDottedPath(data, value.substr(1)) : value;
+          });
+          return ids;
+        }
+
+        function defaultResponseInterceptor(response) {
+          return response.resource;
+        }
+
+        function Resource(value) {
+          shallowClearAndCopy(value || {}, this);
+        }
+
+        Resource.prototype.toJSON = function() {
+          var data = extend({}, this);
+          delete data.$promise;
+          delete data.$resolved;
+          return data;
+        };
+
+        forEach(actions, function(action, name) {
+          var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
+
+          Resource[name] = function(a1, a2, a3, a4) {
+            var params = {}, data, success, error;
+
+            /* jshint -W086 */ /* (purposefully fall through case statements) */
+            switch (arguments.length) {
+              case 4:
+                error = a4;
+                success = a3;
+              //fallthrough
+              case 3:
+              case 2:
+                if (isFunction(a2)) {
+                  if (isFunction(a1)) {
+                    success = a1;
+                    error = a2;
+                    break;
+                  }
+
+                  success = a2;
+                  error = a3;
+                  //fallthrough
+                } else {
+                  params = a1;
+                  data = a2;
+                  success = a3;
+                  break;
+                }
+              case 1:
+                if (isFunction(a1)) success = a1;
+                else if (hasBody) data = a1;
+                else params = a1;
+                break;
+              case 0: break;
+              default:
+                throw $resourceMinErr('badargs',
+                  "Expected up to 4 arguments [params, data, success, error], got {0} arguments",
+                  arguments.length);
+            }
+            /* jshint +W086 */ /* (purposefully fall through case statements) */
+
+            var isInstanceCall = this instanceof Resource;
+            var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
+            var httpConfig = {};
+            var responseInterceptor = action.interceptor && action.interceptor.response ||
+              defaultResponseInterceptor;
+            var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
+              undefined;
+
+            forEach(action, function(value, key) {
+              if (key != 'params' && key != 'isArray' && key != 'interceptor') {
+                httpConfig[key] = copy(value);
+              }
+            });
+
+            if (hasBody) httpConfig.data = data;
+            route.setUrlParams(httpConfig,
+              extend({}, extractParams(data, action.params || {}), params),
+              action.url);
+
+            var promise = $http(httpConfig).then(function(response) {
+              var data = response.data,
+                promise = value.$promise;
+
+              if (data) {
+                // Need to convert action.isArray to boolean in case it is undefined
+                // jshint -W018
+                if (angular.isArray(data) !== (!!action.isArray)) {
+                  throw $resourceMinErr('badcfg',
+                      'Error in resource configuration for action `{0}`. Expected response to ' +
+                      'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object',
+                    angular.isArray(data) ? 'array' : 'object');
+                }
+                // jshint +W018
+                if (action.isArray) {
+                  value.length = 0;
+                  forEach(data, function(item) {
+                    if (typeof item === "object") {
+                      value.push(new Resource(item));
+                    } else {
+                      // Valid JSON values may be string literals, and these should not be converted
+                      // into objects. These items will not have access to the Resource prototype
+                      // methods, but unfortunately there
+                      value.push(item);
+                    }
+                  });
+                } else {
+                  shallowClearAndCopy(data, value);
+                  value.$promise = promise;
+                }
+              }
+
+              value.$resolved = true;
+
+              response.resource = value;
+
+              return response;
+            }, function(response) {
+              value.$resolved = true;
+
+              (error || noop)(response);
+
+              return $q.reject(response);
+            });
+
+            promise = promise.then(
+              function(response) {
+                var value = responseInterceptor(response);
+                (success || noop)(value, response.headers);
+                return value;
+              },
+              responseErrorInterceptor);
+
+            if (!isInstanceCall) {
+              // we are creating instance / collection
+              // - set the initial promise
+              // - return the instance / collection
+              value.$promise = promise;
+              value.$resolved = false;
+
+              return value;
+            }
+
+            // instance call
+            return promise;
+          };
+
+
+          Resource.prototype['$' + name] = function(params, success, error) {
+            if (isFunction(params)) {
+              error = success; success = params; params = {};
+            }
+            var result = Resource[name].call(this, params, this, success, error);
+            return result.$promise || result;
+          };
+        });
+
+        Resource.bind = function(additionalParamDefaults) {
+          return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
+        };
+
+        return Resource;
+      }
+
+      return resourceFactory;
+    }];
+  });
+
+
+})(window, window.angular);

Datei-Diff unterdrückt, da er zu groß ist
+ 13 - 0
ionic/www/lib/ionic/js/angular/angular-resource.min.js


+ 681 - 0
ionic/www/lib/ionic/js/angular/angular-sanitize.js

@@ -0,0 +1,681 @@
+/**
+ * @license AngularJS v1.3.13
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+var $sanitizeMinErr = angular.$$minErr('$sanitize');
+
+/**
+ * @ngdoc module
+ * @name ngSanitize
+ * @description
+ *
+ * # ngSanitize
+ *
+ * The `ngSanitize` module provides functionality to sanitize HTML.
+ *
+ *
+ * <div doc-module-components="ngSanitize"></div>
+ *
+ * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
+ */
+
+/*
+ * HTML Parser By Misko Hevery (misko@hevery.com)
+ * based on:  HTML Parser By John Resig (ejohn.org)
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * // Use like so:
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $sanitize
+ * @kind function
+ *
+ * @description
+ *   The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
+ *   then serialized back to properly escaped html string. This means that no unsafe input can make
+ *   it into the returned string, however, since our parser is more strict than a typical browser
+ *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a
+ *   browser, won't make it through the sanitizer. The input may also contain SVG markup.
+ *   The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
+ *   `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
+ *
+ * @param {string} html HTML input.
+ * @returns {string} Sanitized HTML.
+ *
+ * @example
+   <example module="sanitizeExample" deps="angular-sanitize.js">
+   <file name="index.html">
+     <script>
+         angular.module('sanitizeExample', ['ngSanitize'])
+           .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
+             $scope.snippet =
+               '<p style="color:blue">an html\n' +
+               '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
+               'snippet</p>';
+             $scope.deliberatelyTrustDangerousSnippet = function() {
+               return $sce.trustAsHtml($scope.snippet);
+             };
+           }]);
+     </script>
+     <div ng-controller="ExampleController">
+        Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+       <table>
+         <tr>
+           <td>Directive</td>
+           <td>How</td>
+           <td>Source</td>
+           <td>Rendered</td>
+         </tr>
+         <tr id="bind-html-with-sanitize">
+           <td>ng-bind-html</td>
+           <td>Automatically uses $sanitize</td>
+           <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+           <td><div ng-bind-html="snippet"></div></td>
+         </tr>
+         <tr id="bind-html-with-trust">
+           <td>ng-bind-html</td>
+           <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
+           <td>
+           <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
+&lt;/div&gt;</pre>
+           </td>
+           <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
+         </tr>
+         <tr id="bind-default">
+           <td>ng-bind</td>
+           <td>Automatically escapes</td>
+           <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+           <td><div ng-bind="snippet"></div></td>
+         </tr>
+       </table>
+       </div>
+   </file>
+   <file name="protractor.js" type="protractor">
+     it('should sanitize the html snippet by default', function() {
+       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
+         toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
+     });
+
+     it('should inline raw snippet if bound to a trusted value', function() {
+       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
+         toBe("<p style=\"color:blue\">an html\n" +
+              "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
+              "snippet</p>");
+     });
+
+     it('should escape snippet without any filter', function() {
+       expect(element(by.css('#bind-default div')).getInnerHtml()).
+         toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
+              "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
+              "snippet&lt;/p&gt;");
+     });
+
+     it('should update', function() {
+       element(by.model('snippet')).clear();
+       element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
+       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
+         toBe('new <b>text</b>');
+       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
+         'new <b onclick="alert(1)">text</b>');
+       expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
+         "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
+     });
+   </file>
+   </example>
+ */
+function $SanitizeProvider() {
+  this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
+    return function(html) {
+      var buf = [];
+      htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
+        return !/^unsafe/.test($$sanitizeUri(uri, isImage));
+      }));
+      return buf.join('');
+    };
+  }];
+}
+
+function sanitizeText(chars) {
+  var buf = [];
+  var writer = htmlSanitizeWriter(buf, angular.noop);
+  writer.chars(chars);
+  return buf.join('');
+}
+
+
+// Regular Expressions for parsing tags and attributes
+var START_TAG_REGEXP =
+       /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
+  END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
+  ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
+  BEGIN_TAG_REGEXP = /^</,
+  BEGING_END_TAGE_REGEXP = /^<\//,
+  COMMENT_REGEXP = /<!--(.*?)-->/g,
+  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
+  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
+  SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+  // Match everything outside of normal chars and " (quote character)
+  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
+
+
+// Good source of info about elements and attributes
+// http://dev.w3.org/html5/spec/Overview.html#semantics
+// http://simon.html5.org/html-elements
+
+// Safe Void Elements - HTML5
+// http://dev.w3.org/html5/spec/Overview.html#void-elements
+var voidElements = makeMap("area,br,col,hr,img,wbr");
+
+// Elements that you can, intentionally, leave open (and which close themselves)
+// http://dev.w3.org/html5/spec/Overview.html#optional-tags
+var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
+    optionalEndTagInlineElements = makeMap("rp,rt"),
+    optionalEndTagElements = angular.extend({},
+                                            optionalEndTagInlineElements,
+                                            optionalEndTagBlockElements);
+
+// Safe Block Elements - HTML5
+var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
+        "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
+        "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
+
+// Inline Elements - HTML5
+var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
+        "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
+        "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
+
+// SVG Elements
+// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
+var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," +
+        "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," +
+        "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," +
+        "stop,svg,switch,text,title,tspan,use");
+
+// Special Elements (can contain anything)
+var specialElements = makeMap("script,style");
+
+var validElements = angular.extend({},
+                                   voidElements,
+                                   blockElements,
+                                   inlineElements,
+                                   optionalEndTagElements,
+                                   svgElements);
+
+//Attributes that have href and hence need to be sanitized
+var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
+
+var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
+    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
+    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
+    'scope,scrolling,shape,size,span,start,summary,target,title,type,' +
+    'valign,value,vspace,width');
+
+// SVG attributes (without "id" and "name" attributes)
+// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
+var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
+    'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +
+    'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +
+    'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +
+    'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +
+    'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +
+    'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +
+    'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +
+    'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +
+    'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +
+    'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +
+    'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +
+    'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +
+    'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +
+    'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +
+    'zoomAndPan');
+
+var validAttrs = angular.extend({},
+                                uriAttrs,
+                                svgAttrs,
+                                htmlAttrs);
+
+function makeMap(str) {
+  var obj = {}, items = str.split(','), i;
+  for (i = 0; i < items.length; i++) obj[items[i]] = true;
+  return obj;
+}
+
+
+/**
+ * @example
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ * @param {string} html string
+ * @param {object} handler
+ */
+function htmlParser(html, handler) {
+  if (typeof html !== 'string') {
+    if (html === null || typeof html === 'undefined') {
+      html = '';
+    } else {
+      html = '' + html;
+    }
+  }
+  var index, chars, match, stack = [], last = html, text;
+  stack.last = function() { return stack[stack.length - 1]; };
+
+  while (html) {
+    text = '';
+    chars = true;
+
+    // Make sure we're not in a script or style element
+    if (!stack.last() || !specialElements[stack.last()]) {
+
+      // Comment
+      if (html.indexOf("<!--") === 0) {
+        // comments containing -- are not allowed unless they terminate the comment
+        index = html.indexOf("--", 4);
+
+        if (index >= 0 && html.lastIndexOf("-->", index) === index) {
+          if (handler.comment) handler.comment(html.substring(4, index));
+          html = html.substring(index + 3);
+          chars = false;
+        }
+      // DOCTYPE
+      } else if (DOCTYPE_REGEXP.test(html)) {
+        match = html.match(DOCTYPE_REGEXP);
+
+        if (match) {
+          html = html.replace(match[0], '');
+          chars = false;
+        }
+      // end tag
+      } else if (BEGING_END_TAGE_REGEXP.test(html)) {
+        match = html.match(END_TAG_REGEXP);
+
+        if (match) {
+          html = html.substring(match[0].length);
+          match[0].replace(END_TAG_REGEXP, parseEndTag);
+          chars = false;
+        }
+
+      // start tag
+      } else if (BEGIN_TAG_REGEXP.test(html)) {
+        match = html.match(START_TAG_REGEXP);
+
+        if (match) {
+          // We only have a valid start-tag if there is a '>'.
+          if (match[4]) {
+            html = html.substring(match[0].length);
+            match[0].replace(START_TAG_REGEXP, parseStartTag);
+          }
+          chars = false;
+        } else {
+          // no ending tag found --- this piece should be encoded as an entity.
+          text += '<';
+          html = html.substring(1);
+        }
+      }
+
+      if (chars) {
+        index = html.indexOf("<");
+
+        text += index < 0 ? html : html.substring(0, index);
+        html = index < 0 ? "" : html.substring(index);
+
+        if (handler.chars) handler.chars(decodeEntities(text));
+      }
+
+    } else {
+      // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w].
+      html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
+        function(all, text) {
+          text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
+
+          if (handler.chars) handler.chars(decodeEntities(text));
+
+          return "";
+      });
+
+      parseEndTag("", stack.last());
+    }
+
+    if (html == last) {
+      throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
+                                        "of html: {0}", html);
+    }
+    last = html;
+  }
+
+  // Clean up any remaining tags
+  parseEndTag();
+
+  function parseStartTag(tag, tagName, rest, unary) {
+    tagName = angular.lowercase(tagName);
+    if (blockElements[tagName]) {
+      while (stack.last() && inlineElements[stack.last()]) {
+        parseEndTag("", stack.last());
+      }
+    }
+
+    if (optionalEndTagElements[tagName] && stack.last() == tagName) {
+      parseEndTag("", tagName);
+    }
+
+    unary = voidElements[tagName] || !!unary;
+
+    if (!unary)
+      stack.push(tagName);
+
+    var attrs = {};
+
+    rest.replace(ATTR_REGEXP,
+      function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
+        var value = doubleQuotedValue
+          || singleQuotedValue
+          || unquotedValue
+          || '';
+
+        attrs[name] = decodeEntities(value);
+    });
+    if (handler.start) handler.start(tagName, attrs, unary);
+  }
+
+  function parseEndTag(tag, tagName) {
+    var pos = 0, i;
+    tagName = angular.lowercase(tagName);
+    if (tagName)
+      // Find the closest opened tag of the same type
+      for (pos = stack.length - 1; pos >= 0; pos--)
+        if (stack[pos] == tagName)
+          break;
+
+    if (pos >= 0) {
+      // Close all the open elements, up the stack
+      for (i = stack.length - 1; i >= pos; i--)
+        if (handler.end) handler.end(stack[i]);
+
+      // Remove the open elements from the stack
+      stack.length = pos;
+    }
+  }
+}
+
+var hiddenPre=document.createElement("pre");
+var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
+/**
+ * decodes all entities into regular string
+ * @param value
+ * @returns {string} A string with decoded entities.
+ */
+function decodeEntities(value) {
+  if (!value) { return ''; }
+
+  // Note: IE8 does not preserve spaces at the start/end of innerHTML
+  // so we must capture them and reattach them afterward
+  var parts = spaceRe.exec(value);
+  var spaceBefore = parts[1];
+  var spaceAfter = parts[3];
+  var content = parts[2];
+  if (content) {
+    hiddenPre.innerHTML=content.replace(/</g,"&lt;");
+    // innerText depends on styling as it doesn't display hidden elements.
+    // Therefore, it's better to use textContent not to cause unnecessary
+    // reflows. However, IE<9 don't support textContent so the innerText
+    // fallback is necessary.
+    content = 'textContent' in hiddenPre ?
+      hiddenPre.textContent : hiddenPre.innerText;
+  }
+  return spaceBefore + content + spaceAfter;
+}
+
+/**
+ * Escapes all potentially dangerous characters, so that the
+ * resulting string can be safely inserted into attribute or
+ * element text.
+ * @param value
+ * @returns {string} escaped text
+ */
+function encodeEntities(value) {
+  return value.
+    replace(/&/g, '&amp;').
+    replace(SURROGATE_PAIR_REGEXP, function(value) {
+      var hi = value.charCodeAt(0);
+      var low = value.charCodeAt(1);
+      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
+    }).
+    replace(NON_ALPHANUMERIC_REGEXP, function(value) {
+      return '&#' + value.charCodeAt(0) + ';';
+    }).
+    replace(/</g, '&lt;').
+    replace(/>/g, '&gt;');
+}
+
+/**
+ * create an HTML/XML writer which writes to buffer
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
+ * @returns {object} in the form of {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * }
+ */
+function htmlSanitizeWriter(buf, uriValidator) {
+  var ignore = false;
+  var out = angular.bind(buf, buf.push);
+  return {
+    start: function(tag, attrs, unary) {
+      tag = angular.lowercase(tag);
+      if (!ignore && specialElements[tag]) {
+        ignore = tag;
+      }
+      if (!ignore && validElements[tag] === true) {
+        out('<');
+        out(tag);
+        angular.forEach(attrs, function(value, key) {
+          var lkey=angular.lowercase(key);
+          var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
+          if (validAttrs[lkey] === true &&
+            (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
+            out(' ');
+            out(key);
+            out('="');
+            out(encodeEntities(value));
+            out('"');
+          }
+        });
+        out(unary ? '/>' : '>');
+      }
+    },
+    end: function(tag) {
+        tag = angular.lowercase(tag);
+        if (!ignore && validElements[tag] === true) {
+          out('</');
+          out(tag);
+          out('>');
+        }
+        if (tag == ignore) {
+          ignore = false;
+        }
+      },
+    chars: function(chars) {
+        if (!ignore) {
+          out(encodeEntities(chars));
+        }
+      }
+  };
+}
+
+
+// define ngSanitize module and register $sanitize service
+angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
+
+/* global sanitizeText: false */
+
+/**
+ * @ngdoc filter
+ * @name linky
+ * @kind function
+ *
+ * @description
+ * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
+ * plain email address links.
+ *
+ * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
+ *
+ * @param {string} text Input text.
+ * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
+ * @returns {string} Html-linkified text.
+ *
+ * @usage
+   <span ng-bind-html="linky_expression | linky"></span>
+ *
+ * @example
+   <example module="linkyExample" deps="angular-sanitize.js">
+     <file name="index.html">
+       <script>
+         angular.module('linkyExample', ['ngSanitize'])
+           .controller('ExampleController', ['$scope', function($scope) {
+             $scope.snippet =
+               'Pretty text with some links:\n'+
+               'http://angularjs.org/,\n'+
+               'mailto:us@somewhere.org,\n'+
+               'another@somewhere.org,\n'+
+               'and one more: ftp://127.0.0.1/.';
+             $scope.snippetWithTarget = 'http://angularjs.org/';
+           }]);
+       </script>
+       <div ng-controller="ExampleController">
+       Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+       <table>
+         <tr>
+           <td>Filter</td>
+           <td>Source</td>
+           <td>Rendered</td>
+         </tr>
+         <tr id="linky-filter">
+           <td>linky filter</td>
+           <td>
+             <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
+           </td>
+           <td>
+             <div ng-bind-html="snippet | linky"></div>
+           </td>
+         </tr>
+         <tr id="linky-target">
+          <td>linky target</td>
+          <td>
+            <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
+          </td>
+          <td>
+            <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
+          </td>
+         </tr>
+         <tr id="escaped-html">
+           <td>no filter</td>
+           <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
+           <td><div ng-bind="snippet"></div></td>
+         </tr>
+       </table>
+     </file>
+     <file name="protractor.js" type="protractor">
+       it('should linkify the snippet with urls', function() {
+         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
+             toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
+                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');
+         expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
+       });
+
+       it('should not linkify snippet without the linky filter', function() {
+         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
+             toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
+                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');
+         expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
+       });
+
+       it('should update', function() {
+         element(by.model('snippet')).clear();
+         element(by.model('snippet')).sendKeys('new http://link.');
+         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
+             toBe('new http://link.');
+         expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
+         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
+             .toBe('new http://link.');
+       });
+
+       it('should work with the target property', function() {
+        expect(element(by.id('linky-target')).
+            element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
+            toBe('http://angularjs.org/');
+        expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
+       });
+     </file>
+   </example>
+ */
+angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
+  var LINKY_URL_REGEXP =
+        /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
+      MAILTO_REGEXP = /^mailto:/;
+
+  return function(text, target) {
+    if (!text) return text;
+    var match;
+    var raw = text;
+    var html = [];
+    var url;
+    var i;
+    while ((match = raw.match(LINKY_URL_REGEXP))) {
+      // We can not end in these as they are sometimes found at the end of the sentence
+      url = match[0];
+      // if we did not match ftp/http/www/mailto then assume mailto
+      if (!match[2] && !match[4]) {
+        url = (match[3] ? 'http://' : 'mailto:') + url;
+      }
+      i = match.index;
+      addText(raw.substr(0, i));
+      addLink(url, match[0].replace(MAILTO_REGEXP, ''));
+      raw = raw.substring(i + match[0].length);
+    }
+    addText(raw);
+    return $sanitize(html.join(''));
+
+    function addText(text) {
+      if (!text) {
+        return;
+      }
+      html.push(sanitizeText(text));
+    }
+
+    function addLink(url, text) {
+      html.push('<a ');
+      if (angular.isDefined(target)) {
+        html.push('target="',
+                  target,
+                  '" ');
+      }
+      html.push('href="',
+                url.replace(/"/g, '&quot;'),
+                '">');
+      addText(text);
+      html.push('</a>');
+    }
+  };
+}]);
+
+
+})(window, window.angular);

Datei-Diff unterdrückt, da er zu groß ist
+ 16 - 0
ionic/www/lib/ionic/js/angular/angular-sanitize.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 26130 - 0
ionic/www/lib/ionic/js/angular/angular.js


Datei-Diff unterdrückt, da er zu groß ist
+ 250 - 0
ionic/www/lib/ionic/js/angular/angular.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 13121 - 0
ionic/www/lib/ionic/js/ionic-angular.js


Datei-Diff unterdrückt, da er zu groß ist
+ 18 - 0
ionic/www/lib/ionic/js/ionic-angular.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 54615 - 0
ionic/www/lib/ionic/js/ionic.bundle.js


Datei-Diff unterdrückt, da er zu groß ist
+ 386 - 0
ionic/www/lib/ionic/js/ionic.bundle.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 8269 - 0
ionic/www/lib/ionic/js/ionic.js


Datei-Diff unterdrückt, da er zu groß ist
+ 17 - 0
ionic/www/lib/ionic/js/ionic.min.js


+ 170 - 0
ionic/www/lib/ionic/scss/_action-sheet.scss

@@ -0,0 +1,170 @@
+/**
+ * Action Sheets
+ * --------------------------------------------------
+ */
+
+.action-sheet-backdrop {
+  @include transition(background-color 150ms ease-in-out);
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: $z-index-action-sheet;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0,0,0,0);
+
+  &.active {
+    background-color: rgba(0,0,0,0.4);
+  }
+}
+
+.action-sheet-wrapper {
+  @include translate3d(0, 100%, 0);
+  @include transition(all cubic-bezier(.36, .66, .04, 1) 500ms);
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  width: 100%;
+  max-width: 500px;
+  margin: auto;
+}
+
+.action-sheet-up {
+  @include translate3d(0, 0, 0);
+}
+
+.action-sheet {
+  margin-left: $sheet-margin;
+  margin-right: $sheet-margin;
+  width: auto;
+  z-index: $z-index-action-sheet;
+  overflow: hidden;
+
+  .button {
+    display: block;
+    padding: 1px;
+    width: 100%;
+    border-radius: 0;
+    border-color: $sheet-options-border-color;
+    background-color: transparent;
+
+    color: $sheet-options-text-color;
+    font-size: 21px;
+
+    &:hover {
+      color: $sheet-options-text-color;
+    }
+    &.destructive {
+      color: #ff3b30;
+      &:hover {
+        color: #ff3b30;
+      }
+    }
+  }
+
+  .button.active, .button.activated {
+    box-shadow: none;
+    border-color: $sheet-options-border-color;
+    color: $sheet-options-text-color;
+    background: $sheet-options-bg-active-color;
+  }
+}
+
+.action-sheet-has-icons .icon {
+  position: absolute;
+  left: 16px;
+}
+
+.action-sheet-title {
+  padding: $sheet-margin * 2;
+  color: #8f8f8f;
+  text-align: center;
+  font-size: 13px;
+}
+
+.action-sheet-group {
+  margin-bottom: $sheet-margin;
+  border-radius: $sheet-border-radius;
+  background-color: #fff;
+  overflow: hidden;
+
+  .button {
+    border-width: 1px 0px 0px 0px;
+  }
+  .button:first-child:last-child {
+    border-width: 0;
+  }
+}
+
+.action-sheet-options {
+  background: $sheet-options-bg-color;
+}
+
+.action-sheet-cancel {
+  .button {
+    font-weight: 500;
+  }
+}
+
+.action-sheet-open {
+  pointer-events: none;
+
+  &.modal-open .modal {
+    pointer-events: none;
+  }
+
+  .action-sheet-backdrop {
+    pointer-events: auto;
+  }
+}
+
+
+.platform-android {
+
+  .action-sheet-backdrop.active {
+    background-color: rgba(0,0,0,0.2);
+  }
+
+  .action-sheet {
+    margin: 0;
+
+    .action-sheet-title,
+    .button {
+      text-align: left;
+      border-color: transparent;
+      font-size: 16px;
+      color: inherit;
+    }
+
+    .action-sheet-title {
+      font-size: 14px;
+      padding: 16px;
+      color: #666;
+    }
+
+    .button.active,
+    .button.activated {
+      background: #e8e8e8;
+    }
+  }
+
+  .action-sheet-group {
+    margin: 0;
+    border-radius: 0;
+    background-color: #fafafa;
+  }
+
+  .action-sheet-cancel {
+    display: none;
+  }
+
+  .action-sheet-has-icons {
+
+    .button {
+      padding-left: 56px;
+    }
+
+  }
+
+}

+ 48 - 0
ionic/www/lib/ionic/scss/_animations.scss

@@ -0,0 +1,48 @@
+
+// Slide up from the bottom, used for modals
+// -------------------------------
+
+.slide-in-up {
+  @include translate3d(0, 100%, 0);
+}
+.slide-in-up.ng-enter,
+.slide-in-up > .ng-enter {
+  @include transition(all cubic-bezier(.1, .7, .1, 1) 400ms);
+}
+.slide-in-up.ng-enter-active,
+.slide-in-up > .ng-enter-active {
+  @include translate3d(0, 0, 0);
+}
+
+.slide-in-up.ng-leave,
+.slide-in-up > .ng-leave {
+  @include transition(all ease-in-out 250ms);
+}
+
+
+// Scale Out
+// Scale from hero (1 in this case) to zero
+// -------------------------------
+
+@-webkit-keyframes scaleOut {
+  from { -webkit-transform: scale(1); opacity: 1; }
+  to { -webkit-transform: scale(0.8); opacity: 0; }
+}
+@keyframes scaleOut {
+  from { transform: scale(1); opacity: 1; }
+  to { transform: scale(0.8); opacity: 0; }
+}
+
+
+// Super Scale In
+// Scale from super (1.x) to duper (1 in this case)
+// -------------------------------
+
+@-webkit-keyframes superScaleIn {
+  from { -webkit-transform: scale(1.2); opacity: 0; }
+  to { -webkit-transform: scale(1); opacity: 1 }
+}
+@keyframes superScaleIn {
+  from { transform: scale(1.2); opacity: 0; }
+  to { transform: scale(1); opacity: 1; }
+}

+ 24 - 0
ionic/www/lib/ionic/scss/_backdrop.scss

@@ -0,0 +1,24 @@
+
+.backdrop {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: $z-index-backdrop;
+
+  width: 100%;
+  height: 100%;
+
+  background-color: $loading-backdrop-bg-color;
+
+  visibility: hidden;
+  opacity: 0;
+
+  &.visible {
+    visibility: visible;
+  }
+  &.active {
+    opacity: 1;
+  }
+
+  @include transition($loading-backdrop-fadein-duration opacity linear);
+}

+ 62 - 0
ionic/www/lib/ionic/scss/_badge.scss

@@ -0,0 +1,62 @@
+
+/**
+ * Badges
+ * --------------------------------------------------
+ */
+
+.badge {
+  @include badge-style($badge-default-bg, $badge-default-text);
+  z-index: $z-index-badge;
+  display: inline-block;
+  padding: 3px 8px;
+  min-width: 10px;
+  border-radius: $badge-border-radius;
+  vertical-align: baseline;
+  text-align: center;
+  white-space: nowrap;
+  font-weight: $badge-font-weight;
+  font-size: $badge-font-size;
+  line-height: $badge-line-height;
+
+  &:empty {
+    display: none;
+  }
+}
+
+//Be sure to override specificity of rule that 'badge color matches tab color by default'
+.tabs .tab-item .badge,
+.badge {
+  &.badge-light {
+    @include badge-style($badge-light-bg, $badge-light-text);
+  }
+  &.badge-stable {
+    @include badge-style($badge-stable-bg, $badge-stable-text);
+  }
+  &.badge-positive {
+    @include badge-style($badge-positive-bg, $badge-positive-text);
+  }
+  &.badge-calm {
+    @include badge-style($badge-calm-bg, $badge-calm-text);
+  }
+  &.badge-assertive {
+    @include badge-style($badge-assertive-bg, $badge-assertive-text);
+  }
+  &.badge-balanced {
+    @include badge-style($badge-balanced-bg, $badge-balanced-text);
+  }
+  &.badge-energized {
+    @include badge-style($badge-energized-bg, $badge-energized-text);
+  }
+  &.badge-royal {
+    @include badge-style($badge-royal-bg, $badge-royal-text);
+  }
+  &.badge-dark {
+    @include badge-style($badge-dark-bg, $badge-dark-text);
+  }
+}
+
+// Quick fix for labels/badges in buttons
+.button .badge {
+  position: relative;
+  top: -1px;
+}

+ 404 - 0
ionic/www/lib/ionic/scss/_bar.scss

@@ -0,0 +1,404 @@
+
+/**
+ * Bar (Headers and Footers)
+ * --------------------------------------------------
+ */
+
+.bar {
+  @include display-flex();
+  @include translate3d(0,0,0);
+  @include user-select(none);
+  position: absolute;
+  right: 0;
+  left: 0;
+  z-index: $z-index-bar;
+
+  box-sizing: border-box;
+  padding: $bar-padding-portrait;
+
+  width: 100%;
+  height: $bar-height;
+  border-width: 0;
+  border-style: solid;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid $bar-default-border;
+
+  background-color: $bar-default-bg;
+
+  /* border-width: 1px will actually create 2 device pixels on retina */
+  /* this nifty trick sets an actual 1px border on hi-res displays */
+  background-size: 0;
+  @media (min--moz-device-pixel-ratio: 1.5),
+         (-webkit-min-device-pixel-ratio: 1.5),
+         (min-device-pixel-ratio: 1.5),
+         (min-resolution: 144dpi),
+         (min-resolution: 1.5dppx) {
+    border: none;
+    background-image: linear-gradient(0deg, $bar-default-border, $bar-default-border 50%, transparent 50%);
+    background-position: bottom;
+    background-size: 100% 1px;
+    background-repeat: no-repeat;
+  }
+
+  &.bar-clear {
+    border: none;
+    background: none;
+    color: #fff;
+
+    .button {
+      color: #fff;
+    }
+    .title {
+      color: #fff;
+    }
+  }
+
+  &.item-input-inset {
+    .item-input-wrapper {
+      margin-top: -1px;
+
+      input {
+        padding-left: 8px;
+        width: 94%;
+        height: 28px;
+        background: transparent;
+      }
+    }
+  }
+
+  &.bar-light {
+    @include bar-style($bar-light-bg, $bar-light-border, $bar-light-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-light-border, $bar-light-border 50%, transparent 50%);
+    }
+  }
+  &.bar-stable {
+    @include bar-style($bar-stable-bg, $bar-stable-border, $bar-stable-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-stable-border, $bar-stable-border 50%, transparent 50%);
+    }
+  }
+  &.bar-positive {
+    @include bar-style($bar-positive-bg, $bar-positive-border, $bar-positive-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-positive-border, $bar-positive-border 50%, transparent 50%);
+    }
+  }
+  &.bar-calm {
+    @include bar-style($bar-calm-bg, $bar-calm-border, $bar-calm-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-calm-border, $bar-calm-border 50%, transparent 50%);
+    }
+  }
+  &.bar-assertive {
+    @include bar-style($bar-assertive-bg, $bar-assertive-border, $bar-assertive-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-assertive-border, $bar-assertive-border 50%, transparent 50%);
+    }
+  }
+  &.bar-balanced {
+    @include bar-style($bar-balanced-bg, $bar-balanced-border, $bar-balanced-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-balanced-border, $bar-positive-border 50%, transparent 50%);
+    }
+  }
+  &.bar-energized {
+    @include bar-style($bar-energized-bg, $bar-energized-border, $bar-energized-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-energized-border, $bar-energized-border 50%, transparent 50%);
+    }
+  }
+  &.bar-royal {
+    @include bar-style($bar-royal-bg, $bar-royal-border, $bar-royal-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-royal-border, $bar-royal-border 50%, transparent 50%);
+    }
+  }
+  &.bar-dark {
+    @include bar-style($bar-dark-bg, $bar-dark-border, $bar-dark-text);
+    &.bar-footer{
+      background-image: linear-gradient(180deg, $bar-dark-border, $bar-dark-border 50%, transparent 50%);
+    }
+  }
+
+  // Title inside of a bar is centered
+  .title {
+    position: absolute;
+
+    top: 0;
+    right: 0;
+    left: 0;
+    z-index: $z-index-bar-title;
+    overflow: hidden;
+
+    margin: 0 10px;
+
+    min-width: 30px;
+    height: $bar-height - 1;
+
+    text-align: center;
+
+    // Go into ellipsis if too small
+    text-overflow: ellipsis;
+    white-space: nowrap;
+
+    font-size: $bar-title-font-size;
+    font-weight: $headings-font-weight;
+
+    line-height: $bar-height;
+
+    &.title-left {
+      text-align: left;
+    }
+    &.title-right {
+      text-align: right;
+    }
+  }
+
+  .title a {
+    color: inherit;
+  }
+
+  .button {
+    z-index: $z-index-bar-button;
+    padding: 0 $button-bar-button-padding;
+    min-width: initial;
+    min-height: $button-bar-button-height - 1;
+    font-weight: 400;
+    font-size: $button-bar-button-font-size;
+    line-height: $button-bar-button-height;
+
+    &.button-icon:before,
+    .icon:before,
+    &.icon:before,
+    &.icon-left:before,
+    &.icon-right:before {
+      padding-right: 2px;
+      padding-left: 2px;
+      font-size: $button-bar-button-icon-size;
+      line-height: $button-bar-button-height;
+    }
+
+    &.button-icon {
+      font-size: $bar-title-font-size;
+      .icon:before,
+      &:before,
+      &.icon-left:before,
+      &.icon-right:before {
+        vertical-align: top;
+        font-size: $button-large-icon-size;
+        line-height: $button-bar-button-height;
+      }
+    }
+    &.button-clear {
+      padding-right: 2px;
+      padding-left: 2px;
+      font-weight: 300;
+      font-size: $bar-title-font-size;
+
+      .icon:before,
+      &.icon:before,
+      &.icon-left:before,
+      &.icon-right:before {
+        font-size: $button-large-icon-size;
+        line-height: $button-bar-button-height;
+      }
+    }
+
+    &.back-button {
+      display: block;
+      margin-right: 5px;
+      padding: 0;
+      white-space: nowrap;
+      font-weight: 400;
+    }
+
+    &.back-button.active,
+    &.back-button.activated {
+      opacity: 0.2;
+    }
+  }
+
+  .button-bar > .button,
+  .buttons > .button {
+    min-height: $button-bar-button-height - 1;
+    line-height: $button-bar-button-height;
+  }
+
+  .button-bar + .button,
+  .button + .button-bar {
+    margin-left: 5px;
+  }
+
+  // Android 4.4 messes with the display property
+  .buttons,
+  .buttons.primary-buttons,
+  .buttons.secondary-buttons {
+    display: inherit;
+  }
+  .buttons span {
+    display: inline-block;
+  }
+  .buttons-left span {
+    margin-right: 5px;
+    display: inherit;
+  }
+  .buttons-right span {
+    margin-left: 5px;
+    display: inherit;
+  }
+
+  // Place the last button in a bar on the right of the bar
+  .title + .button:last-child,
+  > .button + .button:last-child,
+  > .button.pull-right,
+  .buttons.pull-right,
+  .title + .buttons {
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    bottom: 5px;
+  }
+
+}
+
+.platform-android {
+
+  .nav-bar-has-subheader .bar {
+    background-image: none;
+  }
+
+  .bar {
+
+    .back-button .icon:before {
+      font-size: 24px;
+    }
+
+    .title {
+      font-size: 19px;
+      line-height: $bar-height;
+    }
+  }
+
+}
+
+// Default styles for buttons inside of styled bars
+.bar-light {
+  .button {
+    @include button-style($bar-light-bg, $bar-light-border, $bar-light-active-bg, $bar-light-active-border, $bar-light-text);
+    @include button-clear($bar-light-text, $bar-title-font-size);
+  }
+}
+.bar-stable {
+  .button {
+    @include button-style($bar-stable-bg, $bar-stable-border, $bar-stable-active-bg, $bar-stable-active-border, $bar-stable-text);
+    @include button-clear($bar-stable-text, $bar-title-font-size);
+  }
+}
+.bar-positive {
+  .button {
+    @include button-style($bar-positive-bg, $bar-positive-border, $bar-positive-active-bg, $bar-positive-active-border, $bar-positive-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-calm {
+  .button {
+    @include button-style($bar-calm-bg, $bar-calm-border, $bar-calm-active-bg, $bar-calm-active-border, $bar-calm-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-assertive {
+  .button {
+    @include button-style($bar-assertive-bg, $bar-assertive-border, $bar-assertive-active-bg, $bar-assertive-active-border, $bar-assertive-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-balanced {
+  .button {
+    @include button-style($bar-balanced-bg, $bar-balanced-border, $bar-balanced-active-bg, $bar-balanced-active-border, $bar-balanced-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-energized {
+  .button {
+    @include button-style($bar-energized-bg, $bar-energized-border, $bar-energized-active-bg, $bar-energized-active-border, $bar-energized-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-royal {
+  .button {
+    @include button-style($bar-royal-bg, $bar-royal-border, $bar-royal-active-bg, $bar-royal-active-border, $bar-royal-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+.bar-dark {
+  .button {
+    @include button-style($bar-dark-bg, $bar-dark-border, $bar-dark-active-bg, $bar-dark-active-border, $bar-dark-text);
+    @include button-clear(#fff, $bar-title-font-size);
+  }
+}
+
+// Header at top
+.bar-header {
+  top: 0;
+  border-top-width: 0;
+  border-bottom-width: 1px;
+  &.has-tabs-top{
+    border-bottom-width: 0px;
+    background-image: none;
+  }
+}
+.tabs-top .bar-header{
+  border-bottom-width: 0px;
+  background-image: none;
+}
+
+// Footer at bottom
+.bar-footer {
+  bottom: 0;
+  border-top-width: 1px;
+  border-bottom-width: 0;
+  background-position: top;
+
+  height: $bar-footer-height;
+
+  &.item-input-inset {
+    position: absolute;
+  }
+}
+
+// Don't render padding if the bar is just for tabs
+.bar-tabs {
+  padding: 0;
+}
+
+.bar-subheader {
+  top: $bar-height;
+  display: block;
+
+  height: $bar-subheader-height;
+}
+.bar-subfooter {
+  bottom: $bar-footer-height;
+  display: block;
+
+  height: $bar-subfooter-height;
+}
+
+.nav-bar-block {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: $z-index-bar;
+}
+
+.bar .back-button.hide,
+.bar .buttons .hide {
+  display: none;
+}
+
+.nav-bar-tabs-top .bar {
+  background-image: none;
+}
+

+ 54 - 0
ionic/www/lib/ionic/scss/_button-bar.scss

@@ -0,0 +1,54 @@
+
+/**
+ * Button Bar
+ * --------------------------------------------------
+ */
+
+.button-bar {
+  @include display-flex();
+  @include flex(1);
+  width: 100%;
+
+  &.button-bar-inline {
+    display: block;
+    width: auto;
+
+    @include clearfix();
+
+    > .button {
+      width: auto;
+      display: inline-block;
+      float: left;
+    }
+  }
+}
+
+.button-bar > .button {
+  @include flex(1);
+  display: block;
+  
+  overflow: hidden;
+
+  padding: 0 16px;
+
+  width: 0;
+
+  border-width: 1px 0px 1px 1px;
+  border-radius: 0;
+  text-align: center;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+
+  &:before,
+  .icon:before {
+    line-height: 44px;
+  }
+
+  &:first-child {
+    border-radius: $button-border-radius 0px 0px $button-border-radius;
+  }
+  &:last-child {
+    border-right-width: 1px;
+    border-radius: 0px $button-border-radius $button-border-radius 0px;
+  }
+}

+ 252 - 0
ionic/www/lib/ionic/scss/_button.scss

@@ -0,0 +1,252 @@
+
+/**
+ * Buttons
+ * --------------------------------------------------
+ */
+
+.button {
+  // set the color defaults
+  @include button-style($button-default-bg, $button-default-border, $button-default-active-bg, $button-default-active-border, $button-default-text);
+
+  position: relative;
+  display: inline-block;
+  margin: 0;
+  padding: 0 $button-padding;
+
+  min-width: ($button-padding * 3) + $button-font-size;
+  min-height: $button-height + 5px;
+
+  border-width: $button-border-width;
+  border-style: solid;
+  border-radius: $button-border-radius;
+
+  vertical-align: top;
+  text-align: center;
+
+  text-overflow: ellipsis;
+  font-size: $button-font-size;
+  line-height: $button-height - $button-border-width + 1px;
+
+  cursor: pointer;
+
+  &:after {
+    // used to create a larger button "hit" area
+    position: absolute;
+    top: -6px;
+    right: -6px;
+    bottom: -6px;
+    left: -6px;
+    content: ' ';
+  }
+
+  .icon {
+    vertical-align: top;
+    pointer-events: none;
+  }
+
+  .icon:before,
+  &.icon:before,
+  &.icon-left:before,
+  &.icon-right:before {
+    display: inline-block;
+    padding: 0 0 $button-border-width 0;
+    vertical-align: inherit;
+    font-size: $button-icon-size;
+    line-height: $button-height - $button-border-width;
+    pointer-events: none;
+  }
+  &.icon-left:before {
+    float: left;
+    padding-right: .2em;
+    padding-left: 0;
+  }
+  &.icon-right:before {
+    float: right;
+    padding-right: 0;
+    padding-left: .2em;
+  }
+
+  &.button-block, &.button-full {
+    margin-top: $button-block-margin;
+    margin-bottom: $button-block-margin;
+  }
+
+  &.button-light {
+    @include button-style($button-light-bg, $button-light-border, $button-light-active-bg, $button-light-active-border, $button-light-text);
+    @include button-clear($button-light-border);
+    @include button-outline($button-light-border);
+  }
+
+  &.button-stable {
+    @include button-style($button-stable-bg, $button-stable-border, $button-stable-active-bg, $button-stable-active-border, $button-stable-text);
+    @include button-clear($button-stable-border);
+    @include button-outline($button-stable-border);
+  }
+
+  &.button-positive {
+    @include button-style($button-positive-bg, $button-positive-border, $button-positive-active-bg, $button-positive-active-border, $button-positive-text);
+    @include button-clear($button-positive-bg);
+    @include button-outline($button-positive-bg);
+  }
+
+  &.button-calm {
+    @include button-style($button-calm-bg, $button-calm-border, $button-calm-active-bg, $button-calm-active-border, $button-calm-text);
+    @include button-clear($button-calm-bg);
+    @include button-outline($button-calm-bg);
+  }
+
+  &.button-assertive {
+    @include button-style($button-assertive-bg, $button-assertive-border, $button-assertive-active-bg, $button-assertive-active-border, $button-assertive-text);
+    @include button-clear($button-assertive-bg);
+    @include button-outline($button-assertive-bg);
+  }
+
+  &.button-balanced {
+    @include button-style($button-balanced-bg, $button-balanced-border, $button-balanced-active-bg, $button-balanced-active-border, $button-balanced-text);
+    @include button-clear($button-balanced-bg);
+    @include button-outline($button-balanced-bg);
+  }
+
+  &.button-energized {
+    @include button-style($button-energized-bg, $button-energized-border, $button-energized-active-bg, $button-energized-active-border, $button-energized-text);
+    @include button-clear($button-energized-bg);
+    @include button-outline($button-energized-bg);
+  }
+
+  &.button-royal {
+    @include button-style($button-royal-bg, $button-royal-border, $button-royal-active-bg, $button-royal-active-border, $button-royal-text);
+    @include button-clear($button-royal-bg);
+    @include button-outline($button-royal-bg);
+  }
+
+  &.button-dark {
+    @include button-style($button-dark-bg, $button-dark-border, $button-dark-active-bg, $button-dark-active-border, $button-dark-text);
+    @include button-clear($button-dark-bg);
+    @include button-outline($button-dark-bg);
+  }
+}
+
+.button-small {
+  padding: 2px $button-small-padding 1px;
+  min-width: $button-small-height;
+  min-height: $button-small-height + 2;
+  font-size: $button-small-font-size;
+  line-height: $button-small-height - $button-border-width - 1;
+
+  .icon:before,
+  &.icon:before,
+  &.icon-left:before,
+  &.icon-right:before {
+    font-size: $button-small-icon-size;
+    line-height: $button-small-icon-size + 3;
+    margin-top: 3px;
+  }
+}
+
+.button-large {
+  padding: 0 $button-large-padding;
+  min-width: ($button-large-padding * 3) + $button-large-font-size;
+  min-height: $button-large-height + 5;
+  font-size: $button-large-font-size;
+  line-height: $button-large-height - $button-border-width;
+
+  .icon:before,
+  &.icon:before,
+  &.icon-left:before,
+  &.icon-right:before {
+    padding-bottom: ($button-border-width * 2);
+    font-size: $button-large-icon-size;
+    line-height: $button-large-height - ($button-border-width * 2) - 1;
+  }
+}
+
+.button-icon {
+  @include transition(opacity .1s);
+  padding: 0 6px;
+  min-width: initial;
+  border-color: transparent;
+  background: none;
+
+  &.button.active,
+  &.button.activated {
+    border-color: transparent;
+    background: none;
+    box-shadow: none;
+    opacity: 0.3;
+  }
+
+  .icon:before,
+  &.icon:before {
+    font-size: $button-large-icon-size;
+  }
+}
+
+.button-clear {
+  @include button-clear($button-default-border);
+  @include transition(opacity .1s);
+  padding: 0 $button-clear-padding;
+  max-height: $button-height;
+  border-color: transparent;
+  background: none;
+  box-shadow: none;
+
+  &.active,
+  &.activated {
+    opacity: 0.3;
+  }
+}
+
+.button-outline {
+  @include button-outline($button-default-border);
+  @include transition(opacity .1s);
+  background: none;
+  box-shadow: none;
+}
+
+.padding > .button.button-block:first-child {
+  margin-top: 0;
+}
+
+.button-block {
+  display: block;
+  clear: both;
+
+  &:after {
+    clear: both;
+  }
+}
+
+.button-full,
+.button-full > .button {
+  display: block;
+  margin-right: 0;
+  margin-left: 0;
+  border-right-width: 0;
+  border-left-width: 0;
+  border-radius: 0;
+}
+
+button.button-block,
+button.button-full,
+.button-full > button.button,
+input.button.button-block  {
+  width: 100%;
+}
+
+a.button {
+  text-decoration: none;
+
+  .icon:before,
+  &.icon:before,
+  &.icon-left:before,
+  &.icon-right:before {
+    margin-top: 2px;
+  }
+}
+
+.button.disabled,
+.button[disabled] {
+  opacity: .4;
+  cursor: default !important;
+  pointer-events: none;
+}

+ 176 - 0
ionic/www/lib/ionic/scss/_checkbox.scss

@@ -0,0 +1,176 @@
+
+/**
+ * Checkbox
+ * --------------------------------------------------
+ */
+
+.checkbox {
+  // set the color defaults
+  @include checkbox-style($checkbox-off-border-default, $checkbox-on-bg-default, $checkbox-on-border-default);
+
+  position: relative;
+  display: inline-block;
+  padding: ($checkbox-height / 4) ($checkbox-width / 4);
+  cursor: pointer;
+}
+.checkbox-light  {
+  @include checkbox-style($checkbox-off-border-light, $checkbox-on-bg-light, $checkbox-off-border-light);
+}
+.checkbox-stable  {
+  @include checkbox-style($checkbox-off-border-stable, $checkbox-on-bg-stable, $checkbox-off-border-stable);
+}
+.checkbox-positive  {
+  @include checkbox-style($checkbox-off-border-positive, $checkbox-on-bg-positive, $checkbox-off-border-positive);
+}
+.checkbox-calm  {
+  @include checkbox-style($checkbox-off-border-calm, $checkbox-on-bg-calm, $checkbox-off-border-calm);
+}
+.checkbox-assertive  {
+  @include checkbox-style($checkbox-off-border-assertive, $checkbox-on-bg-assertive, $checkbox-off-border-assertive);
+}
+.checkbox-balanced  {
+  @include checkbox-style($checkbox-off-border-balanced, $checkbox-on-bg-balanced, $checkbox-off-border-balanced);
+}
+.checkbox-energized{
+  @include checkbox-style($checkbox-off-border-energized, $checkbox-on-bg-energized, $checkbox-off-border-energized);
+}
+.checkbox-royal  {
+  @include checkbox-style($checkbox-off-border-royal, $checkbox-on-bg-royal, $checkbox-off-border-royal);
+}
+.checkbox-dark  {
+  @include checkbox-style($checkbox-off-border-dark, $checkbox-on-bg-dark, $checkbox-off-border-dark);
+}
+
+.checkbox input:disabled:before,
+.checkbox input:disabled + .checkbox-icon:before {
+  border-color: $checkbox-off-border-light;
+}
+
+.checkbox input:disabled:checked:before,
+.checkbox input:disabled:checked + .checkbox-icon:before {
+  background: $checkbox-on-bg-light;
+}
+
+
+.checkbox.checkbox-input-hidden input {
+  display: none !important;
+}
+
+.checkbox input,
+.checkbox-icon {
+  position: relative;
+  width: $checkbox-width;
+  height: $checkbox-height;
+  display: block;
+  border: 0;
+  background: transparent;
+  cursor: pointer;
+  -webkit-appearance: none;
+
+  &:before {
+    // what the checkbox looks like when its not checked
+    display: table;
+    width: 100%;
+    height: 100%;
+    border-width: $checkbox-border-width;
+    border-style: solid;
+    border-radius: $checkbox-border-radius;
+    background: $checkbox-off-bg-color;
+    content: ' ';
+    @include transition(background-color 20ms ease-in-out);
+  }
+}
+
+.checkbox input:checked:before,
+input:checked + .checkbox-icon:before {
+  border-width: $checkbox-border-width + 1;
+}
+
+// the checkmark within the box
+.checkbox input:after,
+.checkbox-icon:after {
+  @include transition(opacity .05s ease-in-out);
+  @include rotate(-45deg);
+  position: absolute;
+  top: 33%;
+  left: 25%;
+  display: table;
+  width: ($checkbox-width / 2);
+  height: ($checkbox-width / 4) - 1;
+  border: $checkbox-check-width solid $checkbox-check-color;
+  border-top: 0;
+  border-right: 0;
+  content: ' ';
+  opacity: 0;
+}
+
+.platform-android .checkbox-platform input:before,
+.platform-android .checkbox-platform .checkbox-icon:before,
+.checkbox-square input:before,
+.checkbox-square .checkbox-icon:before {
+  border-radius: 2px;
+  width: 72%;
+  height: 72%;
+  margin-top: 14%;
+  margin-left: 14%;
+  border-width: 2px;
+}
+
+.platform-android .checkbox-platform input:after,
+.platform-android .checkbox-platform .checkbox-icon:after,
+.checkbox-square input:after,
+.checkbox-square .checkbox-icon:after {
+  border-width: 2px;
+  top: 19%;
+  left: 25%;
+  width: ($checkbox-width / 2) - 1;
+  height: 7px;
+}
+
+.grade-c .checkbox input:after,
+.grade-c .checkbox-icon:after {
+  @include rotate(0);
+  top: 3px;
+  left: 4px;
+  border: none;
+  color: $checkbox-check-color;
+  content: '\2713';
+  font-weight: bold;
+  font-size: 20px;
+}
+
+// what the checkmark looks like when its checked
+.checkbox input:checked:after,
+input:checked + .checkbox-icon:after {
+  opacity: 1;
+}
+
+// make sure item content have enough padding on left to fit the checkbox
+.item-checkbox {
+  padding-left: ($item-padding * 2) + $checkbox-width;
+
+  &.active {
+    box-shadow: none;
+  }
+}
+
+// position the checkbox to the left within an item
+.item-checkbox .checkbox {
+  position: absolute;
+  top: 50%;
+  right: $item-padding / 2;
+  left: $item-padding / 2;
+  z-index: $z-index-item-checkbox;
+  margin-top: (($checkbox-height + ($checkbox-height / 2)) / 2) * -1;
+}
+
+
+.item-checkbox.item-checkbox-right {
+  padding-right: ($item-padding * 2) + $checkbox-width;
+  padding-left: $item-padding;
+}
+
+.item-checkbox-right .checkbox input,
+.item-checkbox-right .checkbox-icon {
+  float: right;
+}

+ 314 - 0
ionic/www/lib/ionic/scss/_form.scss

@@ -0,0 +1,314 @@
+/**
+ * Forms
+ * --------------------------------------------------
+ */
+
+// Make all forms have space below them
+form {
+  margin: 0 0 $line-height-base;
+}
+
+// Groups of fields with labels on top (legends)
+legend {
+  display: block;
+  margin-bottom: $line-height-base;
+  padding: 0;
+  width: 100%;
+  border: $input-border-width solid $input-border;
+  color: $dark;
+  font-size: $font-size-base * 1.5;
+  line-height: $line-height-base * 2;
+
+  small {
+    color: $stable;
+    font-size: $line-height-base * .75;
+  }
+}
+
+// Set font for forms
+label,
+input,
+button,
+select,
+textarea {
+  @include font-shorthand($font-size-base, normal, $line-height-base); // Set size, weight, line-height here
+}
+input,
+button,
+select,
+textarea {
+  font-family: $font-family-base; // And only set font-family here for those that need it (note the missing label element)
+}
+
+
+// Input List
+// -------------------------------
+
+.item-input {
+  @include display-flex();
+  @include align-items(center);
+  position: relative;
+  overflow: hidden;
+  padding: 6px 0 5px 16px;
+
+  input {
+    @include border-radius(0);
+    @include flex(1, 220px);
+    @include appearance(none);
+    margin: 0;
+    padding-right: 24px;
+    background-color: transparent;
+  }
+
+  .button .icon {
+    @include flex(0, 0, 24px);
+    position: static;
+    display: inline-block;
+    height: auto;
+    text-align: center;
+    font-size: 16px;
+  }
+
+  .button-bar {
+    @include border-radius(0);
+    @include flex(1, 0, 220px);
+    @include appearance(none);
+  }
+
+  .icon {
+    min-width: 14px;
+  }
+}
+
+.item-input-inset {
+  @include display-flex();
+  @include align-items(center);
+  position: relative;
+  overflow: hidden;
+  padding: ($item-padding / 3) * 2;
+}
+
+.item-input-wrapper {
+  @include display-flex();
+  @include flex(1, 0);
+  @include align-items(center);
+  @include border-radius(4px);
+  padding-right: 8px;
+  padding-left: 8px;
+  background: #eee;
+}
+
+.item-input-inset .item-input-wrapper input {
+  padding-left: 4px;
+  height: 29px;
+  background: transparent;
+  line-height: 18px;
+}
+
+.item-input-wrapper ~ .button {
+  margin-left: ($item-padding / 3) * 2;
+}
+
+.input-label {
+  display: table;
+  padding: 7px 10px 7px 0px;
+  max-width: 200px;
+  width: 35%;
+  color: $input-label-color;
+  font-size: 16px;
+}
+
+.placeholder-icon {
+  color: #aaa;
+  &:first-child {
+    padding-right: 6px;
+  }
+  &:last-child {
+    padding-left: 6px;
+  }
+}
+
+.item-stacked-label {
+  display: block;
+  background-color: transparent;
+  box-shadow: none;
+
+  .input-label, .icon {
+    display: inline-block;
+    padding: 4px 0 0 0px;
+    vertical-align: middle;
+  }
+}
+
+.item-stacked-label input,
+.item-stacked-label textarea {
+  @include border-radius(2px);
+  padding: 4px 8px 3px 0;
+  border: none;
+  background-color: $input-bg;
+}
+.item-stacked-label input {
+  overflow: hidden;
+  height: $line-height-computed + $font-size-base + 12px;
+}
+
+.item-floating-label {
+  display: block;
+  background-color: transparent;
+  box-shadow: none;
+
+  .input-label {
+    position: relative;
+    padding: 5px 0 0 0;
+    opacity: 0;
+    top: 10px;
+    @include transition(opacity .15s ease-in, top .2s linear);
+
+    &.has-input {
+      opacity: 1;
+      top: 0;
+      @include transition(opacity .15s ease-in, top .2s linear);
+    }
+  }
+}
+
+
+// Form Controls
+// -------------------------------
+
+// Shared size and type resets
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"] {
+  display: block;
+  padding-top: 2px;
+  padding-left: 0;
+  height: $line-height-computed + $font-size-base;
+  color: $input-color;
+  vertical-align: middle;
+  font-size: $font-size-base;
+  line-height: $font-size-base + 2;
+}
+
+.platform-ios,
+.platform-android {
+  input[type="datetime-local"],
+  input[type="date"],
+  input[type="month"],
+  input[type="time"],
+  input[type="week"] {
+    padding-top: 8px;
+  }
+}
+
+.item-input {
+  input,
+  textarea {
+    width: 100%;
+  }
+}
+
+textarea {
+  padding-left: 0;
+  @include placeholder($input-color-placeholder, -3px);
+}
+
+// Reset height since textareas have rows
+textarea {
+  height: auto;
+}
+
+// Everything else
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"] {
+  border: 0;
+}
+
+// Position radios and checkboxes better
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 0;
+  line-height: normal;
+}
+
+// Reset width of input images, buttons, radios, checkboxes
+.item-input {
+  input[type="file"],
+  input[type="image"],
+  input[type="submit"],
+  input[type="reset"],
+  input[type="button"],
+  input[type="radio"],
+  input[type="checkbox"] {
+    width: auto; // Override of generic input selector
+  }
+}
+
+// Set the height of file to match text inputs
+input[type="file"] {
+  line-height: $input-height-base;
+}
+
+// Text input classes to hide text caret during scroll
+.previous-input-focus,
+.cloned-text-input + input,
+.cloned-text-input + textarea {
+  position: absolute !important;
+  left: -9999px;
+  width: 200px;
+}
+
+
+// Placeholder
+// -------------------------------
+input,
+textarea {
+  @include placeholder();
+}
+
+
+// DISABLED STATE
+// -------------------------------
+
+// Disabled and read-only inputs
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly]:not(.cloned-text-input),
+textarea[readonly]:not(.cloned-text-input),
+select[readonly] {
+  background-color: $input-bg-disabled;
+  cursor: not-allowed;
+}
+// Explicitly reset the colors here
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"][readonly],
+input[type="checkbox"][readonly] {
+  background-color: transparent;
+}

+ 151 - 0
ionic/www/lib/ionic/scss/_grid.scss

@@ -0,0 +1,151 @@
+/**
+ * Grid
+ * --------------------------------------------------
+ * Using flexbox for the grid, inspired by Philip Walton:
+ * http://philipwalton.github.io/solved-by-flexbox/demos/grids/
+ * By default each .col within a .row will evenly take up
+ * available width, and the height of each .col with take
+ * up the height of the tallest .col in the same .row.
+ */
+
+.row {
+  @include display-flex();
+  padding: ($grid-padding-width / 2);
+  width: 100%;
+}
+
+.row-wrap {
+  @include flex-wrap(wrap);
+}
+
+.row-no-padding {
+  padding: 0;
+
+  > .col {
+    padding: 0;
+  }
+}
+
+.row + .row {
+  margin-top: ($grid-padding-width / 2) * -1;
+  padding-top: 0;
+}
+
+.col {
+  @include flex(1);
+  display: block;
+  padding: ($grid-padding-width / 2);
+  width: 100%;
+}
+
+
+/* Vertically Align Columns */
+/* .row-* vertically aligns every .col in the .row */
+.row-top {
+  @include align-items(flex-start);
+}
+.row-bottom {
+  @include align-items(flex-end);
+}
+.row-center {
+  @include align-items(center);
+}
+.row-stretch {
+  @include align-items(stretch);
+}
+.row-baseline {
+  @include align-items(baseline);
+}
+
+/* .col-* vertically aligns an individual .col */
+.col-top {
+  @include align-self(flex-start);
+}
+.col-bottom {
+  @include align-self(flex-end);
+}
+.col-center {
+  @include align-self(center);
+}
+
+/* Column Offsets */
+.col-offset-10 {
+  margin-left: 10%;
+}
+.col-offset-20 {
+  margin-left: 20%;
+}
+.col-offset-25 {
+  margin-left: 25%;
+}
+.col-offset-33, .col-offset-34 {
+  margin-left: 33.3333%;
+}
+.col-offset-50 {
+  margin-left: 50%;
+}
+.col-offset-66, .col-offset-67 {
+  margin-left: 66.6666%;
+}
+.col-offset-75 {
+  margin-left: 75%;
+}
+.col-offset-80 {
+  margin-left: 80%;
+}
+.col-offset-90 {
+  margin-left: 90%;
+}
+
+
+/* Explicit Column Percent Sizes */
+/* By default each grid column will evenly distribute */
+/* across the grid. However, you can specify individual */
+/* columns to take up a certain size of the available area */
+.col-10 {
+  @include flex(0, 0, 10%);
+  max-width: 10%;
+}
+.col-20 {
+  @include flex(0, 0, 20%);
+  max-width: 20%;
+}
+.col-25 {
+  @include flex(0, 0, 25%);
+  max-width: 25%;
+}
+.col-33, .col-34 {
+  @include flex(0, 0, 33.3333%);
+  max-width: 33.3333%;
+}
+.col-50 {
+  @include flex(0, 0, 50%);
+  max-width: 50%;
+}
+.col-66, .col-67 {
+  @include flex(0, 0, 66.6666%);
+  max-width: 66.6666%;
+}
+.col-75 {
+  @include flex(0, 0, 75%);
+  max-width: 75%;
+}
+.col-80 {
+  @include flex(0, 0, 80%);
+  max-width: 80%;
+}
+.col-90 {
+  @include flex(0, 0, 90%);
+  max-width: 90%;
+}
+
+
+/* Responsive Grid Classes */
+/* Adding a class of responsive-X to a row */
+/* will trigger the flex-direction to */
+/* change to column and add some margin */
+/* to any columns in the row for clearity */
+
+@include responsive-grid-break('.responsive-sm', $grid-responsive-sm-break);
+@include responsive-grid-break('.responsive-md', $grid-responsive-md-break);
+@include responsive-grid-break('.responsive-lg', $grid-responsive-lg-break);

+ 815 - 0
ionic/www/lib/ionic/scss/_items.scss

@@ -0,0 +1,815 @@
+/**
+ * Items
+ * --------------------------------------------------
+ */
+
+.item {
+  @include item-style($item-default-bg, $item-default-border, $item-default-text);
+
+  position: relative;
+  z-index: $z-index-item; // Make sure the borders and stuff don't get hidden by children
+  display: block;
+
+  margin: $item-border-width * -1;
+  padding: $item-padding;
+
+  border-width: $item-border-width;
+  border-style: solid;
+  font-size: $item-font-size;
+
+  h2 {
+    margin: 0 0 2px 0;
+    font-size: 16px;
+    font-weight: normal;
+  }
+  h3 {
+    margin: 0 0 4px 0;
+    font-size: 14px;
+  }
+  h4 {
+    margin: 0 0 4px 0;
+    font-size: 12px;
+  }
+  h5, h6 {
+    margin: 0 0 3px 0;
+    font-size: 10px;
+  }
+  p {
+    color: #666;
+    font-size: 14px;
+    margin-bottom: 2px;
+  }
+
+  h1:last-child,
+  h2:last-child,
+  h3:last-child,
+  h4:last-child,
+  h5:last-child,
+  h6:last-child,
+  p:last-child {
+    margin-bottom: 0;
+  }
+
+  // Align badges within items
+  .badge {
+    @include display-flex();
+    position: absolute;
+    top: $item-padding;
+    right: ($item-padding * 2);
+  }
+  &.item-button-right .badge {
+    right: ($item-padding * 2) + 35;
+  }
+  &.item-divider .badge {
+    top: ceil($item-padding / 2);
+  }
+  .badge + .badge {
+    margin-right: 5px;
+  }
+
+  // Different themes for items
+  &.item-light {
+    @include item-style($item-light-bg, $item-light-border, $item-light-text);
+  }
+  &.item-stable {
+    @include item-style($item-stable-bg, $item-stable-border, $item-stable-text);
+  }
+  &.item-positive {
+    @include item-style($item-positive-bg, $item-positive-border, $item-positive-text);
+  }
+  &.item-calm {
+    @include item-style($item-calm-bg, $item-calm-border, $item-calm-text);
+  }
+  &.item-assertive {
+    @include item-style($item-assertive-bg, $item-assertive-border, $item-assertive-text);
+  }
+  &.item-balanced {
+    @include item-style($item-balanced-bg, $item-balanced-border, $item-balanced-text);
+  }
+  &.item-energized {
+    @include item-style($item-energized-bg, $item-energized-border, $item-energized-text);
+  }
+  &.item-royal {
+    @include item-style($item-royal-bg, $item-royal-border, $item-royal-text);
+  }
+  &.item-dark {
+    @include item-style($item-dark-bg, $item-dark-border, $item-dark-text);
+  }
+
+  &[ng-click]:hover {
+    cursor: pointer;
+  }
+
+}
+
+.list-borderless .item,
+.item-borderless {
+  border-width: 0;
+}
+
+// Link and Button Active States
+.item.active,
+.item.activated,
+.item-complex.active .item-content,
+.item-complex.activated .item-content,
+.item .item-content.active,
+.item .item-content.activated {
+  @include item-active-style($item-default-active-bg, $item-default-active-border);
+
+  // Different active themes for <a> and <button> items
+  &.item-light {
+    @include item-active-style($item-light-active-bg, $item-light-active-border);
+  }
+  &.item-stable {
+    @include item-active-style($item-stable-active-bg, $item-stable-active-border);
+  }
+  &.item-positive {
+    @include item-active-style($item-positive-active-bg, $item-positive-active-border);
+  }
+  &.item-calm {
+    @include item-active-style($item-calm-active-bg, $item-calm-active-border);
+  }
+  &.item-assertive {
+    @include item-active-style($item-assertive-active-bg, $item-assertive-active-border);
+  }
+  &.item-balanced {
+    @include item-active-style($item-balanced-active-bg, $item-balanced-active-border);
+  }
+  &.item-energized {
+    @include item-active-style($item-energized-active-bg, $item-energized-active-border);
+  }
+  &.item-royal {
+    @include item-active-style($item-royal-active-bg, $item-royal-active-border);
+  }
+  &.item-dark {
+    @include item-active-style($item-dark-active-bg, $item-dark-active-border);
+  }
+}
+
+// Handle text overflow
+.item,
+.item h1,
+.item h2,
+.item h3,
+.item h4,
+.item h5,
+.item h6,
+.item p,
+.item-content,
+.item-content h1,
+.item-content h2,
+.item-content h3,
+.item-content h4,
+.item-content h5,
+.item-content h6,
+.item-content p {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+// Linked list items
+a.item {
+  color: inherit;
+  text-decoration: none;
+
+  &:hover,
+  &:focus {
+    text-decoration: none;
+  }
+}
+
+
+/**
+ * Complex Items
+ * --------------------------------------------------
+ * Adding .item-complex allows the .item to be slidable and
+ * have options underneath the button, but also requires an
+ * additional .item-content element inside .item.
+ * Basically .item-complex removes any default settings which
+ * .item added, so that .item-content looks them as just .item.
+ */
+
+.item-complex,
+a.item.item-complex,
+button.item.item-complex {
+  padding: 0;
+}
+.item-complex .item-content,
+.item-radio .item-content {
+  position: relative;
+  z-index: $z-index-item;
+  padding: $item-padding (ceil( ($item-padding * 3) + ($item-padding / 3) ) - 5) $item-padding $item-padding;
+  border: none;
+  background-color: white;
+}
+
+a.item-content {
+  display: block;
+  color: inherit;
+  text-decoration: none;
+}
+
+.item-text-wrap .item,
+.item-text-wrap .item-content,
+.item-text-wrap,
+.item-text-wrap h1,
+.item-text-wrap h2,
+.item-text-wrap h3,
+.item-text-wrap h4,
+.item-text-wrap h5,
+.item-text-wrap h6,
+.item-text-wrap p,
+.item-complex.item-text-wrap .item-content,
+.item-body h1,
+.item-body h2,
+.item-body h3,
+.item-body h4,
+.item-body h5,
+.item-body h6,
+.item-body p {
+  overflow: visible;
+  white-space: normal;
+}
+.item-complex.item-text-wrap,
+.item-complex.item-text-wrap h1,
+.item-complex.item-text-wrap h2,
+.item-complex.item-text-wrap h3,
+.item-complex.item-text-wrap h4,
+.item-complex.item-text-wrap h5,
+.item-complex.item-text-wrap h6,
+.item-complex.item-text-wrap p {
+  overflow: visible;
+  white-space: normal;
+}
+
+// Link and Button Active States
+
+.item-complex{
+  // Stylized items
+  &.item-light > .item-content{
+    @include item-style($item-light-bg, $item-light-border, $item-light-text);
+    &.active, &:active {
+      @include item-active-style($item-light-active-bg, $item-light-active-border);
+    }
+  }
+  &.item-stable > .item-content{
+    @include item-style($item-stable-bg, $item-stable-border, $item-stable-text);
+    &.active, &:active {
+      @include item-active-style($item-stable-active-bg, $item-stable-active-border);
+    }
+  }
+  &.item-positive > .item-content{
+    @include item-style($item-positive-bg, $item-positive-border, $item-positive-text);
+    &.active, &:active {
+      @include item-active-style($item-positive-active-bg, $item-positive-active-border);
+    }
+  }
+  &.item-calm > .item-content{
+    @include item-style($item-calm-bg, $item-calm-border, $item-calm-text);
+    &.active, &:active {
+      @include item-active-style($item-calm-active-bg, $item-calm-active-border);
+    }
+  }
+  &.item-assertive > .item-content{
+    @include item-style($item-assertive-bg, $item-assertive-border, $item-assertive-text);
+    &.active, &:active {
+      @include item-active-style($item-assertive-active-bg, $item-assertive-active-border);
+    }
+  }
+  &.item-balanced > .item-content{
+    @include item-style($item-balanced-bg, $item-balanced-border, $item-balanced-text);
+    &.active, &:active {
+      @include item-active-style($item-balanced-active-bg, $item-balanced-active-border);
+    }
+  }
+  &.item-energized > .item-content{
+    @include item-style($item-energized-bg, $item-energized-border, $item-energized-text);
+    &.active, &:active {
+      @include item-active-style($item-energized-active-bg, $item-energized-active-border);
+    }
+  }
+  &.item-royal > .item-content{
+    @include item-style($item-royal-bg, $item-royal-border, $item-royal-text);
+    &.active, &:active {
+      @include item-active-style($item-royal-active-bg, $item-royal-active-border);
+    }
+  }
+  &.item-dark > .item-content{
+    @include item-style($item-dark-bg, $item-dark-border, $item-dark-text);
+    &.active, &:active {
+      @include item-active-style($item-dark-active-bg, $item-dark-active-border);
+    }
+  }
+}
+
+
+/**
+ * Item Icons
+ * --------------------------------------------------
+ */
+
+.item-icon-left .icon,
+.item-icon-right .icon {
+  @include display-flex();
+  @include align-items(center);
+  position: absolute;
+  top: 0;
+  height: 100%;
+  font-size: $item-icon-font-size;
+
+  &:before {
+    display: block;
+    width: $item-icon-font-size;
+    text-align: center;
+  }
+}
+
+.item .fill-icon {
+  min-width: $item-icon-fill-font-size + 2;
+  min-height: $item-icon-fill-font-size + 2;
+  font-size: $item-icon-fill-font-size;
+}
+
+.item-icon-left {
+  padding-left: ceil( ($item-padding * 3) + ($item-padding / 3) );
+
+  .icon {
+    left: ceil( ($item-padding / 3) * 2);
+  }
+}
+.item-complex.item-icon-left {
+  padding-left: 0;
+
+  .item-content {
+    padding-left: ceil( ($item-padding * 3) + ($item-padding / 3) );
+  }
+}
+
+.item-icon-right {
+  padding-right: ceil( ($item-padding * 3) + ($item-padding / 3) );
+
+  .icon {
+    right: ceil( ($item-padding / 3) * 2);
+  }
+}
+.item-complex.item-icon-right {
+  padding-right: 0;
+
+  .item-content {
+    padding-right: ceil( ($item-padding * 3) + ($item-padding / 3) );
+  }
+}
+
+.item-icon-left.item-icon-right .icon:first-child {
+  right: auto;
+}
+.item-icon-left.item-icon-right .icon:last-child,
+.item-icon-left .item-delete .icon {
+  left: auto;
+}
+
+.item-icon-left .icon-accessory,
+.item-icon-right .icon-accessory {
+  color: $item-icon-accessory-color;
+  font-size: $item-icon-accessory-font-size;
+}
+.item-icon-left .icon-accessory {
+  left: floor($item-padding / 5);
+}
+.item-icon-right .icon-accessory {
+  right: floor($item-padding / 5);
+}
+
+
+/**
+ * Item Button
+ * --------------------------------------------------
+ * An item button is a child button inside an .item (not the entire .item)
+ */
+
+.item-button-left {
+  padding-left: ceil($item-padding * 4.5);
+}
+
+.item-button-left > .button,
+.item-button-left .item-content > .button {
+  @include display-flex();
+  @include align-items(center);
+  position: absolute;
+  top: ceil($item-padding / 2);
+  left: ceil( ($item-padding / 3) * 2);
+  min-width: $item-icon-font-size + ($button-border-width * 2);
+  min-height: $item-icon-font-size + ($button-border-width * 2);
+  font-size: $item-button-font-size;
+  line-height: $item-button-line-height;
+
+  .icon:before {
+    position: relative;
+    left: auto;
+    width: auto;
+    line-height: $item-icon-font-size - 1;
+  }
+
+  > .button {
+    margin: 0px 2px;
+    min-height: $item-icon-font-size + ($button-border-width * 2);
+    font-size: $item-button-font-size;
+    line-height: $item-button-line-height;
+  }
+}
+
+.item-button-right,
+a.item.item-button-right,
+button.item.item-button-right {
+  padding-right: $item-padding * 5;
+}
+
+.item-button-right > .button,
+.item-button-right .item-content > .button,
+.item-button-right > .buttons,
+.item-button-right .item-content > .buttons {
+  @include display-flex();
+  @include align-items(center);
+  position: absolute;
+  top: ceil($item-padding / 2);
+  right: $item-padding;
+  min-width: $item-icon-font-size + ($button-border-width * 2);
+  min-height: $item-icon-font-size + ($button-border-width * 2);
+  font-size: $item-button-font-size;
+  line-height: $item-button-line-height;
+
+  .icon:before {
+    position: relative;
+    left: auto;
+    width: auto;
+    line-height: $item-icon-font-size - 1;
+  }
+
+  > .button {
+    margin: 0px 2px;
+    min-width: $item-icon-font-size + ($button-border-width * 2);
+    min-height: $item-icon-font-size + ($button-border-width * 2);
+    font-size: $item-button-font-size;
+    line-height: $item-button-line-height;
+  }
+}
+
+
+// Item Avatar
+// -------------------------------
+
+.item-avatar,
+.item-avatar .item-content,
+.item-avatar-left,
+.item-avatar-left .item-content {
+  padding-left: $item-avatar-width + ($item-padding * 2);
+  min-height: $item-avatar-width + ($item-padding * 2);
+
+  > img:first-child,
+  .item-image {
+    position: absolute;
+    top: $item-padding;
+    left: $item-padding;
+    max-width: $item-avatar-width;
+    max-height: $item-avatar-height;
+    width: 100%;
+    height: 100%;
+    border-radius: $item-avatar-border-radius;
+  }
+}
+
+.item-avatar-right,
+.item-avatar-right .item-content {
+  padding-right: $item-avatar-width + ($item-padding * 2);
+  min-height: $item-avatar-width + ($item-padding * 2);
+
+  > img:first-child,
+  .item-image {
+    position: absolute;
+    top: $item-padding;
+    right: $item-padding;
+    max-width: $item-avatar-width;
+    max-height: $item-avatar-height;
+    width: 100%;
+    height: 100%;
+    border-radius: $item-avatar-border-radius;
+  }
+}
+
+
+// Item Thumbnails
+// -------------------------------
+
+.item-thumbnail-left,
+.item-thumbnail-left .item-content {
+  padding-top: $item-padding / 2;
+  padding-left: $item-thumbnail-width + $item-thumbnail-margin + $item-padding;
+  min-height: $item-thumbnail-height + ($item-thumbnail-margin * 2);
+
+  > img:first-child,
+  .item-image {
+    position: absolute;
+    top: $item-thumbnail-margin;
+    left: $item-thumbnail-margin;
+    max-width: $item-thumbnail-width;
+    max-height: $item-thumbnail-height;
+    width: 100%;
+    height: 100%;
+  }
+}
+.item-avatar.item-complex,
+.item-avatar-left.item-complex,
+.item-thumbnail-left.item-complex {
+  padding-top: 0;
+  padding-left: 0;
+}
+
+.item-thumbnail-right,
+.item-thumbnail-right .item-content {
+  padding-top: $item-padding / 2;
+  padding-right: $item-thumbnail-width + $item-thumbnail-margin + $item-padding;
+  min-height: $item-thumbnail-height + ($item-thumbnail-margin * 2);
+
+  > img:first-child,
+  .item-image {
+    position: absolute;
+    top: $item-thumbnail-margin;
+    right: $item-thumbnail-margin;
+    max-width: $item-thumbnail-width;
+    max-height: $item-thumbnail-height;
+    width: 100%;
+    height: 100%;
+  }
+}
+.item-avatar-right.item-complex,
+.item-thumbnail-right.item-complex {
+  padding-top: 0;
+  padding-right: 0;
+}
+
+
+// Item Image
+// -------------------------------
+
+.item-image {
+  padding: 0;
+  text-align: center;
+
+  img:first-child, .list-img {
+    width: 100%;
+    vertical-align: middle;
+  }
+}
+
+
+// Item Body
+// -------------------------------
+
+.item-body {
+  overflow: auto;
+  padding: $item-padding;
+  text-overflow: inherit;
+  white-space: normal;
+
+  h1, h2, h3, h4, h5, h6, p {
+    margin-top: $item-padding;
+    margin-bottom: $item-padding;
+  }
+}
+
+
+// Item Divider
+// -------------------------------
+
+.item-divider {
+  padding-top: ceil($item-padding / 2);
+  padding-bottom: ceil($item-padding / 2);
+  min-height: 30px;
+  background-color: $item-divider-bg;
+  color: $item-divider-color;
+  font-weight: 500;
+}
+
+.platform-ios .item-divider-platform,
+.item-divider-ios {
+  padding-top: 26px;
+  text-transform: uppercase;
+  font-weight: 300;
+  font-size: 13px;
+  background-color: #efeff4;
+  color: #555;
+}
+
+.platform-android .item-divider-platform,
+.item-divider-android {
+  font-weight: 300;
+  font-size: 13px;
+}
+
+
+// Item Note
+// -------------------------------
+
+.item-note {
+  float: right;
+  color: #aaa;
+  font-size: 14px;
+}
+
+
+// Item Editing
+// -------------------------------
+
+.item-left-editable .item-content,
+.item-right-editable .item-content {
+  // setup standard transition settings
+  @include transition-duration( $item-edit-transition-duration );
+  @include transition-timing-function( $item-edit-transition-function );
+  -webkit-transition-property: -webkit-transform;
+     -moz-transition-property: -moz-transform;
+          transition-property: transform;
+}
+
+.list-left-editing .item-left-editable .item-content,
+.item-left-editing.item-left-editable .item-content {
+  // actively editing the left side of the item
+  @include translate3d($item-left-edit-open-width, 0, 0);
+}
+
+.item-remove-animate {
+  &.ng-leave {
+    @include transition-duration( $item-remove-transition-duration );
+  }
+  &.ng-leave .item-content,
+  &.ng-leave:last-of-type {
+    @include transition-duration( $item-remove-transition-duration );
+    @include transition-timing-function( $item-remove-transition-function );
+    @include transition-property( all );
+  }
+
+  &.ng-leave.ng-leave-active .item-content {
+    opacity:0;
+    -webkit-transform: translate3d(-100%, 0, 0) !important;
+    transform: translate3d(-100%, 0, 0) !important;
+  }
+  &.ng-leave.ng-leave-active:last-of-type {
+    opacity: 0;
+  }
+
+  &.ng-leave.ng-leave-active ~ ion-item:not(.ng-leave) {
+    -webkit-transform: translate3d(0, unquote('-webkit-calc(-100% + 1px)'), 0);
+    transform: translate3d(0, calc(-100% + 1px), 0);
+    @include transition-duration( $item-remove-transition-duration );
+    @include transition-timing-function( $item-remove-descendents-transition-function );
+    @include transition-property( all );
+  }
+}
+
+
+
+// Item Left Edit Button
+// -------------------------------
+
+.item-left-edit {
+  @include transition(all $item-edit-transition-function $item-edit-transition-duration / 2);
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: $z-index-item-edit;
+  width: $item-left-edit-open-width;
+  height: 100%;
+  line-height: 100%;
+
+  .button {
+    height: 100%;
+
+    &.icon {
+      @include display-flex();
+      @include align-items(center);
+      position: absolute;
+      top: 0;
+      height: 100%;
+    }
+  }
+
+  display: none;
+  opacity: 0;
+  @include translate3d( ($item-left-edit-left - $item-left-edit-open-width) / 2, 0, 0);
+  &.visible {
+    display: block;
+    &.active {
+      opacity: 1;
+      @include translate3d($item-left-edit-left, 0, 0);
+    }
+  }
+}
+.list-left-editing .item-left-edit {
+  @include transition-delay($item-edit-transition-duration / 2);
+}
+
+// Item Delete (Left side edit button)
+// -------------------------------
+
+.item-delete .button.icon {
+  color: $item-delete-icon-color;
+  font-size: $item-delete-icon-size;
+
+  &:hover {
+    opacity: .7;
+  }
+}
+
+
+// Item Right Edit Button
+// -------------------------------
+
+.item-right-edit {
+  @include transition(all $item-edit-transition-function $item-edit-transition-duration);
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: $z-index-item-reorder;
+  width: $item-right-edit-open-width *  1.5;
+  height: 100%;
+  background: inherit;
+  padding-left: 20px;
+
+  .button {
+    min-width: $item-right-edit-open-width;
+    height: 100%;
+
+    &.icon {
+      @include display-flex();
+      @include align-items(center);
+      position: absolute;
+      top: 0;
+      height: 100%;
+      font-size: $item-reorder-icon-size;
+    }
+  }
+
+  display: block;
+  opacity: 0;
+  @include translate3d($item-right-edit-open-width *  1.5, 0, 0);
+  &.visible {
+    display: block;
+    &.active {
+      opacity: 1;
+      @include translate3d(0, 0, 0);
+    }
+  }
+}
+
+
+// Item Reordering (Right side edit button)
+// -------------------------------
+
+.item-reorder .button.icon {
+  color: $item-reorder-icon-color;
+  font-size: $item-reorder-icon-size;
+}
+
+.item-reordering {
+  // item is actively being reordered
+  position: absolute;
+  left: 0;
+  top: 0;
+  z-index: $z-index-item-reordering;
+  width: 100%;
+  box-shadow: 0px 0px 10px 0px #aaa;
+
+  .item-reorder {
+    z-index: $z-index-item-reordering;
+  }
+}
+
+.item-placeholder {
+  // placeholder for the item that's being reordered
+  opacity: 0.7;
+}
+
+
+/**
+ * The hidden right-side buttons that can be exposed under a list item
+ * with dragging.
+ */
+.item-options {
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: $z-index-item-options;
+  height: 100%;
+
+  .button {
+    height: 100%;
+    border: none;
+    border-radius: 0;
+    @include display-inline-flex();
+    @include align-items(center);
+
+    &:before{
+      margin: 0 auto;
+    }
+  }
+}

+ 125 - 0
ionic/www/lib/ionic/scss/_list.scss

@@ -0,0 +1,125 @@
+
+/**
+ * Lists
+ * --------------------------------------------------
+ */
+
+.list {
+  position: relative;
+  padding-top: $item-border-width;
+  padding-bottom: $item-border-width;
+  padding-left: 0; // reset padding because ul and ol
+  margin-bottom: 20px;
+}
+.list:last-child {
+  margin-bottom: 0px;
+  &.card{
+    margin-bottom:40px;
+  }
+}
+
+
+/**
+ * List Header
+ * --------------------------------------------------
+ */
+
+.list-header {
+  margin-top: $list-header-margin-top;
+  padding: $list-header-padding;
+  background-color: $list-header-bg;
+  color: $list-header-color;
+  font-weight: bold;
+}
+
+// when its a card make sure it doesn't duplicate top and bottom borders
+.card.list .list-item {
+  padding-right: 1px;
+  padding-left: 1px;
+}
+
+
+/**
+ * Cards and Inset Lists
+ * --------------------------------------------------
+ * A card and list-inset are close to the same thing, except a card as a box shadow.
+ */
+
+.card,
+.list-inset {
+  overflow: hidden;
+  margin: ($content-padding * 2) $content-padding;
+  border-radius: $card-border-radius;
+  background-color: $card-body-bg;
+}
+
+.card {
+  padding-top: $item-border-width;
+  padding-bottom: $item-border-width;
+  box-shadow: $card-box-shadow;
+
+  .item {
+    border-left: 0;
+    border-right: 0;
+  }
+  .item:first-child {
+    border-top: 0;
+  }
+  .item:last-child {
+    border-bottom: 0;
+  }
+}
+
+.padding {
+  .card, .list-inset {
+    margin-left: 0;
+    margin-right: 0;
+  }
+}
+
+.card .item,
+.list-inset .item,
+.padding > .list .item
+{
+  &:first-child {
+    border-top-left-radius: $card-border-radius;
+    border-top-right-radius: $card-border-radius;
+
+    .item-content {
+      border-top-left-radius: $card-border-radius;
+      border-top-right-radius: $card-border-radius;
+    }
+  }
+  &:last-child {
+    border-bottom-right-radius: $card-border-radius;
+    border-bottom-left-radius: $card-border-radius;
+
+    .item-content {
+      border-bottom-right-radius: $card-border-radius;
+      border-bottom-left-radius: $card-border-radius;
+    }
+  }
+}
+
+.card .item:last-child,
+.list-inset .item:last-child {
+  margin-bottom: $item-border-width * -1;
+}
+
+.card .item,
+.list-inset .item,
+.padding > .list .item,
+.padding-horizontal > .list .item {
+  margin-right: 0;
+  margin-left: 0;
+
+  &.item-input input {
+    padding-right: 44px;
+  }
+}
+.padding-left > .list .item {
+  margin-left: 0;
+}
+.padding-right > .list .item {
+  margin-right: 0;
+}

+ 50 - 0
ionic/www/lib/ionic/scss/_loading.scss

@@ -0,0 +1,50 @@
+
+/**
+ * Loading
+ * --------------------------------------------------
+ */
+
+.loading-container {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+
+  z-index: $z-index-loading;
+
+  @include display-flex();
+  @include justify-content(center);
+  @include align-items(center);
+
+  @include transition(0.2s opacity linear);
+  visibility: hidden;
+  opacity: 0;
+
+  &:not(.visible) .icon {
+    display: none;
+  }
+  &.visible {
+    visibility: visible;
+  }
+  &.active {
+    opacity: 1;
+  }
+
+  .loading {
+    padding: $loading-padding;
+
+    border-radius: $loading-border-radius;
+    background-color: $loading-bg-color;
+
+    color: $loading-text-color;
+
+    text-align: center;
+    text-overflow: ellipsis;
+    font-size: $loading-font-size;
+
+    h1, h2, h3, h4, h5, h6 {
+      color: $loading-text-color;
+    }
+  }
+}

+ 0 - 0
ionic/www/lib/ionic/scss/_menu.scss


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.