├── hooks ├── .gitignore └── README.md ├── .gitignore ├── www ├── css │ └── style.css ├── img │ └── ionic.png ├── lib │ └── ionic │ │ ├── fonts │ │ ├── ionicons.eot │ │ ├── ionicons.ttf │ │ └── ionicons.woff │ │ ├── scss │ │ ├── _progress.scss │ │ ├── ionicons │ │ │ ├── ionicons.scss │ │ │ ├── _ionicons-font.scss │ │ │ ├── _ionicons-animation.scss │ │ │ └── _ionicons-variables.scss │ │ ├── _split-pane.scss │ │ ├── ionic.scss │ │ ├── _menu.scss │ │ ├── _button-bar.scss │ │ ├── _slide-box.scss │ │ ├── _platform.scss │ │ ├── _radio.scss │ │ ├── _modal.scss │ │ ├── _badge.scss │ │ ├── _action-sheet.scss │ │ ├── _list.scss │ │ ├── _popup.scss │ │ ├── _grid.scss │ │ ├── _range.scss │ │ ├── _checkbox.scss │ │ ├── _type.scss │ │ ├── _toggle.scss │ │ ├── _util.scss │ │ ├── _tabs.scss │ │ ├── _form.scss │ │ ├── _scaffolding.scss │ │ ├── _button.scss │ │ ├── _bar.scss │ │ ├── _reset.scss │ │ ├── _animations.scss │ │ ├── _mixins.scss │ │ └── _items.scss │ │ └── js │ │ ├── angular │ │ ├── angular-resource.min.js │ │ ├── angular-sanitize.min.js │ │ └── angular-animate.min.js │ │ └── angular-ui │ │ └── angular-ui-router.min.js ├── views │ ├── tab-tracking.html │ ├── tab-history.html │ └── tabs.html ├── js │ ├── services.js │ ├── app.js │ └── controllers.js └── index.html ├── 1.png ├── 4.png ├── 2_3.png ├── ionic.project ├── package.json ├── scss └── ionic.app.scss ├── gulpfile.js ├── config.xml └── README.md /hooks/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /www/css/style.css: -------------------------------------------------------------------------------- 1 | /* Empty. Add your own CSS if you like */ 2 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/1.png -------------------------------------------------------------------------------- /4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/4.png -------------------------------------------------------------------------------- /2_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/2_3.png -------------------------------------------------------------------------------- /ionic.project: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "email": "", 4 | "app_id": "", 5 | "package_name": "" 6 | } -------------------------------------------------------------------------------- /www/img/ionic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/www/img/ionic.png -------------------------------------------------------------------------------- /www/lib/ionic/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/www/lib/ionic/fonts/ionicons.eot -------------------------------------------------------------------------------- /www/lib/ionic/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/www/lib/ionic/fonts/ionicons.ttf -------------------------------------------------------------------------------- /www/lib/ionic/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myurasov/Salesforce-REST-API-Ionic-Framework-App-Sample/HEAD/www/lib/ionic/fonts/ionicons.woff -------------------------------------------------------------------------------- /www/views/tab-tracking.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Enable Tracking 4 | 5 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_progress.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Progress 4 | * -------------------------------------------------- 5 | */ 6 | 7 | progress { 8 | display: block; 9 | margin: $progress-margin; 10 | width: $progress-width; 11 | } 12 | -------------------------------------------------------------------------------- /www/views/tab-history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ position }} 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-project", 3 | "version": "1.0.0", 4 | "description": "An Ionic project", 5 | "dependencies": { 6 | "gulp": "^3.5.6", 7 | "gulp-sass": "^0.7.1", 8 | "gulp-concat": "^2.2.0", 9 | "gulp-minify-css": "^0.3.0", 10 | "gulp-rename": "^1.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /www/views/tabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/ionicons/ionicons.scss: -------------------------------------------------------------------------------- 1 | @import "ionicons-variables"; 2 | /*! 3 | Ionicons, v#{$ionicons-version} 4 | Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ 5 | https://twitter.com/benjsperry https://twitter.com/ionicframework 6 | MIT License: https://github.com/driftyco/ionicons 7 | */ 8 | 9 | @import "ionicons-font"; 10 | @import "ionicons-animation"; 11 | @import "ionicons-icons"; -------------------------------------------------------------------------------- /scss/ionic.app.scss: -------------------------------------------------------------------------------- 1 | //$light: #ff0045 !default; 2 | //$stable: #f80029 !default; 3 | //$positive: #4a87ee !default; 4 | //$calm: #43cee6 !default; 5 | //$balanced: #66cc33 !default; 6 | //$energized: #f0b840 !default; 7 | //$assertive: #ef4e3a !default; 8 | //$royal: #e90061 !default; 9 | //$dark: #e12000 !default; 10 | 11 | // The path for our ionicons font files, relative to the built CSS in www/css 12 | $ionicons-font-path: "../lib/ionic/fonts" !default; 13 | 14 | // Include all of Ionic 15 | @import "../www/lib/ionic/scss/ionic"; 16 | 17 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_split-pane.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Split Pane 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .split-pane { 8 | @include display-flex(); 9 | @include align-items(stretch); 10 | width: 100%; 11 | height: 100%; 12 | } 13 | 14 | .split-pane-menu { 15 | @include flex(0, 0, $split-pane-menu-width); 16 | 17 | overflow-y: auto; 18 | width: $split-pane-menu-width; 19 | height: 100%; 20 | border-right: 1px solid $split-pane-menu-border-color; 21 | 22 | @media all and (max-width: 568px) { 23 | border-right: none; 24 | } 25 | } 26 | 27 | .split-pane-content { 28 | @include flex(1, 0, auto); 29 | } 30 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/ionic.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | @import 4 | // Ionicons 5 | "ionicons/ionicons.scss", 6 | 7 | // Variables 8 | "mixins", 9 | "variables", 10 | 11 | // Base 12 | "reset", 13 | "scaffolding", 14 | "type", 15 | 16 | // Components 17 | "action-sheet", 18 | "bar", 19 | "tabs", 20 | "menu", 21 | "modal", 22 | "popup", 23 | "items", 24 | "list", 25 | "badge", 26 | "slide-box", 27 | "split-pane", 28 | 29 | // Forms 30 | "form", 31 | "checkbox", 32 | "toggle", 33 | "radio", 34 | "range", 35 | "progress", 36 | 37 | // Buttons 38 | "button", 39 | "button-bar", 40 | 41 | // Util 42 | "animations", 43 | "grid", 44 | "util", 45 | "platform"; 46 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var concat = require('gulp-concat'); 3 | var sass = require('gulp-sass'); 4 | var minifyCss = require('gulp-minify-css'); 5 | var rename = require('gulp-rename'); 6 | 7 | var paths = { 8 | sass: ['./scss/**/*.scss'] 9 | }; 10 | 11 | gulp.task('sass', function (done) { 12 | gulp.src('./scss/ionic.app.scss') 13 | .pipe(sass()) 14 | .pipe(gulp.dest('./www/css/')) 15 | .pipe(minifyCss({ 16 | keepSpecialComments: 0 17 | })) 18 | .pipe(rename({ extname: '.min.css' })) 19 | .pipe(gulp.dest('./www/css/')) 20 | .on('end', done); 21 | }); 22 | 23 | gulp.task('watch', function () { 24 | gulp.watch(paths.sass, ['sass']); 25 | }); 26 | 27 | gulp.task('default', ['sass']); 28 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SF Sample 4 | 5 | An Ionic Framework and Cordova project. 6 | 7 | 8 | Ionic Framework Team 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_menu.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Menus 4 | * -------------------------------------------------- 5 | * Side panel structure 6 | */ 7 | 8 | .menu { 9 | position: absolute; 10 | top: 0; 11 | bottom: 0; 12 | z-index: $z-index-menu; 13 | overflow: hidden; 14 | 15 | min-height: 100%; 16 | max-height: 100%; 17 | width: $menu-width; 18 | 19 | background-color: #fff; 20 | } 21 | 22 | .menu-content { 23 | @include transform(none); 24 | box-shadow: $menu-side-shadow; 25 | } 26 | 27 | .grade-b .menu-content, 28 | .grade-c .menu-content { 29 | @include box-sizing(content-box); 30 | right: -1px; 31 | left: -1px; 32 | border-right: 1px solid #ccc; 33 | border-left: 1px solid #ccc; 34 | box-shadow: none; 35 | } 36 | 37 | .menu-left { 38 | left: 0; 39 | } 40 | 41 | .menu-right { 42 | right: 0; 43 | } 44 | 45 | .menu-animated { 46 | @include transition-transform($menu-animation-speed ease); 47 | } 48 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/ionicons/_ionicons-font.scss: -------------------------------------------------------------------------------- 1 | // Ionicons Font Path 2 | // -------------------------- 3 | 4 | @font-face { 5 | font-family: $ionicons-font-family; 6 | src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}"); 7 | src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}#iefix") format("embedded-opentype"), 8 | url("#{$ionicons-font-path}/ionicons.ttf?v=#{$ionicons-version}") format("truetype"), 9 | url("#{$ionicons-font-path}/ionicons.woff?v=#{$ionicons-version}") format("woff"), 10 | url("#{$ionicons-font-path}/ionicons.svg?v=#{$ionicons-version}#Ionicons") format("svg"); 11 | font-weight: normal; 12 | font-style: normal; 13 | } 14 | 15 | .ion { 16 | display: inline-block; 17 | font-family: $ionicons-font-family; 18 | speak: none; 19 | font-style: normal; 20 | font-weight: normal; 21 | font-variant: normal; 22 | text-transform: none; 23 | text-rendering: auto; 24 | line-height: 1; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } -------------------------------------------------------------------------------- /www/lib/ionic/scss/_button-bar.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Button Bar 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .button-bar { 8 | @include display-flex(); 9 | @include flex(1); 10 | width: 100%; 11 | 12 | &.button-bar-inline { 13 | display: block; 14 | width: auto; 15 | 16 | @include clearfix(); 17 | 18 | > .button { 19 | width: auto; 20 | display: inline-block; 21 | float: left; 22 | } 23 | } 24 | } 25 | 26 | .button-bar > .button { 27 | @include flex(1); 28 | display: block; 29 | 30 | overflow: hidden; 31 | 32 | padding: 0 16px; 33 | 34 | width: 0; 35 | 36 | border-width: 1px 0px 1px 1px; 37 | border-radius: 0; 38 | text-align: center; 39 | text-overflow: ellipsis; 40 | white-space: nowrap; 41 | 42 | &:before, 43 | .icon:before { 44 | line-height: 44px; 45 | } 46 | 47 | &:first-child { 48 | border-radius: 2px 0px 0px 2px; 49 | } 50 | &:last-child { 51 | border-right-width: 1px; 52 | border-radius: 0px 2px 2px 0px; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /www/js/services.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Services 3 | */ 4 | 5 | // auth service 6 | app.factory('auth', function ($window, salesforce_client_id) { 7 | 8 | return { 9 | 10 | get: function () { 11 | var data = $window.localStorage.auth; 12 | console.log('auth.get', data); 13 | return data ? JSON.parse(data) : false; 14 | }, 15 | 16 | set: function (data) { 17 | data = JSON.stringify(data); 18 | console.log('auth.set', data); 19 | $window.localStorage.auth = data; 20 | }, 21 | 22 | erase: function () { 23 | delete $window.localStorage.auth; 24 | }, 25 | 26 | // open OAuth page in external browser 27 | openLogin: function () { 28 | $window.open( 29 | 'https://login.salesforce.com/services/oauth2/authorize' + 30 | '?response_type=token&display=touch' + 31 | '&redirect_uri=sfsampleapp://oauth-callback' + 32 | '&client_id=' + salesforce_client_id, 33 | '_system', 34 | 'location=yes' 35 | ) 36 | } 37 | 38 | } 39 | 40 | }); 41 | 42 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_slide-box.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Slide Box 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .slider { 8 | position: relative; 9 | visibility: hidden; 10 | // Make sure items don't scroll over ever 11 | overflow: hidden; 12 | } 13 | 14 | .slider-slides { 15 | position: relative; 16 | height: 100%; 17 | } 18 | 19 | .slider-slide { 20 | position: relative; 21 | display: block; 22 | float: left; 23 | width: 100%; 24 | height: 100%; 25 | vertical-align: top; 26 | } 27 | 28 | .slider-slide-image { 29 | > img { 30 | width: 100%; 31 | } 32 | } 33 | 34 | .slider-pager { 35 | position: absolute; 36 | bottom: 20px; 37 | z-index: $z-index-slider-pager; 38 | width: 100%; 39 | height: 15px; 40 | text-align: center; 41 | 42 | .slider-pager-page { 43 | display: inline-block; 44 | margin: 0px 3px; 45 | width: 15px; 46 | color: #000; 47 | text-decoration: none; 48 | 49 | opacity: 0.3; 50 | 51 | &.active { 52 | @include transition(opacity 0.4s ease-in); 53 | opacity: 1; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_platform.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Platform 4 | * -------------------------------------------------- 5 | * Platform specific tweaks when in Cordova. 6 | */ 7 | 8 | .platform-ios7.platform-cordova:not(.fullscreen) { 9 | // iOS7 has a status bar which sits on top of the header. 10 | // Bump down everything to make room for it. However, if 11 | // if its in Cordova, and set to fullscreen, then disregard the bump. 12 | 13 | .bar-header { 14 | height: 64px; 15 | 16 | &.item-input-inset .item-input-wrapper { 17 | margin-top: 19px !important; 18 | } 19 | 20 | > * { 21 | margin-top: 20px; 22 | } 23 | } 24 | 25 | .has-header, 26 | .bar-subheader { 27 | top: 64px; 28 | } 29 | 30 | .has-subheader { 31 | top: 108px; 32 | } 33 | } 34 | 35 | .platform-ios7.status-bar-hide { 36 | // Cordova doesn't adjust the body height correctly, this makes up for it 37 | margin-bottom: 20px; 38 | } 39 | 40 | .platform-android.platform-cordova { 41 | 42 | .bar-header { 43 | height: 48px; 44 | } 45 | 46 | .has-header, 47 | .bar-subheader { 48 | top: 48px; 49 | } 50 | 51 | .has-subheader { 52 | top: 96px; 53 | } 54 | 55 | .title { 56 | line-height: 48px; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_radio.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Radio Button Inputs 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .item-radio { 8 | padding: 0; 9 | 10 | &:hover { 11 | cursor: pointer; 12 | } 13 | } 14 | 15 | .item-radio .item-content { 16 | /* give some room to the right for the checkmark icon */ 17 | padding-right: $item-padding * 4; 18 | } 19 | 20 | .item-radio .radio-icon { 21 | /* checkmark icon will be hidden by default */ 22 | position: absolute; 23 | top: 0; 24 | right: 0; 25 | z-index: $z-index-item-radio; 26 | visibility: hidden; 27 | padding: $item-padding - 2; 28 | height: 100%; 29 | font-size: 24px; 30 | } 31 | 32 | .item-radio input { 33 | /* hide any radio button inputs elements (the ugly circles) */ 34 | position: absolute; 35 | left: -9999px; 36 | 37 | &:checked ~ .item-content { 38 | /* style the item content when its checked */ 39 | background: #f7f7f7; 40 | } 41 | 42 | &:checked ~ .radio-icon { 43 | /* show the checkmark icon when its checked */ 44 | visibility: visible; 45 | } 46 | } 47 | 48 | // Hack for Android to correctly display the checked item 49 | // http://timpietrusky.com/advanced-checkbox-hack 50 | .item-radio { 51 | -webkit-animation: androidCheckedbugfix infinite 1s; 52 | } 53 | @-webkit-keyframes androidCheckedbugfix { 54 | from { padding:0; } 55 | to { padding:0; } 56 | } 57 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_modal.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Modals 4 | * -------------------------------------------------- 5 | * Modals are independent windows that slide in from off-screen. 6 | */ 7 | 8 | .modal-backdrop { 9 | @include transition(background-color 300ms ease-in-out); 10 | position: fixed; 11 | top: 0; 12 | left: 0; 13 | z-index: $z-index-modal; 14 | width: 100%; 15 | height: 100%; 16 | background-color: $modal-backdrop-bg-inactive; 17 | 18 | &.active { 19 | background-color: $modal-backdrop-bg-active; 20 | } 21 | } 22 | 23 | .modal { 24 | position: absolute; 25 | top: 0; 26 | z-index: $z-index-modal; 27 | overflow: hidden; 28 | min-height: 100%; 29 | width: 100%; 30 | background-color: $modal-bg-color; 31 | } 32 | 33 | @media (min-width: $modal-inset-mode-break-point) { 34 | // inset mode is when the modal doesn't fill the entire 35 | // display but instead is centered within a large display 36 | .modal { 37 | top: $modal-inset-mode-top; 38 | right: $modal-inset-mode-right; 39 | bottom: $modal-inset-mode-bottom; 40 | left: $modal-inset-mode-left; 41 | overflow: visible; 42 | min-height: $modal-inset-mode-min-height; 43 | width: (100% - $modal-inset-mode-left - $modal-inset-mode-right); 44 | } 45 | 46 | .modal.ng-leave-active { 47 | bottom: 0; 48 | } 49 | } 50 | 51 | .modal-open { 52 | pointer-events: none; 53 | 54 | .modal { 55 | pointer-events: auto; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_badge.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Badges 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .badge { 8 | @include badge-style($badge-default-bg, $badge-default-text); 9 | z-index: $z-index-badge; 10 | display: inline-block; 11 | padding: 3px 8px; 12 | min-width: 10px; 13 | border-radius: $badge-border-radius; 14 | vertical-align: baseline; 15 | text-align: center; 16 | white-space: nowrap; 17 | font-weight: $badge-font-weight; 18 | font-size: $badge-font-size; 19 | line-height: $badge-line-height; 20 | 21 | &:empty { 22 | display: none; 23 | } 24 | } 25 | 26 | //Be sure to override specificity of rule that 'badge color matches tab color by default' 27 | .tabs .tab-item .badge, 28 | .badge { 29 | &.badge-light { 30 | @include badge-style($badge-light-bg, $badge-light-text); 31 | } 32 | &.badge-stable { 33 | @include badge-style($badge-stable-bg, $badge-stable-text); 34 | } 35 | &.badge-positive { 36 | @include badge-style($badge-positive-bg, $badge-positive-text); 37 | } 38 | &.badge-calm { 39 | @include badge-style($badge-calm-bg, $badge-calm-text); 40 | } 41 | &.badge-assertive { 42 | @include badge-style($badge-assertive-bg, $badge-assertive-text); 43 | } 44 | &.badge-balanced { 45 | @include badge-style($badge-balanced-bg, $badge-balanced-text); 46 | } 47 | &.badge-energized { 48 | @include badge-style($badge-energized-bg, $badge-energized-text); 49 | } 50 | &.badge-royal { 51 | @include badge-style($badge-royal-bg, $badge-royal-text); 52 | } 53 | &.badge-dark { 54 | @include badge-style($badge-dark-bg, $badge-dark-text); 55 | } 56 | } 57 | 58 | // Quick fix for labels/badges in buttons 59 | .button .badge { 60 | position: relative; 61 | top: -1px; 62 | } 63 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_action-sheet.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Action Sheets 3 | * -------------------------------------------------- 4 | */ 5 | 6 | .action-sheet-backdrop { 7 | @include transition(background-color 300ms ease-in-out); 8 | position: fixed; 9 | top: 0; 10 | left: 0; 11 | z-index: $z-index-action-sheet; 12 | width: 100%; 13 | height: 100%; 14 | background-color: rgba(0,0,0,0); 15 | 16 | &.active { 17 | background-color: rgba(0,0,0,0.5); 18 | } 19 | } 20 | 21 | .action-sheet-wrapper { 22 | @include translate3d(0, 100%, 0); 23 | @include transition(all ease-in-out 300ms); 24 | position: absolute; 25 | bottom: 0; 26 | width: 100%; 27 | } 28 | 29 | .action-sheet-up { 30 | @include translate3d(0, 0, 0); 31 | } 32 | 33 | .action-sheet { 34 | margin-left: 15px; 35 | margin-right: 15px; 36 | width: auto; 37 | z-index: $z-index-action-sheet; 38 | overflow: hidden; 39 | 40 | .button { 41 | display: block; 42 | padding: 1px; 43 | width: 100%; 44 | border-radius: 0; 45 | 46 | background-color: transparent; 47 | 48 | color: $positive; 49 | font-size: 18px; 50 | 51 | &.destructive { 52 | color: $assertive; 53 | } 54 | } 55 | } 56 | 57 | .action-sheet-title { 58 | padding: 10px; 59 | color: lighten($base-color, 40%); 60 | text-align: center; 61 | font-size: 12px; 62 | } 63 | 64 | .action-sheet-group { 65 | margin-bottom: 5px; 66 | border-radius: $sheet-border-radius; 67 | background-color: #fff; 68 | .button { 69 | border-width: 1px 0px 0px 0px; 70 | border-radius: 0; 71 | 72 | &.active { 73 | background-color: transparent; 74 | color: inherit; 75 | } 76 | } 77 | .button:first-child:last-child { 78 | border-width: 0; 79 | } 80 | } 81 | 82 | .action-sheet-open { 83 | pointer-events: none; 84 | 85 | &.modal-open .modal { 86 | pointer-events: none; 87 | } 88 | 89 | .action-sheet-backdrop { 90 | pointer-events: auto; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/ionicons/_ionicons-animation.scss: -------------------------------------------------------------------------------- 1 | // Animation Icons 2 | // -------------------------- 3 | 4 | .#{$ionicons-prefix}spin { 5 | -webkit-animation: spin 1s infinite linear; 6 | -moz-animation: spin 1s infinite linear; 7 | -o-animation: spin 1s infinite linear; 8 | animation: spin 1s infinite linear; 9 | } 10 | 11 | @-moz-keyframes spin { 12 | 0% { -moz-transform: rotate(0deg); } 13 | 100% { -moz-transform: rotate(359deg); } 14 | } 15 | @-webkit-keyframes spin { 16 | 0% { -webkit-transform: rotate(0deg); } 17 | 100% { -webkit-transform: rotate(359deg); } 18 | } 19 | @-o-keyframes spin { 20 | 0% { -o-transform: rotate(0deg); } 21 | 100% { -o-transform: rotate(359deg); } 22 | } 23 | @-ms-keyframes spin { 24 | 0% { -ms-transform: rotate(0deg); } 25 | 100% { -ms-transform: rotate(359deg); } 26 | } 27 | @keyframes spin { 28 | 0% { transform: rotate(0deg); } 29 | 100% { transform: rotate(359deg); } 30 | } 31 | 32 | 33 | .#{$ionicons-prefix}loading-a, 34 | .#{$ionicons-prefix}loading-b, 35 | .#{$ionicons-prefix}loading-c, 36 | .#{$ionicons-prefix}loading-d, 37 | .#{$ionicons-prefix}looping, 38 | .#{$ionicons-prefix}refreshing, 39 | .#{$ionicons-prefix}ios7-reloading { 40 | @extend .ion; 41 | @extend .#{$ionicons-prefix}spin; 42 | } 43 | 44 | .#{$ionicons-prefix}loading-a { 45 | -webkit-animation-timing-function: steps(8, start); 46 | -moz-animation-timing-function: steps(8, start); 47 | animation-timing-function: steps(8, start); 48 | } 49 | 50 | .#{$ionicons-prefix}loading-a:before { 51 | @extend .#{$ionicons-prefix}load-a:before; 52 | } 53 | 54 | .#{$ionicons-prefix}loading-b:before { 55 | @extend .#{$ionicons-prefix}load-b:before; 56 | } 57 | 58 | .#{$ionicons-prefix}loading-c:before { 59 | @extend .#{$ionicons-prefix}load-c:before; 60 | } 61 | 62 | .#{$ionicons-prefix}loading-d:before { 63 | @extend .#{$ionicons-prefix}load-d:before; 64 | } 65 | 66 | .#{$ionicons-prefix}looping:before { 67 | @extend .#{$ionicons-prefix}loop:before; 68 | } 69 | 70 | .#{$ionicons-prefix}refreshing:before { 71 | @extend .#{$ionicons-prefix}refresh:before; 72 | } 73 | 74 | .#{$ionicons-prefix}ios7-reloading:before { 75 | @extend .#{$ionicons-prefix}ios7-reload:before; 76 | } 77 | -------------------------------------------------------------------------------- /www/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * App configuration and initialisation 3 | */ 4 | 5 | // handle custom url scheme 6 | function handleOpenURL(url) { 7 | 8 | var path = url.match('://(.*?)[\\?#]')[1]; 9 | 10 | if (path == 'oauth-callback') { 11 | 12 | // get hash part 13 | var query = url.substr(url.indexOf("#") + 1); 14 | 15 | var data = {}; 16 | 17 | // split into parts 18 | var parts = query.split('&'); 19 | 20 | // read names and values 21 | for (var i = 0; i < parts.length; i++) { 22 | var name = parts[i].substr(0, parts[i].indexOf('=')); 23 | var val = parts[i].substr(parts[i].indexOf('=') + 1); 24 | val = decodeURIComponent(val); 25 | data[name] = val; 26 | } 27 | 28 | // save auth using LayoutController 29 | 30 | var $scope = angular.element(document.body).scope(); 31 | 32 | $scope.$apply(function () { 33 | $scope.onAuth(data); 34 | }); 35 | } 36 | } 37 | 38 | // 39 | 40 | var app = angular.module('SFSample', ['ionic']) 41 | 42 | .run(function ($ionicPlatform, $window) { 43 | $ionicPlatform.ready(function () { 44 | if ($window.StatusBar) { 45 | StatusBar.styleDefault(); 46 | } 47 | }); 48 | }) 49 | 50 | .config(function ($stateProvider, $urlRouterProvider) { 51 | 52 | $stateProvider 53 | 54 | .state('tab', { 55 | url: "/tab", 56 | abstract: true, 57 | templateUrl: 'views/tabs.html' 58 | }) 59 | 60 | .state('tab.tracking', { 61 | url: '/tracking', 62 | views: { 63 | 'tab-tracking': { 64 | templateUrl: 'views/tab-tracking.html', 65 | controller: 'TrackingController' 66 | } 67 | } 68 | }) 69 | 70 | .state('tab.history', { 71 | url: '/history', 72 | views: { 73 | 'tab-history': { 74 | templateUrl: 'views/tab-history.html', 75 | controller: 'HistoryController' 76 | } 77 | } 78 | }) 79 | 80 | // default state 81 | $urlRouterProvider.otherwise('/tab/tracking'); 82 | 83 | }) 84 | 85 | // check auth data 86 | .run(function ($ionicPlatform, auth) { 87 | 88 | $ionicPlatform.ready(function () { 89 | if (false === auth.get()) { 90 | auth.openLogin(); 91 | } 92 | }) 93 | }) 94 | 95 | // configuration 96 | .constant('salesforce_client_id', '---your-app-client-id---') -------------------------------------------------------------------------------- /www/lib/ionic/scss/_list.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Lists 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .list { 8 | position: relative; 9 | padding-top: $item-border-width; 10 | padding-bottom: $item-border-width; 11 | padding-left: 0; // reset padding because ul and ol 12 | margin-bottom: 20px; 13 | } 14 | .list:last-child { 15 | margin-bottom: 0px; 16 | } 17 | 18 | 19 | /** 20 | * List Header 21 | * -------------------------------------------------- 22 | */ 23 | 24 | .list-header { 25 | margin-top: $list-header-margin-top; 26 | padding: $list-header-padding; 27 | background-color: $list-header-bg; 28 | color: $list-header-color; 29 | font-weight: bold; 30 | } 31 | 32 | // when its a card make sure it doesn't duplicate top and bottom borders 33 | .card.list .list-item { 34 | padding-right: 1px; 35 | padding-left: 1px; 36 | } 37 | 38 | 39 | /** 40 | * Cards and Inset Lists 41 | * -------------------------------------------------- 42 | * A card and list-inset are close to the same thing, except a card as a box shadow. 43 | */ 44 | 45 | .card, 46 | .list-inset { 47 | overflow: hidden; 48 | margin: ($content-padding * 2) $content-padding; 49 | border-radius: $card-border-radius; 50 | background-color: $card-body-bg; 51 | } 52 | 53 | .card { 54 | padding-top: $item-border-width; 55 | padding-bottom: $item-border-width; 56 | box-shadow: 0 1px 1px rgba(0, 0, 0, .1); 57 | } 58 | 59 | .card .item, 60 | .list-inset .item, 61 | .padding > .list .item 62 | { 63 | &:first-child { 64 | border-top-left-radius: $card-border-radius; 65 | border-top-right-radius: $card-border-radius; 66 | 67 | .item-content { 68 | border-top-left-radius: $card-border-radius; 69 | border-top-right-radius: $card-border-radius; 70 | } 71 | } 72 | &:last-child { 73 | border-bottom-right-radius: $card-border-radius; 74 | border-bottom-left-radius: $card-border-radius; 75 | 76 | .item-content { 77 | border-bottom-right-radius: $card-border-radius; 78 | border-bottom-left-radius: $card-border-radius; 79 | } 80 | } 81 | } 82 | 83 | .card .item:last-child, 84 | .list-inset .item:last-child { 85 | margin-bottom: $item-border-width * -1; 86 | } 87 | 88 | .card .item, 89 | .list-inset .item, 90 | .padding > .list .item, 91 | .padding-horizontal > .list .item { 92 | margin-right: 0; 93 | margin-left: 0; 94 | } 95 | .padding-left > .list .item { 96 | margin-left: 0; 97 | } 98 | .padding-right > .list .item { 99 | margin-right: 0; 100 | } 101 | -------------------------------------------------------------------------------- /www/lib/ionic/js/angular/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.12 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)!p.hasOwnProperty(c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&& 7 | b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f 21 | # Cordova Hooks 22 | 23 | This directory may contain scripts used to customize cordova commands. This 24 | directory used to exist at `.cordova/hooks`, but has now been moved to the 25 | project root. Any scripts you add to these directories will be executed before 26 | and after the commands corresponding to the directory name. Useful for 27 | integrating your own build systems or integrating with version control systems. 28 | 29 | __Remember__: Make your scripts executable. 30 | 31 | ## Hook Directories 32 | The following subdirectories will be used for hooks: 33 | 34 | after_build/ 35 | after_compile/ 36 | after_docs/ 37 | after_emulate/ 38 | after_platform_add/ 39 | after_platform_rm/ 40 | after_platform_ls/ 41 | after_plugin_add/ 42 | after_plugin_ls/ 43 | after_plugin_rm/ 44 | after_plugin_search/ 45 | after_prepare/ 46 | after_run/ 47 | after_serve/ 48 | before_build/ 49 | before_compile/ 50 | before_docs/ 51 | before_emulate/ 52 | before_platform_add/ 53 | before_platform_rm/ 54 | before_platform_ls/ 55 | before_plugin_add/ 56 | before_plugin_ls/ 57 | before_plugin_rm/ 58 | before_plugin_search/ 59 | before_prepare/ 60 | before_run/ 61 | before_serve/ 62 | pre_package/ <-- Windows 8 and Windows Phone only. 63 | 64 | ## Script Interface 65 | 66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 67 | 68 | * CORDOVA_VERSION - The version of the Cordova-CLI. 69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 71 | * CORDOVA_HOOK - Path to the hook that is being executed. 72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 73 | 74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 75 | 76 | 77 | ## Writing hooks 78 | 79 | We highly recommend writting your hooks using Node.js so that they are 80 | cross-platform. Some good examples are shown here: 81 | 82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 83 | 84 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_popup.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Popups 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .popup { 8 | position: fixed; 9 | top: 50%; 10 | left: 50%; 11 | z-index: $z-index-popup; 12 | 13 | // Start hidden 14 | visibility: hidden; 15 | 16 | width: $popup-width; 17 | 18 | border-radius: $popup-border-radius; 19 | background-color: $popup-background-color; 20 | 21 | &.popup-hidden { 22 | @include animation-name(scaleOut); 23 | @include animation-duration($popup-leave-animation-duration); 24 | @include animation-timing-function(ease-in-out); 25 | @include animation-fill-mode(both); 26 | } 27 | 28 | &.popup-showing { 29 | visibility: visible; 30 | } 31 | 32 | &.active { 33 | @include animation-name(superScaleIn); 34 | @include animation-duration($popup-enter-animation-duration); 35 | @include animation-timing-function(ease-in-out); 36 | @include animation-fill-mode(both); 37 | } 38 | } 39 | 40 | .popup-head { 41 | padding: 15px 0px; 42 | border-bottom: 1px solid #eee; 43 | text-align: center; 44 | } 45 | .popup-title { 46 | margin: 0; 47 | padding: 0; 48 | font-size: 15px; 49 | } 50 | .popup-sub-title { 51 | margin: 5px 0 0 0; 52 | padding: 0; 53 | font-weight: normal; 54 | font-size: 11px; 55 | } 56 | .popup-body { 57 | padding: 10px; 58 | } 59 | 60 | .popup-buttons { 61 | &.row { 62 | padding: 10px 10px; 63 | } 64 | 65 | .button { 66 | margin: 0px 5px; 67 | min-height: $popup-button-min-height; 68 | border-radius: $popup-button-border-radius; 69 | line-height: $popup-button-line-height; 70 | 71 | &:first-child { 72 | margin-left: 0px; 73 | } 74 | &:last-child { 75 | margin-right: 0px; 76 | } 77 | } 78 | } 79 | 80 | .popup-open { 81 | pointer-events: none; 82 | 83 | &.modal-open .modal { 84 | pointer-events: none; 85 | } 86 | 87 | .popup-backdrop, .popup { 88 | pointer-events: auto; 89 | } 90 | } 91 | 92 | .popup-backdrop { 93 | @include animation-name(fadeIn); 94 | @include animation-duration($popup-backdrop-fadein-duration); 95 | @include animation-timing-function(linear); 96 | @include animation-fill-mode(both); 97 | 98 | position: fixed; 99 | top: 0; 100 | left: 0; 101 | z-index: $z-index-popup-backdrop; 102 | 103 | width: 100%; 104 | height: 100%; 105 | 106 | background-color: rgba(0,0,0,0.4); 107 | } 108 | 109 | .loading-backdrop { 110 | @include transition(visibility 0s linear 0.3s); 111 | position: fixed; 112 | top: 0; 113 | left: 0; 114 | z-index: $z-index-popup-backdrop; 115 | 116 | visibility: hidden; 117 | width: 100%; 118 | height: 100%; 119 | 120 | &.active { 121 | @include transition-delay(0s); 122 | visibility: visible; 123 | &.show-backdrop { 124 | background-color: rgba(0,0,0,0.7); 125 | } 126 | } 127 | } 128 | 129 | .loading { 130 | position: fixed; 131 | top: 50%; 132 | left: 50%; 133 | padding: 20px; 134 | 135 | border-radius: 5px; 136 | background-color: rgba(0,0,0,0.7); 137 | 138 | color: #fff; 139 | 140 | text-align: center; 141 | text-overflow: ellipsis; 142 | font-size: 15px; 143 | 144 | h1, h2, h3, h4, h5, h6 { 145 | color: #fff; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_grid.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Grid 4 | * -------------------------------------------------- 5 | * Using flexbox for the grid, inspired by Philip Walton: 6 | * http://philipwalton.github.io/solved-by-flexbox/demos/grids/ 7 | * By default each .col within a .row will evenly take up 8 | * available width, and the height of each .col with take 9 | * up the height of the tallest .col in the same .row. 10 | */ 11 | 12 | .row { 13 | @include display-flex(); 14 | padding: ($grid-padding-width / 2); 15 | width: 100%; 16 | } 17 | 18 | .row + .row { 19 | margin-top: ($grid-padding-width / 2) * -1; 20 | padding-top: 0; 21 | } 22 | 23 | .col { 24 | @include flex(1); 25 | display: block; 26 | padding: ($grid-padding-width / 2); 27 | width: 100%; 28 | } 29 | 30 | 31 | /* Vertically Align Columns */ 32 | /* .row-* vertically aligns every .col in the .row */ 33 | .row-top { 34 | @include align-items(flex-start); 35 | } 36 | .row-bottom { 37 | @include align-items(flex-end); 38 | } 39 | .row-center { 40 | @include align-items(center); 41 | } 42 | 43 | /* .col-* vertically aligns an individual .col */ 44 | .col-top { 45 | @include align-self(flex-start); 46 | } 47 | .col-bottom { 48 | @include align-self(flex-end); 49 | } 50 | .col-center { 51 | @include align-self(center); 52 | } 53 | 54 | /* Column Offsets */ 55 | .col-offset-10 { 56 | margin-left: 10%; 57 | } 58 | .col-offset-20 { 59 | margin-left: 20%; 60 | } 61 | .col-offset-25 { 62 | margin-left: 25%; 63 | } 64 | .col-offset-33, .col-offset-34 { 65 | margin-left: 33.3333%; 66 | } 67 | .col-offset-50 { 68 | margin-left: 50%; 69 | } 70 | .col-offset-66, .col-offset-67 { 71 | margin-left: 66.6666%; 72 | } 73 | .col-offset-75 { 74 | margin-left: 75%; 75 | } 76 | .col-offset-80 { 77 | margin-left: 80%; 78 | } 79 | .col-offset-90 { 80 | margin-left: 90%; 81 | } 82 | 83 | 84 | /* Explicit Column Percent Sizes */ 85 | /* By default each grid column will evenly distribute */ 86 | /* across the grid. However, you can specify individual */ 87 | /* columns to take up a certain size of the available area */ 88 | .col-10 { 89 | @include flex(0, 0, 10%); 90 | max-width: 10%; 91 | } 92 | .col-20 { 93 | @include flex(0, 0, 20%); 94 | max-width: 20%; 95 | } 96 | .col-25 { 97 | @include flex(0, 0, 25%); 98 | max-width: 25%; 99 | } 100 | .col-33, .col-34 { 101 | @include flex(0, 0, 33.3333%); 102 | max-width: 33.3333%; 103 | } 104 | .col-50 { 105 | @include flex(0, 0, 50%); 106 | max-width: 50%; 107 | } 108 | .col-66, .col-67 { 109 | @include flex(0, 0, 66.6666%); 110 | max-width: 66.6666%; 111 | } 112 | .col-75 { 113 | @include flex(0, 0, 75%); 114 | max-width: 75%; 115 | } 116 | .col-80 { 117 | @include flex(0, 0, 80%); 118 | max-width: 80%; 119 | } 120 | .col-90 { 121 | @include flex(0, 0, 90%); 122 | max-width: 90%; 123 | } 124 | 125 | 126 | /* Responsive Grid Classes */ 127 | /* Adding a class of responsive-X to a row */ 128 | /* will trigger the flex-direction to */ 129 | /* change to column and add some margin */ 130 | /* to any columns in the row for clearity */ 131 | 132 | @include responsive-grid-break('.responsive-sm', $grid-responsive-sm-break); 133 | @include responsive-grid-break('.responsive-md', $grid-responsive-md-break); 134 | @include responsive-grid-break('.responsive-lg', $grid-responsive-lg-break); 135 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_range.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Range 4 | * -------------------------------------------------- 5 | */ 6 | 7 | input[type="range"] { 8 | display: inline-block; 9 | overflow: hidden; 10 | margin-top: 5px; 11 | margin-bottom: 5px; 12 | padding-right: 2px; 13 | padding-left: 1px; 14 | width: auto; 15 | height: $range-slider-height + 15; 16 | outline: none; 17 | background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, $range-default-track-bg), color-stop(100%, $range-default-track-bg)); 18 | background: linear-gradient(to right, $range-default-track-bg 0%, $range-default-track-bg 100%); 19 | background-position: center; 20 | background-size: 99% $range-track-height; 21 | background-repeat: no-repeat; 22 | -webkit-appearance: none; 23 | 24 | &::-webkit-slider-thumb { 25 | position: relative; 26 | width: $range-slider-width; 27 | height: $range-slider-height; 28 | border-radius: $range-slider-border-radius; 29 | background-color: $toggle-handle-off-bg-color; 30 | box-shadow: 0 0 2px rgba(0,0,0,.5), 1px 3px 5px rgba(0,0,0,0.25); 31 | cursor: pointer; 32 | -webkit-appearance: none; 33 | } 34 | 35 | &::-webkit-slider-thumb:before { 36 | /* what creates the colorful line on the left side of the slider */ 37 | position: absolute; 38 | top: ($range-slider-height / 2) - ($range-track-height / 2); 39 | left: -2001px; 40 | width: 2000px; 41 | height: $range-track-height; 42 | background: $dark; 43 | content: ' '; 44 | } 45 | 46 | &::-webkit-slider-thumb:after { 47 | /* create a larger (but hidden) hit area */ 48 | position: absolute; 49 | top: -20px; 50 | left: -20px; 51 | padding: 30px; 52 | content: ' '; 53 | //background: red; 54 | //opacity: .5; 55 | } 56 | 57 | } 58 | 59 | .range { 60 | @include display-flex(); 61 | @include align-items(center); 62 | padding: 2px 4px; 63 | 64 | &.range-light { 65 | input { @include range-style($range-light-track-bg); } 66 | } 67 | &.range-stable { 68 | input { @include range-style($range-stable-track-bg); } 69 | } 70 | &.range-positive { 71 | input { @include range-style($range-positive-track-bg); } 72 | } 73 | &.range-calm { 74 | input { @include range-style($range-calm-track-bg); } 75 | } 76 | &.range-balanced { 77 | input { @include range-style($range-balanced-track-bg); } 78 | } 79 | &.range-assertive { 80 | input { @include range-style($range-assertive-track-bg); } 81 | } 82 | &.range-energized { 83 | input { @include range-style($range-energized-track-bg); } 84 | } 85 | &.range-royal { 86 | input { @include range-style($range-royal-track-bg); } 87 | } 88 | &.range-dark { 89 | input { @include range-style($range-dark-track-bg); } 90 | } 91 | } 92 | 93 | .range .icon { 94 | @include flex(0); 95 | display: block; 96 | min-width: $range-icon-size; 97 | text-align: center; 98 | font-size: $range-icon-size; 99 | } 100 | 101 | .range input { 102 | @include flex(1); 103 | display: block; 104 | margin-right: 10px; 105 | margin-left: 10px; 106 | } 107 | 108 | .range-label { 109 | @include flex(0, 0, auto); 110 | display: block; 111 | white-space: nowrap; 112 | } 113 | 114 | .range-label:first-child { 115 | padding-left: 5px; 116 | } 117 | .range input + .range-label { 118 | padding-right: 5px; 119 | padding-left: 0; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_checkbox.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Checkbox 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .checkbox { 8 | // set the color defaults 9 | @include checkbox-style($checkbox-off-border-default, $checkbox-on-bg-default); 10 | 11 | position: relative; 12 | display: inline-block; 13 | padding: ($checkbox-height / 4) ($checkbox-width / 4); 14 | cursor: pointer; 15 | 16 | &.checkbox-light { 17 | @include checkbox-style($checkbox-off-border-light, $checkbox-on-bg-light); 18 | } 19 | &.checkbox-stable { 20 | @include checkbox-style($checkbox-off-border-stable, $checkbox-on-bg-stable); 21 | } 22 | &.checkbox-positive { 23 | @include checkbox-style($checkbox-off-border-positive, $checkbox-on-bg-positive); 24 | } 25 | &.checkbox-calm { 26 | @include checkbox-style($checkbox-off-border-calm, $checkbox-on-bg-calm); 27 | } 28 | &.checkbox-assertive { 29 | @include checkbox-style($checkbox-off-border-assertive, $checkbox-on-bg-assertive); 30 | } 31 | &.checkbox-balanced { 32 | @include checkbox-style($checkbox-off-border-balanced, $checkbox-on-bg-balanced); 33 | } 34 | &.checkbox-energized { 35 | @include checkbox-style($checkbox-off-border-energized, $checkbox-on-bg-energized); 36 | } 37 | &.checkbox-royal { 38 | @include checkbox-style($checkbox-off-border-royal, $checkbox-on-bg-royal); 39 | } 40 | &.checkbox-dark { 41 | @include checkbox-style($checkbox-off-border-dark, $checkbox-on-bg-dark); 42 | } 43 | } 44 | 45 | .checkbox input { 46 | position: relative; 47 | width: $checkbox-width; 48 | height: $checkbox-height; 49 | border: 0; 50 | background: transparent; 51 | cursor: pointer; 52 | -webkit-appearance: none; 53 | 54 | &:before { 55 | /* what the checkbox looks like when its not checked */ 56 | display: table; 57 | width: 100%; 58 | height: 100%; 59 | border-radius: $checkbox-border-radius; 60 | background: $checkbox-off-bg-color; 61 | content: ' '; 62 | transition: background-color .1s ease-in-out; 63 | } 64 | } 65 | 66 | /* the checkmark within the box */ 67 | .checkbox input:after { 68 | @include transition(opacity .05s ease-in-out); 69 | @include rotate(-45deg); 70 | position: absolute; 71 | top: 30%; 72 | left: 26%; 73 | display: table; 74 | width: ($checkbox-width / 2) + 1; 75 | height: ($checkbox-width / 3) + 1; 76 | border: $checkbox-check-width solid $checkbox-check-color; 77 | border-top: 0; 78 | border-right: 0; 79 | content: ' '; 80 | opacity: 0; 81 | } 82 | 83 | .grade-c .checkbox input:after { 84 | @include rotate(0); 85 | top: 3px; 86 | left: 4px; 87 | border: none; 88 | color: $checkbox-check-color; 89 | font-weight: bold; 90 | font-size: 20px; 91 | content: '\2713'; 92 | } 93 | 94 | /* what the checkmark looks like when its checked */ 95 | .checkbox input:checked:after { 96 | opacity: 1; 97 | } 98 | 99 | /* make sure item content have enough padding on left to fit the checkbox */ 100 | .item-checkbox { 101 | padding-left: ($item-padding * 2) + $checkbox-width; 102 | 103 | &.active { 104 | box-shadow: none; 105 | } 106 | } 107 | 108 | /* position the checkbox to the left within an item */ 109 | .item-checkbox .checkbox { 110 | @include display-flex(); 111 | @include align-items(center); 112 | position: absolute; 113 | top: 0; 114 | left: $item-padding / 2; 115 | z-index: $z-index-item-checkbox; 116 | height: 100%; 117 | } 118 | -------------------------------------------------------------------------------- /www/js/controllers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Controllers 3 | */ 4 | 5 | app.controller('LayoutController', function ($scope, auth) { 6 | // save auth data 7 | $scope.onAuth = function (authData) { 8 | auth.set(authData); 9 | } 10 | }); 11 | 12 | app.controller('TrackingController', function ($scope, auth, $rootScope) { 13 | 14 | $scope.input = {}; 15 | 16 | var positionWatchId; 17 | 18 | $scope.$watch('input.enableTracking', function (val) { 19 | if (val) { 20 | 21 | var authData = auth.get(); 22 | var positionList = []; 23 | $rootScope.positionObjectId = null; 24 | 25 | $.ajax({ 26 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c', 27 | type: 'POST', 28 | headers: { 29 | 'Authorization': authData.token_type + ' ' + authData.access_token, 30 | 'Content-type': 'application/json' 31 | }, 32 | data: JSON.stringify({'Data__c': ''}), 33 | }) 34 | 35 | .then(function ok(e) { 36 | 37 | $rootScope.$apply(function () { 38 | $rootScope.positionObjectId = e.id; 39 | }) 40 | 41 | // start position watch 42 | positionWatchId = navigator.geolocation.watchPosition(function (e) { 43 | 44 | positionList.unshift([e.coords.latitude, e.coords.longitude]); 45 | 46 | // store only 25 recent positions 47 | if (positionList.length > 25) { 48 | positionList.splice(-1); 49 | } 50 | 51 | // update Position object 52 | 53 | $.ajax({ 54 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c/' + $rootScope.positionObjectId, 55 | type: 'PATCH', 56 | headers: { 57 | 'Authorization': authData.token_type + ' ' + authData.access_token, 58 | 'Content-type': 'application/json' 59 | }, 60 | data: JSON.stringify({'Data__c': JSON.stringify(positionList)}), 61 | }); 62 | 63 | }); 64 | 65 | }, function err(e) { 66 | if (e.responseJSON[0].errorCode === 'INVALID_SESSION_ID') { 67 | // refresh access token 68 | $scope.input.enableTracking = false; 69 | auth.openLogin(); 70 | } else { 71 | alert(e.responseJSON[0].message); 72 | } 73 | }); 74 | 75 | } else if (positionWatchId) { 76 | // stop position watch 77 | navigator.geolocation.clearWatch(positionWatchId); 78 | } 79 | }) 80 | 81 | }); 82 | 83 | app.controller('HistoryController', function ($scope, $rootScope, $timeout, auth) { 84 | 85 | var authData = auth.get(); 86 | var intervalId = null; 87 | 88 | if ($rootScope.positionObjectId) { 89 | update(); 90 | intervalId = setInterval(update, 1000); 91 | } 92 | 93 | $scope.$on('$destroy', function () { 94 | clearInterval(intervalId); 95 | }) 96 | 97 | function update() { 98 | 99 | $.ajax({ 100 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c/' + $rootScope.positionObjectId, 101 | type: 'GET', 102 | headers: { 103 | 'Authorization': authData.token_type + ' ' + authData.access_token, 104 | 'Content-type': 'application/json' 105 | } 106 | }) 107 | .then(function ok(e) { 108 | $scope.$apply(function () { 109 | $scope.positions = JSON.parse(e.Data__c); 110 | }) 111 | }, function err() { 112 | }); 113 | } 114 | 115 | }); 116 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_type.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Typography 4 | * -------------------------------------------------- 5 | */ 6 | 7 | 8 | // Body text 9 | // ------------------------- 10 | 11 | p { 12 | margin: 0 0 ($line-height-computed / 2); 13 | } 14 | 15 | 16 | // Emphasis & misc 17 | // ------------------------- 18 | 19 | small { font-size: 85%; } 20 | cite { font-style: normal; } 21 | 22 | 23 | // Alignment 24 | // ------------------------- 25 | 26 | .text-left { text-align: left; } 27 | .text-right { text-align: right; } 28 | .text-center { text-align: center; } 29 | 30 | 31 | // Headings 32 | // ------------------------- 33 | 34 | h1, h2, h3, h4, h5, h6, 35 | .h1, .h2, .h3, .h4, .h5, .h6 { 36 | color: $base-color; 37 | font-weight: $headings-font-weight; 38 | font-family: $headings-font-family; 39 | line-height: $headings-line-height; 40 | 41 | small { 42 | font-weight: normal; 43 | line-height: 1; 44 | } 45 | } 46 | 47 | h1, .h1, 48 | h2, .h2, 49 | h3, .h3 { 50 | margin-top: $line-height-computed; 51 | margin-bottom: ($line-height-computed / 2); 52 | 53 | &:first-child { 54 | margin-top: 0; 55 | } 56 | 57 | + h1, + .h1, 58 | + h2, + .h2, 59 | + h3, + .h3 { 60 | margin-top: ($line-height-computed / 2); 61 | } 62 | } 63 | 64 | h4, .h4, 65 | h5, .h5, 66 | h6, .h6 { 67 | margin-top: ($line-height-computed / 2); 68 | margin-bottom: ($line-height-computed / 2); 69 | } 70 | 71 | h1, .h1 { font-size: floor($font-size-base * 2.60); } // ~36px 72 | h2, .h2 { font-size: floor($font-size-base * 2.15); } // ~30px 73 | h3, .h3 { font-size: ceil($font-size-base * 1.70); } // ~24px 74 | h4, .h4 { font-size: ceil($font-size-base * 1.25); } // ~18px 75 | h5, .h5 { font-size: $font-size-base; } 76 | h6, .h6 { font-size: ceil($font-size-base * 0.85); } // ~12px 77 | 78 | h1 small, .h1 small { font-size: ceil($font-size-base * 1.70); } // ~24px 79 | h2 small, .h2 small { font-size: ceil($font-size-base * 1.25); } // ~18px 80 | h3 small, .h3 small, 81 | h4 small, .h4 small { font-size: $font-size-base; } 82 | 83 | 84 | // Description Lists 85 | // ------------------------- 86 | 87 | dl { 88 | margin-bottom: $line-height-computed; 89 | } 90 | dt, 91 | dd { 92 | line-height: $line-height-base; 93 | } 94 | dt { 95 | font-weight: bold; 96 | } 97 | 98 | 99 | // Blockquotes 100 | // ------------------------- 101 | 102 | blockquote { 103 | margin: 0 0 $line-height-computed; 104 | padding: ($line-height-computed / 2) $line-height-computed; 105 | border-left: 5px solid gray; 106 | 107 | p { 108 | font-weight: 300; 109 | font-size: ($font-size-base * 1.25); 110 | line-height: 1.25; 111 | } 112 | 113 | p:last-child { 114 | margin-bottom: 0; 115 | } 116 | 117 | small { 118 | display: block; 119 | line-height: $line-height-base; 120 | &:before { 121 | content: '\2014 \00A0';// EM DASH, NBSP; 122 | } 123 | } 124 | } 125 | 126 | 127 | // Quotes 128 | // ------------------------- 129 | 130 | q:before, 131 | q:after, 132 | blockquote:before, 133 | blockquote:after { 134 | content: ""; 135 | } 136 | 137 | 138 | // Addresses 139 | // ------------------------- 140 | 141 | address { 142 | display: block; 143 | margin-bottom: $line-height-computed; 144 | font-style: normal; 145 | line-height: $line-height-base; 146 | } 147 | 148 | 149 | // Links 150 | // ------------------------- 151 | 152 | a.subdued { 153 | padding-right: 10px; 154 | color: #888; 155 | text-decoration: none; 156 | 157 | &:hover { 158 | text-decoration: none; 159 | } 160 | &:last-child { 161 | padding-right: 0; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_toggle.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Toggle 4 | * -------------------------------------------------- 5 | */ 6 | 7 | /* the overall container of the toggle */ 8 | .toggle { 9 | // set the color defaults 10 | @include toggle-style($toggle-on-default-border, $toggle-on-default-bg); 11 | 12 | position: relative; 13 | display: inline-block; 14 | margin: -$toggle-hit-area-expansion; 15 | padding: $toggle-hit-area-expansion; 16 | 17 | &.dragging { 18 | .handle { 19 | background-color: $toggle-handle-dragging-bg-color !important; 20 | } 21 | } 22 | 23 | &.toggle-light { 24 | @include toggle-style($toggle-on-light-border, $toggle-on-light-bg); 25 | } 26 | &.toggle-stable { 27 | @include toggle-style($toggle-on-stable-border, $toggle-on-stable-bg); 28 | } 29 | &.toggle-positive { 30 | @include toggle-style($toggle-on-positive-border, $toggle-on-positive-bg); 31 | } 32 | &.toggle-calm { 33 | @include toggle-style($toggle-on-calm-border, $toggle-on-calm-bg); 34 | } 35 | &.toggle-assertive { 36 | @include toggle-style($toggle-on-assertive-border, $toggle-on-assertive-bg); 37 | } 38 | &.toggle-balanced { 39 | @include toggle-style($toggle-on-balanced-border, $toggle-on-balanced-bg); 40 | } 41 | &.toggle-energized { 42 | @include toggle-style($toggle-on-energized-border, $toggle-on-energized-bg); 43 | } 44 | &.toggle-royal { 45 | @include toggle-style($toggle-on-royal-border, $toggle-on-royal-bg); 46 | } 47 | &.toggle-dark { 48 | @include toggle-style($toggle-on-dark-border, $toggle-on-dark-bg); 49 | } 50 | } 51 | 52 | /* hide the actual input checkbox */ 53 | .toggle input { 54 | display: none; 55 | } 56 | 57 | /* the track appearance when the toggle is "off" */ 58 | .toggle .track { 59 | @include transition-timing-function(ease-in-out); 60 | @include transition-duration($toggle-transition-duration); 61 | @include transition-property((background-color, border)); 62 | 63 | display: inline-block; 64 | box-sizing: border-box; 65 | width: $toggle-width; 66 | height: $toggle-height; 67 | border: solid $toggle-border-width $toggle-off-border-color; 68 | border-radius: $toggle-border-radius; 69 | background-color: $toggle-off-bg-color; 70 | content: ' '; 71 | cursor: pointer; 72 | } 73 | 74 | /* the handle (circle) thats inside the toggle's track area */ 75 | /* also the handle's appearance when it is "off" */ 76 | .toggle .handle { 77 | @include transition($toggle-transition-duration ease-in-out); 78 | position: absolute; 79 | top: $toggle-border-width + $toggle-hit-area-expansion; 80 | left: $toggle-border-width + $toggle-hit-area-expansion; 81 | display: block; 82 | width: $toggle-handle-width; 83 | height: $toggle-handle-height; 84 | border-radius: $toggle-handle-radius; 85 | background-color: $toggle-handle-off-bg-color; 86 | 87 | /* used to create a larger (but hidden) hit area to slide the handle */ 88 | &:before { 89 | position: absolute; 90 | top: -4px; 91 | left: ( ($toggle-handle-width / 2) * -1) - 8; 92 | padding: ($toggle-handle-height / 2) + 5 ($toggle-handle-width + 7); 93 | content: " "; 94 | } 95 | } 96 | 97 | /* the handle when the toggle is "on" */ 98 | .toggle input:checked + .track .handle { 99 | @include translate3d($toggle-width - $toggle-handle-width - ($toggle-border-width * 2), 0, 0); 100 | background-color: $toggle-handle-on-bg-color; 101 | } 102 | 103 | /* make sure list item content have enough padding on right to fit the toggle */ 104 | .item-toggle { 105 | padding-right: ($item-padding * 3) + $toggle-width; 106 | 107 | &.active { 108 | box-shadow: none; 109 | } 110 | } 111 | 112 | /* position the toggle to the right within a list item */ 113 | .item-toggle .toggle { 114 | position: absolute; 115 | top: $item-padding / 2; 116 | right: $item-padding; 117 | z-index: $z-index-item-toggle; 118 | } 119 | 120 | .toggle input:disabled + .track { 121 | opacity: .6; 122 | } 123 | -------------------------------------------------------------------------------- /www/lib/ionic/js/angular/angular-sanitize.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.12 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(p,h,q){'use strict';function E(a){var e=[];s(e,h.noop).chars(a);return e.join("")}function k(a){var e={};a=a.split(",");var d;for(d=0;d=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= 8 | a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| 10 | c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); 14 | //# sourceMappingURL=angular-sanitize.min.js.map 15 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_util.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Utility Classes 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .hide { 8 | display: none; 9 | } 10 | .opacity-hide { 11 | opacity: 0; 12 | } 13 | .grade-b .opacity-hide, 14 | .grade-c .opacity-hide { 15 | opacity: 1; 16 | display: none; 17 | } 18 | .show { 19 | display: block; 20 | } 21 | .opacity-show { 22 | opacity: 1; 23 | } 24 | .invisible { 25 | visibility: hidden; 26 | } 27 | 28 | .footer-hide { 29 | .bar-footer, 30 | .tabs { 31 | display: none; 32 | } 33 | .has-footer, 34 | .has-tabs { 35 | bottom: 0; 36 | } 37 | } 38 | 39 | .inline { 40 | display: inline-block; 41 | } 42 | 43 | .disable-pointer-events { 44 | pointer-events: none; 45 | } 46 | 47 | .enable-pointer-events { 48 | pointer-events: auto; 49 | } 50 | 51 | .disable-user-behavior { 52 | // used to prevent the browser from doing its native behavior. this doesnt 53 | // prevent the scrolling, but cancels the contextmenu, tap highlighting, etc 54 | 55 | @include user-select(none); 56 | @include touch-callout(none); 57 | @include tap-highlight-transparent(); 58 | 59 | -webkit-user-drag: none; 60 | 61 | -ms-touch-action: none; 62 | -ms-content-zooming: none; 63 | } 64 | 65 | .block { 66 | display: block; 67 | clear: both; 68 | &:after { 69 | display: block; 70 | visibility: hidden; 71 | clear: both; 72 | height: 0; 73 | content: "."; 74 | } 75 | } 76 | 77 | .full-image { 78 | width: 100%; 79 | } 80 | 81 | .clearfix { 82 | *zoom: 1; 83 | &:before, 84 | &:after { 85 | display: table; 86 | content: ""; 87 | // Fixes Opera/contenteditable bug: 88 | // http://nicolasgallagher.com/micro-clearfix-hack/#comment-36952 89 | line-height: 0; 90 | } 91 | &:after { 92 | clear: both; 93 | } 94 | } 95 | 96 | /** 97 | * Content Padding 98 | * -------------------------------------------------- 99 | */ 100 | 101 | .padding { 102 | padding: $content-padding; 103 | } 104 | 105 | .padding-top, 106 | .padding-vertical { 107 | padding-top: $content-padding; 108 | } 109 | 110 | .padding-right, 111 | .padding-horizontal { 112 | padding-right: $content-padding; 113 | } 114 | 115 | .padding-bottom, 116 | .padding-vertical { 117 | padding-bottom: $content-padding; 118 | } 119 | 120 | .padding-left, 121 | .padding-horizontal { 122 | padding-left: $content-padding; 123 | } 124 | 125 | 126 | /** 127 | * Rounded 128 | * -------------------------------------------------- 129 | */ 130 | 131 | .rounded { 132 | border-radius: $border-radius-base; 133 | } 134 | 135 | 136 | /** 137 | * Utility Colors 138 | * -------------------------------------------------- 139 | * Utility colors are added to help set a naming convention. You'll 140 | * notice we purposely do not use words like "red" or "blue", but 141 | * instead have colors which represent an emotion or generic theme. 142 | */ 143 | 144 | .light, a.light { 145 | color: $light; 146 | } 147 | .light-bg { 148 | background-color: $light; 149 | } 150 | .light-border { 151 | border-color: $button-light-border; 152 | } 153 | 154 | .stable, a.stable { 155 | color: $stable; 156 | } 157 | .stable-bg { 158 | background-color: $stable; 159 | } 160 | .stable-border { 161 | border-color: $button-stable-border; 162 | } 163 | 164 | .positive, a.positive { 165 | color: $positive; 166 | } 167 | .positive-bg { 168 | background-color: $positive; 169 | } 170 | .positive-border { 171 | border-color: $button-positive-border; 172 | } 173 | 174 | .calm, a.calm { 175 | color: $calm; 176 | } 177 | .calm-bg { 178 | background-color: $calm; 179 | } 180 | .calm-border { 181 | border-color: $button-calm-border; 182 | } 183 | 184 | .assertive, a.assertive { 185 | color: $assertive; 186 | } 187 | .assertive-bg { 188 | background-color: $assertive; 189 | } 190 | .assertive-border { 191 | border-color: $button-assertive-border; 192 | } 193 | 194 | .balanced, a.balanced { 195 | color: $balanced; 196 | } 197 | .balanced-bg { 198 | background-color: $balanced; 199 | } 200 | .balanced-border { 201 | border-color: $button-balanced-border; 202 | } 203 | 204 | .energized, a.energized { 205 | color: $energized; 206 | } 207 | .energized-bg { 208 | background-color: $energized; 209 | } 210 | .energized-border { 211 | border-color: $button-energized-border; 212 | } 213 | 214 | .royal, a.royal { 215 | color: $royal; 216 | } 217 | .royal-bg { 218 | background-color: $royal; 219 | } 220 | .royal-border { 221 | border-color: $button-royal-border; 222 | } 223 | 224 | .dark, a.dark { 225 | color: $dark; 226 | } 227 | .dark-bg { 228 | background-color: $dark; 229 | } 230 | .dark-border { 231 | border-color: $button-dark-border; 232 | } 233 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_tabs.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Tabs 4 | * -------------------------------------------------- 5 | * A navigation bar with any number of tab items supported. 6 | */ 7 | 8 | .tabs { 9 | @include display-flex(); 10 | @include flex-direction(horizontal); 11 | @include justify-content(center); 12 | @include translate3d(0,0,0); 13 | 14 | @include tab-style($tabs-default-bg, $tabs-default-border, $tabs-default-text); 15 | @include tab-badge-style($tabs-default-text, $tabs-default-bg); 16 | 17 | position: absolute; 18 | bottom: 0; 19 | 20 | z-index: $z-index-tabs; 21 | 22 | width: 100%; 23 | height: $tabs-height; 24 | 25 | border-style: solid; 26 | border-top-width: 1px; 27 | 28 | background-size: 0; 29 | line-height: $tabs-height; 30 | 31 | @media (min--moz-device-pixel-ratio: 1.5), 32 | (-webkit-min-device-pixel-ratio: 1.5), 33 | (min-device-pixel-ratio: 1.5), 34 | (min-resolution: 144dpi), 35 | (min-resolution: 1.5dppx) { 36 | padding-top: 2px; 37 | border-top: none !important; 38 | border-bottom: none !important; 39 | background-position: top; 40 | background-size: 100% 1px; 41 | background-repeat: no-repeat; 42 | } 43 | 44 | } 45 | /* Allow parent element of tabs to define color, or just the tab itself */ 46 | .tabs-light > .tabs, 47 | .tabs.tabs-light { 48 | @include tab-style($tabs-light-bg, $tabs-light-border, $tabs-light-text); 49 | @include tab-badge-style($tabs-light-text, $tabs-light-bg); 50 | } 51 | .tabs-stable > .tabs, 52 | .tabs.tabs-stable { 53 | @include tab-style($tabs-stable-bg, $tabs-stable-border, $tabs-stable-text); 54 | @include tab-badge-style($tabs-stable-text, $tabs-stable-bg); 55 | } 56 | .tabs-positive > .tabs, 57 | .tabs.tabs-positive { 58 | @include tab-style($tabs-positive-bg, $tabs-positive-border, $tabs-positive-text); 59 | @include tab-badge-style($tabs-positive-text, $tabs-positive-bg); 60 | } 61 | .tabs-calm > .tabs, 62 | .tabs.tabs-calm { 63 | @include tab-style($tabs-calm-bg, $tabs-calm-border, $tabs-calm-text); 64 | @include tab-badge-style($tabs-calm-text, $tabs-calm-bg); 65 | } 66 | .tabs-assertive > .tabs, 67 | .tabs.tabs-assertive { 68 | @include tab-style($tabs-assertive-bg, $tabs-assertive-border, $tabs-assertive-text); 69 | @include tab-badge-style($tabs-assertive-text, $tabs-assertive-bg); 70 | } 71 | .tabs-balanced > .tabs, 72 | .tabs.tabs-balanced { 73 | @include tab-style($tabs-balanced-bg, $tabs-balanced-border, $tabs-balanced-text); 74 | @include tab-badge-style($tabs-balanced-text, $tabs-balanced-bg); 75 | } 76 | .tabs-energized > .tabs, 77 | .tabs.tabs-energized { 78 | @include tab-style($tabs-energized-bg, $tabs-energized-border, $tabs-energized-text); 79 | @include tab-badge-style($tabs-energized-text, $tabs-energized-bg); 80 | } 81 | .tabs-royal > .tabs, 82 | .tabs.tabs-royal { 83 | @include tab-style($tabs-royal-bg, $tabs-royal-border, $tabs-royal-text); 84 | @include tab-badge-style($tabs-royal-text, $tabs-royal-bg); 85 | } 86 | .tabs-dark > .tabs, 87 | .tabs.tabs-dark { 88 | @include tab-style($tabs-dark-bg, $tabs-dark-border, $tabs-dark-text); 89 | @include tab-badge-style($tabs-dark-text, $tabs-dark-bg); 90 | } 91 | 92 | /* Allow parent element to have tabs-top */ 93 | .tabs-top > .tabs, 94 | .tabs.tabs-top { 95 | top: $bar-height; 96 | padding-top: 0; 97 | padding-bottom: 2px; 98 | background-position: bottom; 99 | } 100 | 101 | .tab-item { 102 | @include flex(1); 103 | display: block; 104 | overflow: hidden; 105 | 106 | max-width: $tab-item-max-width; 107 | height: 100%; 108 | 109 | color: inherit; 110 | text-align: center; 111 | text-decoration: none; 112 | text-overflow: ellipsis; 113 | white-space: nowrap; 114 | 115 | font-weight: 400; 116 | font-size: $tabs-text-font-size; 117 | font-family: $font-family-light-sans-serif; 118 | 119 | opacity: 0.7; 120 | 121 | &:hover { 122 | cursor: pointer; 123 | } 124 | } 125 | 126 | .tabs-item-hide, 127 | .tabs-item-hide > .tabs { 128 | display: none; 129 | } 130 | 131 | .tabs-icon-top .tab-item, 132 | .tabs-icon-bottom .tab-item { 133 | font-size: $tabs-text-font-size-side-icon; 134 | line-height: $tabs-text-font-size; 135 | } 136 | 137 | .tab-item .icon { 138 | display: block; 139 | margin: 0 auto; 140 | height: $tabs-icon-size; 141 | font-size: $tabs-icon-size; 142 | } 143 | 144 | .tabs-icon-left .tab-item, 145 | .tabs-icon-right .tab-item { 146 | font-size: $tabs-text-font-size-side-icon; 147 | 148 | .icon { 149 | display: inline-block; 150 | vertical-align: top; 151 | 152 | &:before { 153 | font-size: $tabs-icon-size - 8; 154 | line-height: $tabs-height; 155 | } 156 | } 157 | } 158 | 159 | .tabs-icon-left .tab-item .icon { 160 | padding-right: 3px; 161 | } 162 | 163 | .tabs-icon-right .tab-item .icon { 164 | padding-left: 3px; 165 | } 166 | 167 | .tabs-icon-only .icon { 168 | line-height: inherit; 169 | } 170 | 171 | .tab-item.has-badge { 172 | position: relative; 173 | } 174 | 175 | .tab-item .badge { 176 | position: absolute; 177 | padding: $tabs-badge-padding; 178 | top: 4%; 179 | right: 33%; // fallback 180 | right: calc(50% - 26px); 181 | font-size: $tabs-badge-font-size; 182 | height: auto; 183 | line-height: $tabs-badge-font-size + 4; 184 | } 185 | 186 | /* Navigational tab */ 187 | 188 | /* Active state for tab */ 189 | .tab-item.tab-item-active { 190 | opacity: 1; 191 | 192 | &.tab-item-light { 193 | color: $light; 194 | } 195 | &.tab-item-stable { 196 | color: $stable; 197 | } 198 | &.tab-item-positive { 199 | color: $positive; 200 | } 201 | &.tab-item-calm { 202 | color: $calm; 203 | } 204 | &.tab-item-assertive { 205 | color: $assertive; 206 | } 207 | &.tab-item-balanced { 208 | color: $balanced; 209 | } 210 | &.tab-item-energized { 211 | color: $energized; 212 | } 213 | &.tab-item-royal { 214 | color: $royal; 215 | } 216 | &.tab-item-dark { 217 | color: $dark; 218 | } 219 | } 220 | 221 | .item.tabs { 222 | @include display-flex(); 223 | padding: 0; 224 | 225 | .icon:before { 226 | position: relative; 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_form.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Forms 3 | * -------------------------------------------------- 4 | */ 5 | 6 | // Make all forms have space below them 7 | form { 8 | margin: 0 0 $line-height-base; 9 | } 10 | 11 | // Groups of fields with labels on top (legends) 12 | legend { 13 | display: block; 14 | margin-bottom: $line-height-base; 15 | padding: 0; 16 | width: 100%; 17 | border: $input-border-width solid $input-border; 18 | color: $dark; 19 | font-size: $font-size-base * 1.5; 20 | line-height: $line-height-base * 2; 21 | 22 | small { 23 | color: $stable; 24 | font-size: $line-height-base * .75; 25 | } 26 | } 27 | 28 | // Set font for forms 29 | label, 30 | input, 31 | button, 32 | select, 33 | textarea { 34 | @include font-shorthand($font-size-base, normal, $line-height-base); // Set size, weight, line-height here 35 | } 36 | input, 37 | button, 38 | select, 39 | textarea { 40 | font-family: $font-family-base; // And only set font-family here for those that need it (note the missing label element) 41 | } 42 | 43 | 44 | // Input List 45 | // ------------------------------- 46 | 47 | .item-input { 48 | @include display-flex(); 49 | @include align-items(center); 50 | position: relative; 51 | overflow: hidden; 52 | padding: 6px 0 5px 8px; 53 | 54 | input { 55 | @include border-radius(0); 56 | @include flex(1, 0, 220px); 57 | @include appearance(none); 58 | margin: 0; 59 | padding-right: 24px; 60 | background-color: transparent; 61 | } 62 | 63 | .button .icon { 64 | @include flex(0, 0, 24px); 65 | position: static; 66 | display: inline-block; 67 | height: auto; 68 | text-align: center; 69 | font-size: 16px; 70 | } 71 | 72 | .button-bar { 73 | @include border-radius(0); 74 | @include flex(1, 0, 220px); 75 | @include appearance(none); 76 | } 77 | 78 | .icon { 79 | min-width: 14px; 80 | } 81 | } 82 | 83 | .item-input-inset { 84 | @include display-flex(); 85 | @include align-items(center); 86 | position: relative; 87 | overflow: hidden; 88 | padding: ($item-padding / 3) * 2; 89 | } 90 | 91 | .item-input-wrapper { 92 | @include display-flex(); 93 | @include flex(1, 0); 94 | @include align-items(center); 95 | @include border-radius(4px); 96 | padding-right: 8px; 97 | padding-left: 8px; 98 | background: #eee; 99 | } 100 | 101 | .item-input-inset .item-input-wrapper input { 102 | padding-left: 4px; 103 | height: 29px; 104 | background: inherit; 105 | line-height: 18px; 106 | } 107 | 108 | .item-input-wrapper ~ .button { 109 | margin-left: ($item-padding / 3) * 2; 110 | } 111 | 112 | .input-label { 113 | @include flex(1, 0, 100px); 114 | padding: 7px 10px 7px 3px; 115 | max-width: 200px; 116 | color: $input-label-color; 117 | font-weight: bold; 118 | font-size: $font-size-base; 119 | } 120 | 121 | .placeholder-icon { 122 | color: #aaa; 123 | &:first-child { 124 | padding-right: 6px; 125 | } 126 | &:last-child { 127 | padding-left: 6px; 128 | } 129 | } 130 | 131 | .item-stacked-label { 132 | display: block; 133 | background-color: transparent; 134 | box-shadow: none; 135 | 136 | .input-label, .icon { 137 | display: inline-block; 138 | padding: 4px 0; 139 | vertical-align: middle; 140 | } 141 | } 142 | 143 | .item-stacked-label input, 144 | .item-stacked-label textarea 145 | { 146 | @include border-radius(2px); 147 | overflow: hidden; 148 | padding: 4px 8px 3px; 149 | border: none; 150 | background-color: $input-bg; 151 | } 152 | .item-stacked-label input { 153 | height: $line-height-computed + $font-size-base + 12px; 154 | } 155 | 156 | 157 | // Form Controls 158 | // ------------------------------- 159 | 160 | // Shared size and type resets 161 | select, 162 | textarea, 163 | input[type="text"], 164 | input[type="password"], 165 | input[type="datetime"], 166 | input[type="datetime-local"], 167 | input[type="date"], 168 | input[type="month"], 169 | input[type="time"], 170 | input[type="week"], 171 | input[type="number"], 172 | input[type="email"], 173 | input[type="url"], 174 | input[type="search"], 175 | input[type="tel"], 176 | input[type="color"] { 177 | display: block; 178 | padding-top: 2px; 179 | height: $line-height-computed + $font-size-base; 180 | color: $input-color; 181 | vertical-align: middle; 182 | font-size: $font-size-base; 183 | line-height: $font-size-base + 2; 184 | } 185 | 186 | input, 187 | textarea { 188 | width: 100%; 189 | } 190 | 191 | // Reset height since textareas have rows 192 | textarea { 193 | height: auto; 194 | } 195 | 196 | // Everything else 197 | textarea, 198 | input[type="text"], 199 | input[type="password"], 200 | input[type="datetime"], 201 | input[type="datetime-local"], 202 | input[type="date"], 203 | input[type="month"], 204 | input[type="time"], 205 | input[type="week"], 206 | input[type="number"], 207 | input[type="email"], 208 | input[type="url"], 209 | input[type="search"], 210 | input[type="tel"], 211 | input[type="color"] { 212 | border: 0; 213 | } 214 | 215 | // Position radios and checkboxes better 216 | input[type="radio"], 217 | input[type="checkbox"] { 218 | margin: 0; 219 | line-height: normal; 220 | } 221 | 222 | // Reset width of input images, buttons, radios, checkboxes 223 | input[type="file"], 224 | input[type="image"], 225 | input[type="submit"], 226 | input[type="reset"], 227 | input[type="button"], 228 | input[type="radio"], 229 | input[type="checkbox"] { 230 | width: auto; // Override of generic input selector 231 | } 232 | 233 | // Make multiple select elements height not fixed 234 | select[multiple], 235 | select[size] { 236 | height: auto; 237 | } 238 | 239 | // Set the height of select and file controls to match text inputs 240 | select, 241 | input[type="file"] { 242 | line-height: $input-height-base; 243 | } 244 | 245 | // Make select elements obey height by applying a border 246 | select { 247 | border: $input-border-width solid $input-border; 248 | background-color: $input-bg; // Chrome on Linux and Mobile Safari need background-color 249 | } 250 | 251 | 252 | // Placeholder 253 | // ------------------------------- 254 | input, 255 | textarea { 256 | @include placeholder(); 257 | } 258 | 259 | 260 | // DISABLED STATE 261 | // ------------------------------- 262 | 263 | // Disabled and read-only inputs 264 | input[disabled], 265 | select[disabled], 266 | textarea[disabled], 267 | input[readonly], 268 | select[readonly], 269 | textarea[readonly] { 270 | background-color: $input-bg-disabled; 271 | cursor: not-allowed; 272 | } 273 | // Explicitly reset the colors here 274 | input[type="radio"][disabled], 275 | input[type="checkbox"][disabled], 276 | input[type="radio"][readonly], 277 | input[type="checkbox"][readonly] { 278 | background-color: transparent; 279 | } 280 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_scaffolding.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Scaffolding 4 | * -------------------------------------------------- 5 | */ 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | @include box-sizing(border-box); 11 | } 12 | 13 | body, 14 | .ionic-body { 15 | @include touch-callout(none); 16 | @include font-smoothing(antialiased); 17 | @include text-size-adjust(none); 18 | @include tap-highlight-transparent(); 19 | @include user-select(none); 20 | 21 | position: fixed; 22 | top: 0; 23 | right: 0; 24 | bottom: 0; 25 | left: 0; 26 | overflow: hidden; 27 | 28 | margin: 0; 29 | padding: 0; 30 | 31 | color: $base-color; 32 | word-wrap: break-word; 33 | font-size: $font-size-base; 34 | font-family: $font-family-base; 35 | line-height: $line-height-computed; 36 | text-rendering: optimizeLegibility; 37 | -webkit-backface-visibility: hidden; 38 | -webkit-user-drag: none; 39 | } 40 | 41 | body.grade-b, 42 | body.grade-c { 43 | // disable optimizeLegibility for low end devices 44 | text-rendering: auto; 45 | } 46 | 47 | .content { 48 | // used for content areas not using the content directive 49 | position: relative; 50 | } 51 | 52 | .scroll-content { 53 | position: absolute; 54 | top: 0; 55 | right: 0; 56 | bottom: 0; 57 | left: 0; 58 | overflow: hidden; 59 | 60 | // Hide the top border if any 61 | margin-top: -1px; 62 | 63 | width: auto; 64 | height: auto; 65 | } 66 | 67 | .scroll-view { 68 | position: relative; 69 | overflow: hidden; 70 | 71 | // Hide the top border if any 72 | margin-top: -1px; 73 | height: 100%; 74 | } 75 | 76 | /** 77 | * Scroll is the scroll view component available for complex and custom 78 | * scroll view functionality. 79 | */ 80 | .scroll { 81 | @include user-select(none); 82 | @include touch-callout(none); 83 | @include text-size-adjust(none); 84 | @include transform-origin(left, top); 85 | -webkit-backface-visibility: hidden; 86 | } 87 | 88 | // Scroll bar styles 89 | .scroll-bar { 90 | position: absolute; 91 | z-index: $z-index-scroll-bar; 92 | } 93 | // hide the scroll-bar during animations 94 | .ng-animate .scroll-bar { 95 | visibility: hidden; 96 | } 97 | .scroll-bar-h { 98 | right: 2px; 99 | bottom: 3px; 100 | left: 2px; 101 | height: 3px; 102 | 103 | .scroll-bar-indicator { 104 | height: 100%; 105 | } 106 | } 107 | 108 | .scroll-bar-v { 109 | top: 2px; 110 | right: 3px; 111 | bottom: 2px; 112 | width: 3px; 113 | 114 | .scroll-bar-indicator { 115 | width: 100%; 116 | } 117 | } 118 | .scroll-bar-indicator { 119 | position: absolute; 120 | border-radius: 4px; 121 | background: rgba(0,0,0,0.3); 122 | opacity: 1; 123 | 124 | 125 | &.scroll-bar-fade-out { 126 | @include transition(opacity 0.3s linear); 127 | opacity: 0; 128 | } 129 | } 130 | .grade-b .scroll-bar-indicator, 131 | .grade-c .scroll-bar-indicator { 132 | // disable rgba background and border radius for low end devices 133 | border-radius: 0; 134 | background: #aaa; 135 | 136 | &.scroll-bar-fade-out { 137 | @include transition(none); 138 | } 139 | } 140 | 141 | 142 | // Scroll refresher (for pull to refresh) 143 | .scroll-refresher { 144 | position: absolute; 145 | top: -60px; 146 | right: 0; 147 | left: 0; 148 | overflow: hidden; 149 | margin: auto; 150 | height: 60px; 151 | 152 | .icon-refreshing { 153 | @include animation-duration(1.5s); 154 | display: none; 155 | } 156 | } 157 | 158 | .scroll-refresher-content { 159 | position: absolute; 160 | bottom: 15px; 161 | left: 0; 162 | width: 100%; 163 | color: $scroll-refresh-icon-color; 164 | text-align: center; 165 | 166 | font-size: 30px; 167 | } 168 | 169 | .ionic-refresher-content { 170 | position: absolute; 171 | bottom: 15px; 172 | left: 0; 173 | width: 100%; 174 | color: $scroll-refresh-icon-color; 175 | text-align: center; 176 | 177 | font-size: 30px; 178 | 179 | .icon-pulling { 180 | @include animation-name(refresh-spin-back); 181 | @include animation-duration(200ms); 182 | @include animation-timing-function(linear); 183 | @include animation-fill-mode(both); 184 | } 185 | } 186 | 187 | @keyframes refresh-spin { 188 | 0% { transform: rotate(0); } 189 | 100% { transform: rotate(-180deg); } 190 | } 191 | 192 | @-webkit-keyframes refresh-spin { 193 | 0% {-webkit-transform: rotate(0); } 194 | 100% {-webkit-transform: rotate(-180deg); } 195 | } 196 | 197 | @keyframes refresh-spin-back { 198 | 0% { transform: rotate(-180deg); } 199 | 100% { transform: rotate(0); } 200 | } 201 | 202 | @-webkit-keyframes refresh-spin-back { 203 | 0% {-webkit-transform: rotate(-180deg); } 204 | 100% {-webkit-transform: rotate(0); } 205 | } 206 | 207 | .scroll-refresher.active { 208 | 209 | .icon-pulling { 210 | display: block; 211 | } 212 | .icon-refreshing { 213 | display: none; 214 | } 215 | 216 | &.refreshing { 217 | .icon-pulling { 218 | display: none; 219 | } 220 | .icon-refreshing { 221 | display: block; 222 | } 223 | } 224 | 225 | .ionic-refresher-content { 226 | i.icon.icon-pulling { 227 | @include animation-name(refresh-spin); 228 | } 229 | } 230 | } 231 | 232 | // Infinite scroll 233 | ion-infinite-scroll .scroll-infinite { 234 | position: relative; 235 | overflow: hidden; 236 | margin-top: -70px; 237 | height: 60px; 238 | } 239 | 240 | .scroll-infinite-content { 241 | position: absolute; 242 | bottom: 15px; 243 | left: 0; 244 | width: 100%; 245 | color: #666666; 246 | text-align: center; 247 | font-size: 30px; } 248 | 249 | ion-infinite-scroll.active .scroll-infinite { 250 | margin-top: -30px; 251 | } 252 | 253 | .overflow-scroll { 254 | overflow-x: hidden; 255 | overflow-y: scroll; 256 | -webkit-overflow-scrolling: touch; 257 | 258 | .scroll { 259 | position: static; 260 | height: 100%; 261 | } 262 | } 263 | 264 | 265 | .overflow-scroll { 266 | overflow-x: hidden; 267 | overflow-y: scroll; 268 | -webkit-overflow-scrolling: touch; 269 | 270 | .scroll { 271 | position: static; 272 | height: 100%; 273 | } 274 | } 275 | 276 | // Pad top/bottom of content so it doesn't hide behind .bar-title and .bar-tab. 277 | // Note: For these to work, content must come after both bars in the markup 278 | .has-header { 279 | top: $bar-height; 280 | } 281 | 282 | .has-subheader { 283 | top: $bar-height * 2; 284 | } 285 | .has-tabs-top { 286 | top: $bar-height + $tabs-height; 287 | } 288 | .has-header.has-subheader.has-tabs-top { 289 | top: 2 * $bar-height + $tabs-height; 290 | } 291 | 292 | .has-footer { 293 | bottom: $bar-height; 294 | } 295 | 296 | .has-tabs, 297 | .bar-footer.has-tabs { 298 | bottom: $tabs-height; 299 | } 300 | 301 | .has-footer.has-tabs { 302 | bottom: $tabs-height + $bar-height; 303 | } 304 | 305 | // A full screen section with a solid background 306 | .pane { 307 | @include translate3d(0,0,0); 308 | z-index: $z-index-pane; 309 | } 310 | .view { 311 | z-index: $z-index-view; 312 | } 313 | .pane, 314 | .view { 315 | position: absolute; 316 | top: 0; 317 | right: 0; 318 | bottom: 0; 319 | left: 0; 320 | width: 100%; 321 | height: 100%; 322 | background-color: $base-background-color; 323 | } 324 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_button.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Buttons 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .button { 8 | // set the color defaults 9 | @include button-style($button-default-bg, $button-default-border, $button-default-active-bg, $button-default-active-border, $button-default-text); 10 | 11 | position: relative; 12 | display: inline-block; 13 | margin: 0; 14 | padding: 1px $button-padding 0 $button-padding; 15 | 16 | min-width: ($button-padding * 3) + $button-font-size; 17 | min-height: $button-height + 5px; 18 | 19 | border-width: $button-border-width; 20 | border-style: solid; 21 | border-radius: $button-border-radius; 22 | 23 | vertical-align: top; 24 | text-align: center; 25 | 26 | text-overflow: ellipsis; 27 | font-size: $button-font-size; 28 | line-height: $button-height - $button-border-width + 1px; 29 | 30 | cursor: pointer; 31 | 32 | &:after { 33 | // used to create a larger button "hit" area 34 | position: absolute; 35 | top: -6px; 36 | right: -8px; 37 | bottom: -6px; 38 | left: -8px; 39 | content: ' '; 40 | } 41 | 42 | .icon { 43 | vertical-align: top; 44 | } 45 | 46 | .icon:before, 47 | &.icon:before, 48 | &.icon-left:before, 49 | &.icon-right:before { 50 | display: inline-block; 51 | padding: 0 0 $button-border-width 0; 52 | vertical-align: inherit; 53 | font-size: $button-icon-size; 54 | line-height: $button-height - $button-border-width + 1; 55 | } 56 | &.icon-left:before { 57 | float: left; 58 | padding-right: .2em; 59 | padding-left: 0; 60 | } 61 | &.icon-right:before { 62 | float: right; 63 | padding-right: 0; 64 | padding-left: .2em; 65 | } 66 | 67 | &.button-block, &.button-full { 68 | margin-top: $button-block-margin; 69 | margin-bottom: $button-block-margin; 70 | } 71 | 72 | &.button-light { 73 | @include button-style($button-light-bg, $button-light-border, $button-light-active-bg, $button-light-active-border, $button-light-text); 74 | @include button-clear($button-light-border); 75 | @include button-outline($button-light-border); 76 | } 77 | 78 | &.button-stable { 79 | @include button-style($button-stable-bg, $button-stable-border, $button-stable-active-bg, $button-stable-active-border, $button-stable-text); 80 | @include button-clear($button-stable-border); 81 | @include button-outline($button-stable-border); 82 | } 83 | 84 | &.button-positive { 85 | @include button-style($button-positive-bg, $button-positive-border, $button-positive-active-bg, $button-positive-active-border, $button-positive-text); 86 | @include button-clear($button-positive-bg); 87 | @include button-outline($button-positive-bg); 88 | } 89 | 90 | &.button-calm { 91 | @include button-style($button-calm-bg, $button-calm-border, $button-calm-active-bg, $button-calm-active-border, $button-calm-text); 92 | @include button-clear($button-calm-bg); 93 | @include button-outline($button-calm-bg); 94 | } 95 | 96 | &.button-assertive { 97 | @include button-style($button-assertive-bg, $button-assertive-border, $button-assertive-active-bg, $button-assertive-active-border, $button-assertive-text); 98 | @include button-clear($button-assertive-bg); 99 | @include button-outline($button-assertive-bg); 100 | } 101 | 102 | &.button-balanced { 103 | @include button-style($button-balanced-bg, $button-balanced-border, $button-balanced-active-bg, $button-balanced-active-border, $button-balanced-text); 104 | @include button-clear($button-balanced-bg); 105 | @include button-outline($button-balanced-bg); 106 | } 107 | 108 | &.button-energized { 109 | @include button-style($button-energized-bg, $button-energized-border, $button-energized-active-bg, $button-energized-active-border, $button-energized-text); 110 | @include button-clear($button-energized-bg); 111 | @include button-outline($button-energized-bg); 112 | } 113 | 114 | &.button-royal { 115 | @include button-style($button-royal-bg, $button-royal-border, $button-royal-active-bg, $button-royal-active-border, $button-royal-text); 116 | @include button-clear($button-royal-bg); 117 | @include button-outline($button-royal-bg); 118 | } 119 | 120 | &.button-dark { 121 | @include button-style($button-dark-bg, $button-dark-border, $button-dark-active-bg, $button-dark-active-border, $button-dark-text); 122 | @include button-clear($button-dark-bg); 123 | @include button-outline($button-dark-bg); 124 | } 125 | } 126 | 127 | .button-small { 128 | padding: 0 $button-small-padding; 129 | min-width: $button-small-height; 130 | min-height: $button-small-height + 3; 131 | font-size: $button-small-font-size; 132 | line-height: $button-small-height - $button-border-width + 1; 133 | 134 | .icon:before, 135 | &.icon:before, 136 | &.icon-left:before, 137 | &.icon-right:before { 138 | font-size: $button-small-icon-size; 139 | line-height: $button-small-height - $button-border-width - 1; 140 | } 141 | } 142 | 143 | .button-large { 144 | padding: 0 $button-large-padding; 145 | min-width: ($button-large-padding * 3) + $button-large-font-size; 146 | min-height: $button-large-height + 5; 147 | font-size: $button-large-font-size; 148 | line-height: $button-large-height - $button-border-width; 149 | 150 | .icon:before, 151 | &.icon:before, 152 | &.icon-left:before, 153 | &.icon-right:before { 154 | padding-bottom: ($button-border-width * 2); 155 | font-size: $button-large-icon-size; 156 | line-height: $button-large-height - ($button-border-width * 2) - 1; 157 | } 158 | } 159 | 160 | .button-icon { 161 | @include transition(opacity .1s); 162 | padding: 0 6px; 163 | min-width: initial; 164 | border-color: transparent; 165 | background: none; 166 | 167 | &.button.active { 168 | border-color: transparent; 169 | background: none; 170 | box-shadow: none; 171 | opacity: 0.3; 172 | } 173 | 174 | .icon:before, 175 | &.icon:before { 176 | font-size: $button-large-icon-size; 177 | } 178 | } 179 | 180 | .button-clear { 181 | @include button-clear($button-default-border); 182 | @include transition(opacity .1s); 183 | padding: 0 $button-clear-padding; 184 | max-height: $button-height; 185 | border-color: transparent; 186 | background: none; 187 | box-shadow: none; 188 | 189 | &.active { 190 | opacity: 0.3; 191 | } 192 | } 193 | 194 | .button-outline { 195 | @include button-outline($button-default-border); 196 | @include transition(opacity .1s); 197 | background: none; 198 | box-shadow: none; 199 | } 200 | 201 | .padding > .button.button-block:first-child { 202 | margin-top: 0; 203 | } 204 | 205 | .button-block { 206 | display: block; 207 | clear: both; 208 | 209 | &:after { 210 | clear: both; 211 | } 212 | } 213 | 214 | .button-full, 215 | .button-full > .button { 216 | display: block; 217 | margin-right: 0; 218 | margin-left: 0; 219 | border-right-width: 0; 220 | border-left-width: 0; 221 | border-radius: 0; 222 | } 223 | 224 | button.button-block, 225 | button.button-full, 226 | .button-full > button.button, 227 | input.button.button-block { 228 | width: 100%; 229 | } 230 | 231 | a.button { 232 | text-decoration: none; 233 | } 234 | 235 | .button.disabled, 236 | .button[disabled] { 237 | opacity: .4; 238 | cursor: default !important; 239 | pointer-events: none; 240 | } 241 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_bar.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Bar (Headers and Footers) 4 | * -------------------------------------------------- 5 | */ 6 | 7 | .bar { 8 | @include display-flex(); 9 | @include translate3d(0,0,0); 10 | @include user-select(none); 11 | position: absolute; 12 | right: 0; 13 | left: 0; 14 | z-index: $z-index-bar; 15 | 16 | box-sizing: border-box; 17 | padding: $bar-padding-portrait; 18 | 19 | width: 100%; 20 | height: $bar-height; 21 | border-width: 0; 22 | border-style: solid; 23 | border-top: 1px solid transparent; 24 | border-bottom: 1px solid $bar-default-border; 25 | 26 | background-color: $bar-default-bg; 27 | 28 | /* border-width: 1px will actually create 2 device pixels on retina */ 29 | /* this nifty trick sets an actual 1px border on hi-res displays */ 30 | background-size: 0; 31 | @media (min--moz-device-pixel-ratio: 1.5), 32 | (-webkit-min-device-pixel-ratio: 1.5), 33 | (min-device-pixel-ratio: 1.5), 34 | (min-resolution: 144dpi), 35 | (min-resolution: 1.5dppx) { 36 | border: none; 37 | background-image: linear-gradient(0deg, $bar-default-border, $bar-default-border 50%, transparent 50%); 38 | background-position: bottom; 39 | background-size: 100% 1px; 40 | background-repeat: no-repeat; 41 | } 42 | 43 | &.bar-clear { 44 | border: none; 45 | background: none; 46 | color: #fff; 47 | 48 | .button { 49 | color: #fff; 50 | } 51 | .title { 52 | color: #fff; 53 | } 54 | } 55 | 56 | &.item-input-inset { 57 | .item-input-wrapper { 58 | margin-top: -1px; 59 | 60 | input { 61 | padding-left: 8px; 62 | height: 28px; 63 | } 64 | } 65 | } 66 | 67 | &.bar-light { 68 | @include bar-style($bar-light-bg, $bar-light-border, $bar-light-text); 69 | } 70 | &.bar-stable { 71 | @include bar-style($bar-stable-bg, $bar-stable-border, $bar-stable-text); 72 | } 73 | &.bar-positive { 74 | @include bar-style($bar-positive-bg, $bar-positive-border, $bar-positive-text); 75 | } 76 | &.bar-calm { 77 | @include bar-style($bar-calm-bg, $bar-calm-border, $bar-calm-text); 78 | } 79 | &.bar-assertive { 80 | @include bar-style($bar-assertive-bg, $bar-assertive-border, $bar-assertive-text); 81 | } 82 | &.bar-balanced { 83 | @include bar-style($bar-balanced-bg, $bar-balanced-border, $bar-balanced-text); 84 | } 85 | &.bar-energized { 86 | @include bar-style($bar-energized-bg, $bar-energized-border, $bar-energized-text); 87 | } 88 | &.bar-royal { 89 | @include bar-style($bar-royal-bg, $bar-royal-border, $bar-royal-text); 90 | } 91 | &.bar-dark { 92 | @include bar-style($bar-dark-bg, $bar-dark-border, $bar-dark-text); 93 | } 94 | 95 | // Title inside of a bar is centered 96 | .title { 97 | position: absolute; 98 | 99 | top: 0; 100 | right: 0; 101 | left: 0; 102 | z-index: $z-index-bar-title; 103 | overflow: hidden; 104 | 105 | margin: 0 10px; 106 | 107 | min-width: 30px; 108 | 109 | text-align: center; 110 | 111 | // Go into ellipsis if too small 112 | text-overflow: ellipsis; 113 | white-space: nowrap; 114 | 115 | font-size: $bar-title-font-size; 116 | 117 | line-height: $bar-height; 118 | 119 | &.title-left { 120 | text-align: left; 121 | } 122 | &.title-right { 123 | text-align: right; 124 | } 125 | } 126 | 127 | .title a { 128 | color: inherit; 129 | } 130 | 131 | .button { 132 | z-index: $z-index-bar-button; 133 | padding: 0 $button-bar-button-padding; 134 | min-width: initial; 135 | min-height: $button-bar-button-height - 1; 136 | font-size: $button-bar-button-font-size; 137 | font-weight: 400; 138 | line-height: $button-bar-button-height; 139 | 140 | &.button-icon:before, 141 | .icon:before, 142 | &.icon:before, 143 | &.icon-left:before, 144 | &.icon-right:before { 145 | padding-right: 2px; 146 | padding-left: 2px; 147 | font-size: $button-bar-button-icon-size; 148 | line-height: $button-bar-button-height; 149 | } 150 | 151 | &.button-icon { 152 | .icon:before, 153 | &:before, 154 | &.icon-left:before, 155 | &.icon-right:before { 156 | vertical-align: top; 157 | font-size: $button-large-icon-size; 158 | line-height: $button-bar-button-height; 159 | } 160 | } 161 | &.button-clear { 162 | font-size: $bar-title-font-size; 163 | font-weight: 300; 164 | padding-right: 2px; 165 | padding-left: 2px; 166 | 167 | .icon:before, 168 | &.icon:before, 169 | &.icon-left:before, 170 | &.icon-right:before { 171 | font-size: $button-large-icon-size; 172 | line-height: $button-bar-button-height; 173 | } 174 | } 175 | 176 | &.back-button.active { 177 | opacity: 1; 178 | } 179 | } 180 | 181 | .button-bar > .button, 182 | .buttons > .button { 183 | min-height: $button-bar-button-height - 1; 184 | line-height: $button-bar-button-height; 185 | } 186 | 187 | .button-bar + .button, 188 | .button + .button-bar { 189 | margin-left: 5px; 190 | } 191 | 192 | // Place the last button in a bar on the right of the bar 193 | .title + .button:last-child, 194 | > .button + .button:last-child, 195 | > .button.pull-right, 196 | .buttons.pull-right, 197 | .title + .buttons { 198 | position: absolute; 199 | top: 5px; 200 | right: 5px; 201 | bottom: 5px; 202 | } 203 | 204 | } 205 | 206 | // Default styles for buttons inside of styled bars 207 | .bar-light { 208 | .button { 209 | @include button-style($bar-light-bg, $bar-light-border, $bar-light-active-bg, $bar-light-active-border, $bar-light-text); 210 | @include button-clear($bar-light-text, $bar-title-font-size); 211 | } 212 | } 213 | .bar-stable { 214 | .button { 215 | @include button-style($bar-stable-bg, $bar-stable-border, $bar-stable-active-bg, $bar-stable-active-border, $bar-stable-text); 216 | @include button-clear($bar-stable-text, $bar-title-font-size); 217 | } 218 | } 219 | .bar-positive { 220 | .button { 221 | @include button-style($bar-positive-bg, $bar-positive-border, $bar-positive-active-bg, $bar-positive-active-border, $bar-positive-text); 222 | @include button-clear(#fff, $bar-title-font-size); 223 | } 224 | } 225 | .bar-calm { 226 | .button { 227 | @include button-style($bar-calm-bg, $bar-calm-border, $bar-calm-active-bg, $bar-calm-active-border, $bar-calm-text); 228 | @include button-clear(#fff, $bar-title-font-size); 229 | } 230 | } 231 | .bar-assertive { 232 | .button { 233 | @include button-style($bar-assertive-bg, $bar-assertive-border, $bar-assertive-active-bg, $bar-assertive-active-border, $bar-assertive-text); 234 | @include button-clear(#fff, $bar-title-font-size); 235 | } 236 | } 237 | .bar-balanced { 238 | .button { 239 | @include button-style($bar-balanced-bg, $bar-balanced-border, $bar-balanced-active-bg, $bar-balanced-active-border, $bar-balanced-text); 240 | @include button-clear(#fff, $bar-title-font-size); 241 | } 242 | } 243 | .bar-energized { 244 | .button { 245 | @include button-style($bar-energized-bg, $bar-energized-border, $bar-energized-active-bg, $bar-energized-active-border, $bar-energized-text); 246 | @include button-clear(#fff, $bar-title-font-size); 247 | } 248 | } 249 | .bar-royal { 250 | .button { 251 | @include button-style($bar-royal-bg, $bar-royal-border, $bar-royal-active-bg, $bar-royal-active-border, $bar-royal-text); 252 | @include button-clear(#fff, $bar-title-font-size); 253 | } 254 | } 255 | .bar-dark { 256 | .button { 257 | @include button-style($bar-dark-bg, $bar-dark-border, $bar-dark-active-bg, $bar-dark-active-border, $bar-dark-text); 258 | @include button-clear(#fff, $bar-title-font-size); 259 | } 260 | } 261 | 262 | // Header at top 263 | .bar-header { 264 | top: 0; 265 | border-top-width: 0; 266 | border-bottom-width: 1px; 267 | } 268 | 269 | // Footer at bottom 270 | .bar-footer { 271 | bottom: 0; 272 | border-top-width: 1px; 273 | border-bottom-width: 0; 274 | background-position: top; 275 | } 276 | 277 | // Don't render padding if the bar is just for tabs 278 | .bar-tabs { 279 | padding: 0; 280 | } 281 | 282 | .bar-subheader { 283 | top: $bar-height; 284 | display: block; 285 | } 286 | .bar-subfooter { 287 | bottom: $bar-height; 288 | display: block; 289 | } 290 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_reset.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Resets 4 | * -------------------------------------------------- 5 | * Adapted from normalize.css and some reset.css. We don't care even one 6 | * bit about old IE, so we don't need any hacks for that in here. 7 | * 8 | * There are probably other things we could remove here, as well. 9 | * 10 | * normalize.css v2.1.2 | MIT License | git.io/normalize 11 | 12 | * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) 13 | * http://cssreset.com 14 | */ 15 | 16 | html, body, div, span, applet, object, iframe, 17 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 18 | a, abbr, acronym, address, big, cite, code, 19 | del, dfn, em, img, ins, kbd, q, s, samp, 20 | small, strike, strong, sub, sup, tt, var, 21 | b, i, u, center, 22 | dl, dt, dd, ol, ul, li, 23 | fieldset, form, label, legend, 24 | table, caption, tbody, tfoot, thead, tr, th, td, 25 | article, aside, canvas, details, embed, fieldset, 26 | figure, figcaption, footer, header, hgroup, 27 | menu, nav, output, ruby, section, summary, 28 | time, mark, audio, video { 29 | margin: 0; 30 | padding: 0; 31 | border: 0; 32 | vertical-align: baseline; 33 | font: inherit; 34 | font-size: 100%; 35 | } 36 | 37 | ol, ul { 38 | list-style: none; 39 | } 40 | blockquote, q { 41 | quotes: none; 42 | } 43 | blockquote:before, blockquote:after, 44 | q:before, q:after { 45 | content: ''; 46 | content: none; 47 | } 48 | 49 | /** 50 | * Prevent modern browsers from displaying `audio` without controls. 51 | * Remove excess height in iOS 5 devices. 52 | */ 53 | 54 | audio:not([controls]) { 55 | display: none; 56 | height: 0; 57 | } 58 | 59 | /** 60 | * Hide the `template` element in IE, Safari, and Firefox < 22. 61 | */ 62 | 63 | [hidden], 64 | template { 65 | display: none; 66 | } 67 | 68 | script { 69 | display: none !important; 70 | } 71 | 72 | /* ========================================================================== 73 | Base 74 | ========================================================================== */ 75 | 76 | /** 77 | * 1. Set default font family to sans-serif. 78 | * 2. Prevent iOS text size adjust after orientation change, without disabling 79 | * user zoom. 80 | */ 81 | 82 | html { 83 | @include user-select(none); 84 | font-family: sans-serif; /* 1 */ 85 | -webkit-text-size-adjust: 100%; 86 | -ms-text-size-adjust: 100%; /* 2 */ 87 | -webkit-text-size-adjust: 100%; /* 2 */ 88 | } 89 | 90 | /** 91 | * Remove default margin. 92 | */ 93 | 94 | body { 95 | margin: 0; 96 | line-height: 1; 97 | } 98 | 99 | 100 | /** 101 | * Remove default outlines. 102 | */ 103 | a, 104 | button, 105 | :focus, 106 | a:focus, 107 | button:focus, 108 | a:active, 109 | a:hover { 110 | outline: 0; 111 | } 112 | 113 | /* * 114 | * Remove tap highlight color 115 | */ 116 | 117 | a { 118 | -webkit-user-drag: none; 119 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 120 | -webkit-tap-highlight-color: transparent; 121 | 122 | &[href]:hover { 123 | cursor: pointer; 124 | } 125 | } 126 | 127 | /* ========================================================================== 128 | Typography 129 | ========================================================================== */ 130 | 131 | 132 | /** 133 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 134 | */ 135 | 136 | b, 137 | strong { 138 | font-weight: bold; 139 | } 140 | 141 | /** 142 | * Address styling not present in Safari 5 and Chrome. 143 | */ 144 | 145 | dfn { 146 | font-style: italic; 147 | } 148 | 149 | /** 150 | * Address differences between Firefox and other browsers. 151 | */ 152 | 153 | hr { 154 | -moz-box-sizing: content-box; 155 | box-sizing: content-box; 156 | height: 0; 157 | } 158 | 159 | 160 | /** 161 | * Correct font family set oddly in Safari 5 and Chrome. 162 | */ 163 | 164 | code, 165 | kbd, 166 | pre, 167 | samp { 168 | font-size: 1em; 169 | font-family: monospace, serif; 170 | } 171 | 172 | /** 173 | * Improve readability of pre-formatted text in all browsers. 174 | */ 175 | 176 | pre { 177 | white-space: pre-wrap; 178 | } 179 | 180 | /** 181 | * Set consistent quote types. 182 | */ 183 | 184 | q { 185 | quotes: "\201C" "\201D" "\2018" "\2019"; 186 | } 187 | 188 | /** 189 | * Address inconsistent and variable font size in all browsers. 190 | */ 191 | 192 | small { 193 | font-size: 80%; 194 | } 195 | 196 | /** 197 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 198 | */ 199 | 200 | sub, 201 | sup { 202 | position: relative; 203 | vertical-align: baseline; 204 | font-size: 75%; 205 | line-height: 0; 206 | } 207 | 208 | sup { 209 | top: -0.5em; 210 | } 211 | 212 | sub { 213 | bottom: -0.25em; 214 | } 215 | 216 | /** 217 | * Define consistent border, margin, and padding. 218 | */ 219 | 220 | fieldset { 221 | margin: 0 2px; 222 | padding: 0.35em 0.625em 0.75em; 223 | border: 1px solid #c0c0c0; 224 | } 225 | 226 | /** 227 | * 1. Correct `color` not being inherited in IE 8/9. 228 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 229 | */ 230 | 231 | legend { 232 | padding: 0; /* 2 */ 233 | border: 0; /* 1 */ 234 | } 235 | 236 | /** 237 | * 1. Correct font family not being inherited in all browsers. 238 | * 2. Correct font size not being inherited in all browsers. 239 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. 240 | * 4. Remove any default :focus styles 241 | * 5. Make sure webkit font smoothing is being inherited 242 | */ 243 | 244 | button, 245 | input, 246 | select, 247 | textarea { 248 | margin: 0; /* 3 */ 249 | font-size: 100%; /* 2 */ 250 | font-family: inherit; /* 1 */ 251 | outline-offset: 0; /* 4 */ 252 | outline-style: none; /* 4 */ 253 | outline-width: 0; /* 4 */ 254 | -webkit-font-smoothing: inherit; /* 5 */ 255 | } 256 | 257 | /** 258 | * Address Firefox 4+ setting `line-height` on `input` using `importnt` in 259 | * the UA stylesheet. 260 | */ 261 | 262 | button, 263 | input { 264 | line-height: normal; 265 | } 266 | 267 | /** 268 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 269 | * All other form control elements do not inherit `text-transform` values. 270 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. 271 | * Correct `select` style inheritance in Firefox 4+ and Opera. 272 | */ 273 | 274 | button, 275 | select { 276 | text-transform: none; 277 | } 278 | 279 | /** 280 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 281 | * and `video` controls. 282 | * 2. Correct inability to style clickable `input` types in iOS. 283 | * 3. Improve usability and consistency of cursor style between image-type 284 | * `input` and others. 285 | */ 286 | 287 | button, 288 | html input[type="button"], /* 1 */ 289 | input[type="reset"], 290 | input[type="submit"] { 291 | cursor: pointer; /* 3 */ 292 | -webkit-appearance: button; /* 2 */ 293 | } 294 | 295 | /** 296 | * Re-set default cursor for disabled elements. 297 | */ 298 | 299 | button[disabled], 300 | html input[disabled] { 301 | cursor: default; 302 | } 303 | 304 | /** 305 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 306 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 307 | * (include `-moz` to future-proof). 308 | */ 309 | 310 | input[type="search"] { 311 | -webkit-box-sizing: content-box; /* 2 */ 312 | -moz-box-sizing: content-box; 313 | box-sizing: content-box; 314 | -webkit-appearance: textfield; /* 1 */ 315 | } 316 | 317 | /** 318 | * Remove inner padding and search cancel button in Safari 5 and Chrome 319 | * on OS X. 320 | */ 321 | 322 | input[type="search"]::-webkit-search-cancel-button, 323 | input[type="search"]::-webkit-search-decoration { 324 | -webkit-appearance: none; 325 | } 326 | 327 | /** 328 | * Remove inner padding and border in Firefox 4+. 329 | */ 330 | 331 | button::-moz-focus-inner, 332 | input::-moz-focus-inner { 333 | padding: 0; 334 | border: 0; 335 | } 336 | 337 | /** 338 | * 1. Remove default vertical scrollbar in IE 8/9. 339 | * 2. Improve readability and alignment in all browsers. 340 | */ 341 | 342 | textarea { 343 | overflow: auto; /* 1 */ 344 | vertical-align: top; /* 2 */ 345 | } 346 | 347 | 348 | img { 349 | -webkit-user-drag: none; 350 | } 351 | 352 | /* ========================================================================== 353 | Tables 354 | ========================================================================== */ 355 | 356 | /** 357 | * Remove most spacing between table cells. 358 | */ 359 | 360 | table { 361 | border-spacing: 0; 362 | border-collapse: collapse; 363 | } 364 | -------------------------------------------------------------------------------- /www/lib/ionic/js/angular/angular-animate.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.12 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(v,k,t){'use strict';k.module("ngAnimate",["ng"]).factory("$$animateReflow",["$window","$timeout",function(k,B){var d=k.requestAnimationFrame||k.webkitRequestAnimationFrame||function(d){return B(d,10,!1)},q=k.cancelAnimationFrame||k.webkitCancelAnimationFrame||function(d){return B.cancel(d)};return function(p){var k=d(p);return function(){q(k)}}}]).config(["$provide","$animateProvider",function(R,B){function d(d){for(var k=0;k=u&&a>=p&&h()}var f=b.data(n),g=d(b);if(-1!=g.className.indexOf(a)&&f){var l=f.timings,m=f.stagger,p=f.maxDuration,r=f.activeClassName,u=Math.max(l.transitionDelay, 19 | l.animationDelay)*x,w=Date.now(),v=T+" "+S,t=f.itemIndex,q="",s=[];if(0 Apps and create new Connected App. 24 | - Name it "SF Sample 1", enter your email and check "Enable OAuth Settings" 25 | - Enter `sfsampleapp://oauth-callback` as your Callback URL. 26 | - Add "Full access" to Selected OAuth Scopes 27 | - Save Connected App 28 | 29 | ![image](1.png) 30 | 31 | You may heve noticed we're using custom URL scheme for the callback. Our app is registered in the system as the one that opens this type of URLs so we get a callback when user is done with the login process on the Salesforce web site. 32 | 33 | We're going to use a custom object for storing location data in the Salesforce cloud. So we need to create one: 34 | 35 | - Select _Create > Objects_ in the side menu 36 | - Click "New Custom Object" button 37 | - Enter "Position" as object label, "Positions" as plural label. "Position__c" will be automatically assigned as an API name for our object. We'll use this name for call to REST API. 38 | - Leave other setting to default and hit Save 39 | 40 | Now we need to install Ionic CLI tools. Since Ionic is built on top of Apache Cordova, we need to install it too. Assuming you already have nodejs and npm on your system ([here](http://howtonode.org/how-to-install-nodejs) is an instruction how to istall them if you don't), run the following commands in your terminal: 41 | 42 | - Install Cordova and Ionic CLI: `npm install -g cordova ionic` 43 | - Create a new tabbed app: `ionic start "SF Sample" tabs` 44 | - Enter the created app directory: `cd SF\ Sample` 45 | 46 | Go to [https://github.com/myurasov/Salesforce-REST-API-Ionic-framework-app-sample](https://github.com/myurasov/Salesforce-REST-API-Ionic-framework-app-sample) and copy all files from the repository to the current folder. 47 | 48 | App uses few of Cordova plugins: 49 | 50 | - __LaunchMyApp__ for custom url scheme handling 51 | - __org.apache.cordova.inappbrowser__ for opening OAuth URL in external browser 52 | - __cordova-plugin-geolocation__ for location detection 53 | 54 | Install them by executing the following commands: 55 | 56 | cordova plugin add https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git --variable URL_SCHEME=sfsampleapp 57 | cordova plugin add org.apache.cordova.inappbrowser 58 | cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git 59 | 60 | Edit __www/js/app.js__ and replace `---your-app-client-id---` with your Salesforce Connected App Client Id (can be seen in your Force.com developer account under _Create > Apps > SF Sample 1 > Manage_). 61 | 62 | At this point you should be able to launch your app. Run the following commands to open app in the iOS emulator (iOS SDK should be installed to be able to do it): 63 | 64 | ionic platform add ios 65 | ionic build ios 66 | ionic emulate ios 67 | 68 | You should see app loading and immediately opening Salesforce login page. After entering your login credentials and pressing "Log in to Salesforce" app is automatically opened ready to be used: 69 | ![image](2_3.png) 70 | 71 | Let's dig into the code to see what's actually happening here. 72 | 73 | First of all let's take a loot at __www/js/services.js__: 74 | 75 | ```js 76 | // auth service 77 | app.factory('auth', function ($window, salesforce_client_id) { 78 | 79 | return { 80 | get: function () { 81 | var data = $window.localStorage.auth; 82 | console.log('auth.get', data); 83 | return data ? JSON.parse(data) : false; 84 | }, 85 | 86 | set: function (data) { 87 | data = JSON.stringify(data); 88 | console.log('auth.set', data); 89 | $window.localStorage.auth = data; 90 | }, 91 | 92 | erase: function () { 93 | delete $window.localStorage.auth; 94 | }, 95 | 96 | // open OAuth page in external browser 97 | openLogin: function () { 98 | $window.open( 99 | 'https://login.salesforce.com/services/oauth2/authorize' + 100 | '?response_type=token&display=touch' + 101 | '&redirect_uri=sfsampleapp://oauth-callback' + 102 | '&client_id=' + salesforce_client_id, 103 | '_system', 104 | 'location=yes' 105 | ) 106 | } 107 | } 108 | }); 109 | ``` 110 | 111 | We see the __auth__ service defined. It has methods to read/store/delete login information and `openLogin()` method which opens Salesforce login dialog optimized for smartphones. 112 | 113 | Now knowing about what __auth__ service is we can understand the following piece of code in __www/js/app.js__: 114 | 115 | ```js 116 | ... 117 | // check auth data 118 | .run(function ($ionicPlatform, auth) { 119 | $ionicPlatform.ready(function () { 120 | if (false === auth.get()) { 121 | auth.openLogin(); 122 | } 123 | }) 124 | }) 125 | ... 126 | 127 | ``` 128 | 129 | It basically checks whether we have an auth token and if not – opens Salesforce login dialog. When user is done with login browser is redirected to `redirect_uri` parameter passed initially to Salesforce OAuth server. In our case it is `sfsampleapp://oauth-callback` – custom url scheme that our app is registered to handle. When app is invoked with this custom url scheme the global `handleOpenURL()` function is executed: 130 | 131 | ```js 132 | // handle custom url scheme 133 | function handleOpenURL(url) { 134 | 135 | var path = url.match('://(.*?)[\\?#]')[1]; 136 | 137 | if (path == 'oauth-callback') { 138 | 139 | // get hash part 140 | var query = url.substr(url.indexOf("#") + 1); 141 | 142 | var data = {}; 143 | 144 | // split into parts 145 | var parts = query.split('&'); 146 | 147 | // read names and values 148 | for (var i = 0; i < parts.length; i++) { 149 | var name = parts[i].substr(0, parts[i].indexOf('=')); 150 | var val = parts[i].substr(parts[i].indexOf('=') + 1); 151 | val = decodeURIComponent(val); 152 | data[name] = val; 153 | } 154 | 155 | // save auth using LayoutController 156 | 157 | var $scope = angular.element(document.body).scope(); 158 | 159 | $scope.$apply(function () { 160 | $scope.onAuth(data); 161 | }); 162 | } 163 | } 164 | ``` 165 | 166 | The actual URL received by this function looks like: 167 | 168 | ``` 169 | sfsampleapp://oauth-callback 170 | #access_token=TOKEN 171 | &instance_url=https%3A%2F%2Fna15.salesforce.com 172 | &id=https%3A%2F%2Flogin.salesforce.com%2Fid%2F00Di0000000i7UjEAI%2F005i0000002Cy97AAC 173 | &issued_at=1398573122814&signature=NDlJ9Gnz1of90yb1%2BvIgwPtl%2FQqEU31bJZ392LZeWf3D 174 | &scope=full 175 | &token_type=Bearer 176 | ``` 177 | 178 | Here are meaning of some passed params: 179 | 180 | - __access_token__ - temporary token that serves for authorizing access to Salesforce APIs 181 | - __instance_url__ - API endpoint that should be used by our application 182 | - __issued_at__ - Unix timestamp of the token creation date 183 | 184 | Authentication params are parsed into JavaScript object and then using `$scope.$apply()` and __LoginController__ passed to __auth__ service to be saved. 185 | 186 | Now when we have access token the rest is done with CRUD operations on a _Position_ resource in __www/js/controlles.js__. 187 | 188 | Creation of the new _Position_ object with __POST__ method on collection: 189 | 190 | ```js 191 | $.ajax({ 192 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c', 193 | type: 'POST', 194 | headers: { 195 | 'Authorization': authData.token_type + ' ' + authData.access_token, 196 | 'Content-type': 'application/json' 197 | }, 198 | data: JSON.stringify({'Data__c': ''}), 199 | }) 200 | ``` 201 | 202 | Update with __PATCH__ method on resource: 203 | 204 | ```js 205 | $.ajax({ 206 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c/' + $rootScope.positionObjectId, 207 | type: 'PATCH', 208 | headers: { 209 | 'Authorization': authData.token_type + ' ' + authData.access_token, 210 | 'Content-type': 'application/json' 211 | }, 212 | data: JSON.stringify({'Data__c': JSON.stringify(positionList)}), 213 | }); 214 | ``` 215 | 216 | And finally we use __GET__ method to retrieve stored positions in __HistroryController__: 217 | 218 | 219 | ```js 220 | $.ajax({ 221 | url: authData.instance_url + '/services/data/v29.0/sobjects/Position__c/' + $rootScope.positionObjectId, 222 | type: 'GET', 223 | headers: { 224 | 'Authorization': authData.token_type + ' ' + authData.access_token, 225 | 'Content-type': 'application/json' 226 | } 227 | }) 228 | ``` 229 | 230 | ![image](4.png) 231 | 232 | ## Conclusion 233 | 234 | We have created an app utilizing Salesforce in a flexible way without using any SDKs or libraries, but using only open standards - OAuth protocol and RESTful APIs. The same approach can be easily ported to virtually any environment making it attractive in modern multi-platform environment. 235 | 236 | ## About the Author 237 | 238 | I am a full-stack mobile/web/connected devices developer specializing in leading projects from the idea to the full implementation. Feel free to contact me at for any comments and questions or visit my: 239 | 240 | - [LinkedIn](https://www.linkedin.com/profile/view?id=173007295) 241 | - [GitHub](https://github.com/myurasov) 242 | 243 | Thank you for reading! 244 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_animations.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Animations 3 | * -------------------------------------------------- 4 | * The animations in this file are "simple" - not too complex 5 | * and pretty easy on performance. They can be overidden 6 | * and enhanced easily. 7 | */ 8 | 9 | $transition-duration: 250ms; 10 | $slide-in-up-function: cubic-bezier(.1, .7, .1, 1); 11 | 12 | 13 | /** 14 | * Keyframes 15 | * -------------------------------------------------- 16 | */ 17 | 18 | // Slide In From The Bottom To The Top 19 | // ------------------------------- 20 | 21 | @-webkit-keyframes slideInUp { 22 | 0% { -webkit-transform: translate3d(0, 100%, 0); } 23 | 100% { -webkit-transform: translate3d(0, 0, 0); } 24 | } 25 | @-moz-keyframes slideInUp { 26 | 0% { -moz-transform: translate3d(0, 100%, 0); } 27 | 100% { -moz-transform: translate3d(0, 0, 0); } 28 | } 29 | @keyframes slideInUp { 30 | 0% { transform: translate3d(0, 100%, 0); } 31 | 100% { transform: translate3d(0, 0, 0); } 32 | } 33 | 34 | 35 | // Slide Out From The Top To Bottom 36 | // ------------------------------- 37 | 38 | @-webkit-keyframes slideOutUp { 39 | 0% { -webkit-transform: translate3d(0, 0, 0); } 40 | 100% { -webkit-transform: translate3d(0, 100%, 0); } 41 | } 42 | @-moz-keyframes slideOutUp { 43 | 0% { -moz-transform: translate3d(0, 0, 0); } 44 | 100% { -moz-transform: translate3d(0, 100%, 0); } 45 | } 46 | @keyframes slideOutUp { 47 | 0% { transform: translate3d(0, 0, 0); } 48 | 100% { transform: translate3d(0, 100%, 0); } 49 | } 50 | 51 | 52 | // Slide In From Left 53 | // ------------------------------- 54 | 55 | @-webkit-keyframes slideInFromLeft { 56 | from { -webkit-transform: translate3d(-100%, 0, 0); } 57 | to { -webkit-transform: translate3d(0, 0, 0); } 58 | } 59 | @-moz-keyframes slideInFromLeft { 60 | from { -moz-transform: translateX(-100%); } 61 | to { -moz-transform: translateX(0); } 62 | } 63 | @keyframes slideInFromLeft { 64 | from { transform: translateX(-100%); } 65 | to { transform: translateX(0); } 66 | } 67 | 68 | 69 | // Slide In From Right 70 | // ------------------------------- 71 | 72 | @-webkit-keyframes slideInFromRight { 73 | from { -webkit-transform: translate3d(100%, 0, 0); } 74 | to { -webkit-transform: translate3d(0, 0, 0); } 75 | } 76 | @-moz-keyframes slideInFromRight { 77 | from { -moz-transform: translateX(100%); } 78 | to { -moz-transform: translateX(0); } 79 | } 80 | @keyframes slideInFromRight { 81 | from { transform: translateX(100%); } 82 | to { transform: translateX(0); } 83 | } 84 | 85 | 86 | // Slide Out To Left 87 | // ------------------------------- 88 | 89 | @-webkit-keyframes slideOutToLeft { 90 | from { -webkit-transform: translate3d(0, 0, 0); } 91 | to { -webkit-transform: translate3d(-100%, 0, 0); } 92 | } 93 | @-moz-keyframes slideOutToLeft { 94 | from { -moz-transform: translateX(0); } 95 | to { -moz-transform: translateX(-100%); } 96 | } 97 | @keyframes slideOutToLeft { 98 | from { transform: translateX(0); } 99 | to { transform: translateX(-100%); } 100 | } 101 | 102 | 103 | // Slide Out To Right 104 | // ------------------------------- 105 | 106 | @-webkit-keyframes slideOutToRight { 107 | from { -webkit-transform: translate3d(0, 0, 0); } 108 | to { -webkit-transform: translate3d(100%, 0, 0); } 109 | } 110 | @-moz-keyframes slideOutToRight { 111 | from { -moz-transform: translateX(0); } 112 | to { -moz-transform: translateX(100%); } 113 | } 114 | @keyframes slideOutToRight { 115 | from { transform: translateX(0); } 116 | to { transform: translateX(100%); } 117 | } 118 | 119 | 120 | // Fade Out 121 | // ------------------------------- 122 | 123 | @-webkit-keyframes fadeOut { 124 | from { opacity: 1; } 125 | to { opacity: 0; } 126 | } 127 | @-moz-keyframes fadeOut { 128 | from { opacity: 1; } 129 | to { opacity: 0; } 130 | } 131 | @keyframes fadeOut { 132 | from { opacity: 1; } 133 | to { opacity: 0; } 134 | } 135 | 136 | 137 | // Fade In 138 | // ------------------------------- 139 | 140 | @-webkit-keyframes fadeIn { 141 | from { opacity: 0; } 142 | to { opacity: 1; } 143 | } 144 | @-moz-keyframes fadeIn { 145 | from { opacity: 0; } 146 | to { opacity: 1; } 147 | } 148 | @keyframes fadeIn { 149 | from { opacity: 0; } 150 | to { opacity: 1; } 151 | } 152 | 153 | 154 | // Fade Half In 155 | // ------------------------------- 156 | 157 | @-webkit-keyframes fadeInHalf { 158 | from { background-color: rgba(0,0,0,0); } 159 | to { background-color: rgba(0,0,0,0.5); } 160 | } 161 | @-moz-keyframes fadeInHalf { 162 | from { background-color: rgba(0,0,0,0); } 163 | to { background-color: rgba(0,0,0,0.5); } 164 | } 165 | @keyframes fadeInHalf { 166 | from { background-color: rgba(0,0,0,0); } 167 | to { background-color: rgba(0,0,0,0.5); } 168 | } 169 | 170 | 171 | // Fade Half Out 172 | // ------------------------------- 173 | 174 | @-webkit-keyframes fadeOutHalf { 175 | from { background-color: rgba(0,0,0,0.5); } 176 | to { background-color: rgba(0,0,0,0); } 177 | } 178 | @-moz-keyframes fadeOutHalf { 179 | from { background-color: rgba(0,0,0,0.5); } 180 | to { background-color: rgba(0,0,0,0); } 181 | } 182 | @keyframes fadeOutHalf { 183 | from { background-color: rgba(0,0,0,0.5); } 184 | to { background-color: rgba(0,0,0,0); } 185 | } 186 | 187 | // Scale Out 188 | // Scale from hero (1 in this case) to zero 189 | // ------------------------------- 190 | 191 | @-webkit-keyframes scaleOut { 192 | from { -webkit-transform: scale(1); opacity: 1; } 193 | to { -webkit-transform: scale(0.8); opacity: 0; } 194 | } 195 | @-moz-keyframes scaleOut { 196 | from { -moz-transform: scale(1); opacity: 1; } 197 | to { -moz-transform: scale(0.8); opacity: 0; } 198 | } 199 | @keyframes scaleOut { 200 | from { transform: scale(1); opacity: 1; } 201 | to { transform: scale(0.8); opacity: 0; } 202 | } 203 | 204 | // Scale In 205 | // Scale from 0 to hero (1 in this case) 206 | // ------------------------------- 207 | 208 | @-webkit-keyframes scaleIn { 209 | from { -webkit-transform: scale(0); } 210 | to { -webkit-transform: scale(1); } 211 | } 212 | @-moz-keyframes scaleIn { 213 | from { -moz-transform: scale(0); } 214 | to { -moz-transform: scale(1); } 215 | } 216 | @keyframes scaleIn { 217 | from { transform: scale(0); } 218 | to { transform: scale(1); } 219 | } 220 | 221 | // Super Scale In 222 | // Scale from super (1.x) to duper (1 in this case) 223 | // ------------------------------- 224 | 225 | @-webkit-keyframes superScaleIn { 226 | from { -webkit-transform: scale(1.2); opacity: 0; } 227 | to { -webkit-transform: scale(1); opacity: 1 } 228 | } 229 | @-moz-keyframes superScaleIn { 230 | from { -moz-transform: scale(1.2); opacity: 0; } 231 | to { -moz-transform: scale(1); opacity: 1; } 232 | } 233 | @keyframes superScaleIn { 234 | from { transform: scale(1.2); opacity: 0; } 235 | to { transform: scale(1); opacity: 1; } 236 | } 237 | 238 | // Spin 239 | // ------------------------------- 240 | 241 | @-webkit-keyframes spin { 242 | 100% { -webkit-transform: rotate(360deg); } 243 | } 244 | @-moz-keyframes spin { 245 | 100% { -moz-transform: rotate(360deg); } 246 | } 247 | @keyframes spin { 248 | 100% { transform: rotate(360deg); } 249 | } 250 | 251 | .no-animation { 252 | > .ng-enter, &.ng-enter, > .ng-leave, &.ng-leave { 253 | @include transition(none); 254 | } 255 | } 256 | .noop-animation { 257 | > .ng-enter, &.ng-enter, > .ng-leave, &.ng-leave { 258 | @include transition(all cubic-bezier(0.250, 0.460, 0.450, 0.940) $transition-duration); 259 | position: absolute; 260 | top: 0; 261 | right: 0; 262 | bottom: 0; 263 | left: 0; 264 | } 265 | } 266 | 267 | 268 | // required for Android 269 | .ng-animate .pane { 270 | position: absolute; 271 | } 272 | 273 | 274 | /** 275 | * Slide Left-Right, and Right-Left, each with the reserve 276 | * -------------------------------------------------- 277 | * NEW content slides IN from the RIGHT, OLD slides OUT to the LEFT 278 | * Reverse: NEW content slides IN from the LEFT, OLD slides OUT to the RIGHT 279 | */ 280 | 281 | .slide-left-right, 282 | .slide-right-left.reverse { 283 | > .ng-enter, &.ng-enter, 284 | > .ng-leave, &.ng-leave { 285 | @include transition(all ease-in-out $transition-duration); 286 | position: absolute; 287 | top: 0; 288 | right: 0; 289 | bottom: 0; 290 | left: 0; 291 | } 292 | > .ng-enter, &.ng-enter { 293 | /* NEW content placed far RIGHT BEFORE it slides IN from the RIGHT */ 294 | @include translate3d(100%, 0, 0); 295 | } 296 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 297 | /* NEW content ACTIVELY sliding IN from the RIGHT */ 298 | @include translate3d(0, 0, 0); 299 | } 300 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 301 | /* OLD content ACTIVELY sliding OUT to the LEFT */ 302 | @include translate3d(-100%, 0, 0); 303 | } 304 | } 305 | 306 | .slide-left-right.reverse, 307 | .slide-right-left { 308 | > .ng-enter, &.ng-enter, > .ng-leave, &.ng-leave { 309 | @include transition(all ease-in-out $transition-duration); 310 | position: absolute; 311 | top: 0; 312 | right: 0; 313 | bottom: 0; 314 | left: 0; 315 | } 316 | > .ng-enter, &.ng-enter { 317 | /* NEW content placed far LEFT BEFORE it slides IN from the LEFT */ 318 | @include translate3d(-100%, 0, 0); 319 | } 320 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 321 | /* NEW content ACTIVELY sliding IN from the LEFT */ 322 | @include translate3d(0, 0, 0); 323 | } 324 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 325 | /* OLD content ACTIVELY sliding OUT to the RIGHT */ 326 | @include translate3d(100%, 0, 0); 327 | } 328 | } 329 | 330 | 331 | /** 332 | * iOS7 style slide left to right 333 | * -------------------------------------------------- 334 | */ 335 | $ios7-timing-function: ease-in-out; 336 | $ios7-transition-duration: 250ms; 337 | 338 | .slide-left-right-ios7, 339 | .slide-right-left-ios7.reverse { 340 | > .ng-enter, &.ng-enter, 341 | > .ng-leave, &.ng-leave { 342 | @include transition(all $ios7-timing-function $ios7-transition-duration); 343 | position: absolute; 344 | top: 0; 345 | right: -1px; 346 | bottom: 0; 347 | left: -1px; 348 | width: auto; 349 | border-right: 1px solid #ddd; 350 | border-left: 1px solid #ddd; 351 | } 352 | > .ng-enter, &.ng-enter { 353 | /* NEW content placed far RIGHT BEFORE it slides IN from the RIGHT */ 354 | @include translate3d(100%, 0, 0); 355 | } 356 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 357 | /* NEW content ACTIVELY sliding IN from the RIGHT */ 358 | @include translate3d(0, 0, 0); 359 | } 360 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 361 | /* OLD content ACTIVELY sliding OUT to the LEFT */ 362 | @include translate3d(-15%, 0, 0); 363 | } 364 | } 365 | .slide-left-right-ios7.reverse, 366 | .slide-right-left-ios7 { 367 | > .ng-enter, &.ng-enter, > .ng-leave, &.ng-leave { 368 | @include transition(all $ios7-timing-function $ios7-transition-duration); 369 | position: absolute; 370 | top: 0; 371 | right: -1px; 372 | bottom: 0; 373 | left: -1px; 374 | width: auto; 375 | border-right: 1px solid #ddd; 376 | border-left: 1px solid #ddd; 377 | } 378 | > .ng-enter, &.ng-enter { 379 | /* NEW content placed far LEFT BEFORE it slides IN from the LEFT */ 380 | @include translate3d(-100%, 0, 0); 381 | } 382 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 383 | /* NEW content ACTIVELY sliding IN from the LEFT */ 384 | @include translate3d(0, 0, 0); 385 | } 386 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 387 | /* OLD content ACTIVELY sliding OUT to the RIGHT */ 388 | @include translate3d(15%, 0, 0); 389 | } 390 | } 391 | 392 | 393 | 394 | .slide-in-left { 395 | @include translate3d(0%,0,0); 396 | &.ng-enter, > .ng-enter { 397 | @include animation-name(slideInFromLeft); 398 | @include animation-duration($transition-duration); 399 | @include animation-timing-function(ease-in-out); 400 | @include animation-fill-mode(both); 401 | } 402 | &.ng-leave, > .ng-leave { 403 | @include animation-name(slideOutToLeft); 404 | @include animation-duration($transition-duration); 405 | @include animation-timing-function(ease-in-out); 406 | @include animation-fill-mode(both); 407 | } 408 | } 409 | 410 | 411 | .slide-in-left-add { 412 | @include translate3d(100%,0,0); 413 | @include animation-duration($transition-duration); 414 | @include animation-timing-function(ease-in-out); 415 | @include animation-fill-mode(both); 416 | } 417 | .slide-in-left-add-active { 418 | @include animation-name(slideInFromLeft); 419 | } 420 | 421 | .slide-out-left { 422 | @include translate3d(-100%,0,0); 423 | &.ng-enter, > .ng-enter { 424 | @include animation-name(slideOutToLeft); 425 | @include animation-duration($transition-duration); 426 | @include animation-timing-function(ease-in-out); 427 | @include animation-fill-mode(both); 428 | } 429 | &.ng-leave, > .ng-leave { 430 | @include animation-name(slideOutToLeft); 431 | @include animation-duration($transition-duration); 432 | @include animation-timing-function(ease-in-out); 433 | @include animation-fill-mode(both); 434 | } 435 | } 436 | 437 | .slide-out-left { 438 | } 439 | 440 | .slide-out-left-add { 441 | @include translate3d(0,0,0); 442 | @include animation-duration($transition-duration); 443 | @include animation-timing-function(ease-in-out); 444 | @include animation-fill-mode(both); 445 | } 446 | .slide-out-left-add-active { 447 | @include animation-name(slideOutToLeft); 448 | } 449 | 450 | .slide-in-right { 451 | @include translate3d(0%,0,0); 452 | &.ng-enter, > .ng-enter { 453 | @include animation-name(slideInFromRight); 454 | @include animation-duration($transition-duration); 455 | @include animation-timing-function(ease-in-out); 456 | @include animation-fill-mode(both); 457 | } 458 | &.ng-leave, > .ng-leave { 459 | @include animation-name(slideInFromRight); 460 | @include animation-duration($transition-duration); 461 | @include animation-timing-function(ease-in-out); 462 | @include animation-fill-mode(both); 463 | } 464 | } 465 | 466 | .slide-in-right-add { 467 | @include translate3d(-100%,0,0); 468 | @include animation-duration($transition-duration); 469 | @include animation-timing-function(ease-in-out); 470 | @include animation-fill-mode(both); 471 | } 472 | .slide-in-right-add-active { 473 | @include animation-name(slideInFromRight); 474 | } 475 | 476 | .slide-out-right { 477 | @include translate3d(100%,0,0); 478 | &.ng-enter, > .ng-enter { 479 | @include animation-name(slideOutToRight); 480 | @include animation-duration($transition-duration); 481 | @include animation-timing-function(ease-in-out); 482 | @include animation-fill-mode(both); 483 | } 484 | &.ng-leave, > .ng-leave { 485 | @include animation-name(slideOutToRight); 486 | @include animation-duration($transition-duration); 487 | @include animation-timing-function(ease-in-out); 488 | @include animation-fill-mode(both); 489 | } 490 | } 491 | 492 | .slide-out-right-add { 493 | @include translate3d(0,0,0); 494 | @include animation-duration($transition-duration); 495 | @include animation-timing-function(ease-in-out); 496 | @include animation-fill-mode(both); 497 | } 498 | .slide-out-right-add-active { 499 | @include animation-name(slideOutToRight); 500 | } 501 | 502 | 503 | /** 504 | * Slide up from the bottom, used for modals 505 | * -------------------------------------------------- 506 | */ 507 | 508 | .slide-in-up { 509 | @include translate3d(0, 100%, 0); 510 | } 511 | .slide-in-up.ng-enter, 512 | .slide-in-up > .ng-enter { 513 | @include transition(all $slide-in-up-function 400ms); 514 | } 515 | .slide-in-up.ng-enter-active, 516 | .slide-in-up > .ng-enter-active { 517 | @include translate3d(0, 0, 0); 518 | } 519 | 520 | .slide-in-up.ng-leave, 521 | .slide-in-up > .ng-leave { 522 | @include transition(all ease-in-out 250ms); 523 | } 524 | 525 | 526 | .fade-in { 527 | @include animation(fadeOut 0.3s); 528 | &.active { 529 | @include animation(fadeIn 0.3s); 530 | } 531 | } 532 | 533 | .fade-in-not-out { 534 | &.ng-enter, .ng-enter { 535 | @include animation(fadeIn 0.3s); 536 | position: relative; 537 | } 538 | &.ng-leave, .ng-leave { 539 | display: none; 540 | } 541 | } 542 | 543 | 544 | /** 545 | * Some component specific animations 546 | */ 547 | $nav-title-slide-ios7-delay: 250ms; 548 | .nav-title-slide-ios7 { 549 | > .ng-enter, &.ng-enter, 550 | > .ng-leave, &.ng-leave { 551 | @include transition(all $nav-title-slide-ios7-delay); 552 | @include transition-timing-function($ios7-timing-function); 553 | opacity: 1; 554 | } 555 | > .ng-enter, &.ng-enter { 556 | @include translate3d(30%, 0, 0); 557 | opacity: 0; 558 | } 559 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 560 | @include translate3d(0, 0, 0); 561 | opacity: 1; 562 | } 563 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 564 | @include translate3d(-30%, 0, 0); 565 | opacity: 0; 566 | } 567 | 568 | &.reverse { 569 | > .ng-enter, &.ng-enter, 570 | > .ng-leave, &.ng-leave { 571 | @include transition(all ease-in-out $transition-duration); 572 | opacity: 1; 573 | } 574 | > .ng-enter, &.ng-enter { 575 | @include translate3d(-30%, 0, 0); 576 | opacity: 0; 577 | } 578 | > .ng-enter.ng-enter-active, &.ng-enter.ng-enter-active { 579 | @include translate3d(0, 0, 0); 580 | opacity: 1; 581 | } 582 | > .ng-leave.ng-leave-active, &.ng-leave.ng-leave-active { 583 | @include translate3d(30%, 0, 0); 584 | opacity: 0; 585 | } 586 | } 587 | } 588 | -------------------------------------------------------------------------------- /www/lib/ionic/js/angular-ui/angular-ui-router.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * State-based routing for AngularJS 3 | * @version v0.2.7 4 | * @link http://angular-ui.github.com/ 5 | * @license MIT License, http://www.opensource.org/licenses/MIT 6 | */ 7 | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return E(new(E(function(){},{prototype:a})),b)}function e(a){return D(arguments,function(b){b!==a&&D(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path)if(""!==a.path[d]){if(!b.path[d])break;c.push(a.path[d])}return c}function g(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return E({},i,b)}function i(a,b){var c={};return D(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(o[c]=d,A(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);D(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return B(a)&&a.then&&a.$$promises}if(!B(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return D(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!y(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;D(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!B(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=E({},d),s=1+m.length/3,t=!1;if(y(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(E(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return y(a.template)?this.fromString(a.template,b):y(a.templateUrl)?this.fromUrl(a.templateUrl,b):y(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return z(a)?a(b):a},this.fromUrl=function(c,d){return z(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),D(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return B(a)&&z(a.exec)&&z(a.format)&&z(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return y(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!z(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(A(a)){var b=a;a=function(){return b}}else if(!z(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=A(f);if(A(e)&&(e=a.compile(e)),!h&&!z(f)&&!C(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),E(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:A(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),E(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(A(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=A(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=u[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){v[a]||(v[a]=[]),v[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!A(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(u.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):A(b.parent)?b.parent:"";if(e&&!u[e])return m(e,b.self);for(var f in x)z(x[f])&&(b[f]=x[f](b,x.$delegates[f]));if(u[c]=b,!b[w]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){t.$current.navigable==b&&j(a,c)||t.transitionTo(b,a,{location:!1})}]),v[c])for(var g=0;g=I;d--)g=u[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=I;d").html(a).contents();return r.enter(d,c),d}},"false":{remove:function(a){a.html("")},restore:function(a,b){b.append(a)},populate:function(a,b){return b.html(a),b.contents()}}}[a.toString()]};j.append(s);var u=j.parent().inheritedData("$uiView");p.indexOf("@")<0&&(p=p+"@"+(u?u.state.name:""));var v={name:p,state:null};j.data("$uiView",v);var w=function(){if(!h){h=!0;try{m(!0)}catch(a){throw h=!1,a}h=!1}};e.$on("$stateChangeSuccess",w),e.$on("$viewContentLoading",w),m(!1)}}};return i}function t(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function u(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function v(a,b){return{restrict:"A",require:"?^uiSrefActive",link:function(c,d,e,f){var g=t(e.uiSref),h=null,i=u(d)||a.$current,j="FORM"===d[0].nodeName,k=j?"action":"href",l=!0,m=function(b){if(b&&(h=b),l){var c=a.href(g.state,h,{relative:i});if(!c)return l=!1,!1;d[0][k]=c,f&&f.$$setStateInfo(g.state,h)}};g.paramExpr&&(c.$watch(g.paramExpr,function(a){a!==h&&m(a)},!0),h=c.$eval(g.paramExpr)),m(),j||d.bind("click",function(d){var e=d.which||d.button;0!==e&&1!=e||d.ctrlKey||d.metaKey||d.shiftKey||(b(function(){c.$apply(function(){a.go(g.state,h,{relative:i})})}),d.preventDefault())})}}}function w(a,b,c){return{restrict:"A",controller:function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,u(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}}}function x(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(A(j))h=j;else{if(!z(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),F(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var y=b.isDefined,z=b.isFunction,A=b.isString,B=b.isObject,C=b.isArray,D=b.forEach,E=b.extend,F=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),s.$inject=["$state","$compile","$controller","$injector","$anchorScroll"],b.module("ui.router.state").directive("uiView",s),v.$inject=["$state","$timeout"],w.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",v).directive("uiSrefActive",w),x.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",x).directive("ngView",s)}(window,window.angular); 8 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | 2 | // Button Mixins 3 | // -------------------------------------------------- 4 | 5 | @mixin button-style($bg-color, $border-color, $active-bg-color, $active-border-color, $color) { 6 | border-color: $border-color; 7 | background-color: $bg-color; 8 | color: $color; 9 | 10 | // Give desktop users something to play with 11 | &:hover { 12 | color: $color; 13 | text-decoration: none; 14 | } 15 | &.active { 16 | border-color: $active-border-color; 17 | background-color: $active-bg-color; 18 | box-shadow: inset 0px 1px 3px rgba(0,0,0,0.15); 19 | } 20 | } 21 | 22 | @mixin button-clear($color, $font-size:"") { 23 | &.button-clear { 24 | border-color: transparent; 25 | background: none; 26 | box-shadow: none; 27 | color: $color; 28 | 29 | @if $font-size != "" { 30 | font-size: $font-size; 31 | } 32 | } 33 | &.button-icon { 34 | border-color: transparent; 35 | background: none; 36 | } 37 | } 38 | 39 | @mixin button-outline($color, $text-color:"") { 40 | &.button-outline { 41 | border-color: $color; 42 | background: transparent; 43 | @if $text-color == "" { 44 | $text-color: $color; 45 | } 46 | color: $text-color; 47 | &.active { 48 | background-color: $color; 49 | box-shadow: none; 50 | color: #fff; 51 | } 52 | } 53 | } 54 | 55 | 56 | // Bar Mixins 57 | // -------------------------------------------------- 58 | 59 | @mixin bar-style($bg-color, $border-color, $color) { 60 | border-color: $border-color; 61 | background-color: $bg-color; 62 | background-image: linear-gradient(0deg, $border-color, $border-color 50%, transparent 50%); 63 | color: $color; 64 | 65 | .title { 66 | color: $color; 67 | } 68 | } 69 | 70 | 71 | // Tab Mixins 72 | // -------------------------------------------------- 73 | 74 | @mixin tab-style($bg-color, $border-color, $color) { 75 | border-color: $border-color; 76 | background-color: $bg-color; 77 | background-image: linear-gradient(0deg, $border-color, $border-color 50%, transparent 50%); 78 | color: $color; 79 | } 80 | 81 | @mixin tab-badge-style($bg-color, $color) { 82 | .tab-item .badge { 83 | background-color: $bg-color; 84 | color: $color; 85 | } 86 | } 87 | 88 | 89 | // Item Mixins 90 | // -------------------------------------------------- 91 | 92 | @mixin item-style($bg-color, $border-color, $color) { 93 | border-color: $border-color; 94 | background-color: $bg-color; 95 | color: $color; 96 | } 97 | 98 | @mixin item-active-style($active-bg-color, $active-border-color) { 99 | border-color: $active-border-color; 100 | background-color: $active-bg-color; 101 | } 102 | 103 | 104 | // Badge Mixins 105 | // -------------------------------------------------- 106 | 107 | @mixin badge-style($bg-color, $color) { 108 | background-color: $bg-color; 109 | color: $color; 110 | } 111 | 112 | 113 | // Range Mixins 114 | // -------------------------------------------------- 115 | 116 | @mixin range-style($track-bg-color) { 117 | &::-webkit-slider-thumb:before { 118 | background: $track-bg-color; 119 | } 120 | } 121 | 122 | 123 | // Checkbox Mixins 124 | // -------------------------------------------------- 125 | 126 | @mixin checkbox-style($off-border-color, $on-bg-color) { 127 | & input:before { 128 | border: $checkbox-border-width solid $off-border-color; 129 | } 130 | 131 | // what the background looks like when its checked 132 | & input:checked:before { 133 | background: $on-bg-color; 134 | } 135 | } 136 | 137 | 138 | // Toggle Mixins 139 | // -------------------------------------------------- 140 | 141 | @mixin toggle-style($on-border-color, $on-bg-color) { 142 | // the track when the toggle is "on" 143 | & input:checked + .track { 144 | border-color: $on-border-color; 145 | background-color: $on-bg-color; 146 | } 147 | } 148 | 149 | 150 | // Clearfix 151 | // -------------------------------------------------- 152 | 153 | @mixin clearfix { 154 | *zoom: 1; 155 | &:before, 156 | &:after { 157 | display: table; 158 | content: ""; 159 | line-height: 0; 160 | } 161 | &:after { 162 | clear: both; 163 | } 164 | } 165 | 166 | 167 | // Placeholder text 168 | // -------------------------------------------------- 169 | 170 | @mixin placeholder($color: $input-color-placeholder) { 171 | &:-moz-placeholder { 172 | color: $color; 173 | } 174 | &:-ms-input-placeholder { 175 | color: $color; 176 | } 177 | &::-webkit-input-placeholder { 178 | color: $color; 179 | } 180 | } 181 | 182 | 183 | // Text Mixins 184 | // -------------------------------------------------- 185 | 186 | @mixin text-size-adjust($value: none) { 187 | -webkit-text-size-adjust: $value; 188 | -moz-text-size-adjust: $value; 189 | text-size-adjust: $value; 190 | } 191 | @mixin tap-highlight-transparent() { 192 | -webkit-tap-highlight-color: rgba(0,0,0,0); 193 | -webkit-tap-highlight-color: transparent; // For some Androids 194 | } 195 | @mixin touch-callout($value: none) { 196 | -webkit-touch-callout: $value; 197 | } 198 | 199 | 200 | // Font Mixins 201 | // -------------------------------------------------- 202 | 203 | @mixin font-family-serif() { 204 | font-family: $serif-font-family; 205 | } 206 | @mixin font-family-sans-serif() { 207 | font-family: $sans-font-family; 208 | } 209 | @mixin font-family-monospace() { 210 | font-family: $mono-font-family; 211 | } 212 | @mixin font-shorthand($size: $base-font-size, $weight: normal, $line-height: $base-line-height) { 213 | font-weight: $weight; 214 | font-size: $size; 215 | line-height: $line-height; 216 | } 217 | @mixin font-serif($size: $base-font-size, $weight: normal, $line-height: $base-line-height) { 218 | @include font-family-serif(); 219 | @include font-shorthand($size, $weight, $line-height); 220 | } 221 | @mixin font-sans-serif($size: $base-font-size, $weight: normal, $line-height: $base-line-height) { 222 | @include font-family-sans-serif(); 223 | @include font-shorthand($size, $weight, $line-height); 224 | } 225 | @mixin font-monospace($size: $base-font-size, $weight: normal, $line-height: $base-line-height) { 226 | @include font-family-monospace(); 227 | @include font-shorthand($size, $weight, $line-height); 228 | } 229 | @mixin font-smoothing($font-smoothing) { 230 | -webkit-font-smoothing: $font-smoothing; 231 | font-smoothing: $font-smoothing; 232 | } 233 | 234 | 235 | // Appearance 236 | // -------------------------------------------------- 237 | 238 | @mixin appearance($val) { 239 | -webkit-appearance: $val; 240 | -moz-appearance: $val; 241 | appearance: $val; 242 | } 243 | 244 | 245 | // Border Radius Mixins 246 | // -------------------------------------------------- 247 | 248 | @mixin border-radius($radius) { 249 | -webkit-border-radius: $radius; 250 | -moz-border-radius: $radius; 251 | border-radius: $radius; 252 | } 253 | 254 | // Single Corner Border Radius 255 | @mixin border-top-left-radius($radius) { 256 | -webkit-border-top-left-radius: $radius; 257 | -moz-border-radius-topleft: $radius; 258 | border-top-left-radius: $radius; 259 | } 260 | @mixin border-top-right-radius($radius) { 261 | -webkit-border-top-right-radius: $radius; 262 | -moz-border-radius-topright: $radius; 263 | border-top-right-radius: $radius; 264 | } 265 | @mixin border-bottom-right-radius($radius) { 266 | -webkit-border-bottom-right-radius: $radius; 267 | -moz-border-radius-bottomright: $radius; 268 | border-bottom-right-radius: $radius; 269 | } 270 | @mixin border-bottom-left-radius($radius) { 271 | -webkit-border-bottom-left-radius: $radius; 272 | -moz-border-radius-bottomleft: $radius; 273 | border-bottom-left-radius: $radius; 274 | } 275 | 276 | // Single Side Border Radius 277 | @mixin border-top-radius($radius) { 278 | @include border-top-right-radius($radius); 279 | @include border-top-left-radius($radius); 280 | } 281 | @mixin border-right-radius($radius) { 282 | @include border-top-right-radius($radius); 283 | @include border-bottom-right-radius($radius); 284 | } 285 | @mixin border-bottom-radius($radius) { 286 | @include border-bottom-right-radius($radius); 287 | @include border-bottom-left-radius($radius); 288 | } 289 | @mixin border-left-radius($radius) { 290 | @include border-top-left-radius($radius); 291 | @include border-bottom-left-radius($radius); 292 | } 293 | 294 | 295 | // Box shadows 296 | // -------------------------------------------------- 297 | 298 | @mixin box-shadow($shadow...) { 299 | -webkit-box-shadow: $shadow; 300 | -moz-box-shadow: $shadow; 301 | box-shadow: $shadow; 302 | } 303 | 304 | 305 | // Transition Mixins 306 | // -------------------------------------------------- 307 | 308 | @mixin transition($transition...) { 309 | -webkit-transition: $transition; 310 | -moz-transition: $transition; 311 | transition: $transition; 312 | } 313 | @mixin transition-delay($transition-delay) { 314 | -webkit-transition-delay: $transition-delay; 315 | -moz-transition-delay: $transition-delay; 316 | transition-delay: $transition-delay; 317 | } 318 | @mixin transition-duration($transition-duration) { 319 | -webkit-transition-duration: $transition-duration; 320 | -moz-transition-duration: $transition-duration; 321 | transition-duration: $transition-duration; 322 | } 323 | @mixin transition-timing-function($transition-timing) { 324 | -webkit-transition-timing-function: $transition-timing; 325 | -moz-transition-timing-function: $transition-timing; 326 | transition-timing-function: $transition-timing; 327 | } 328 | @mixin transition-property($property) { 329 | -webkit-transition-property: $property; 330 | -moz-transition-property: $property; 331 | transition-property: $property; 332 | } 333 | @mixin transition-transform($properties...) { 334 | // special case cuz of transform vendor prefixes 335 | -webkit-transition: -webkit-transform $properties; 336 | -moz-transition: -moz-transform $properties; 337 | transition: transform $properties; 338 | } 339 | 340 | 341 | // Animation Mixins 342 | // -------------------------------------------------- 343 | 344 | @mixin animation($animation) { 345 | -webkit-animation: $animation; 346 | -moz-animation: $animation; 347 | animation: $animation; 348 | } 349 | @mixin animation-duration($duration) { 350 | -webkit-animation-duration: $duration; 351 | -moz-animation-duration: $duration; 352 | animation-duration: $duration; 353 | } 354 | @mixin animation-direction($direction) { 355 | -webkit-animation-direction: $direction; 356 | -moz-animation-direction: $direction; 357 | animation-direction: $direction; 358 | } 359 | @mixin animation-timing-function($animation-timing) { 360 | -webkit-animation-timing-function: $animation-timing; 361 | -moz-animation-timing-function: $animation-timing; 362 | animation-timing-function: $animation-timing; 363 | } 364 | @mixin animation-fill-mode($fill-mode) { 365 | -webkit-animation-fill-mode: $fill-mode; 366 | -moz-animation-fill-mode: $fill-mode; 367 | animation-fill-mode: $fill-mode; 368 | } 369 | @mixin animation-name($name) { 370 | -webkit-animation-name: $name; 371 | -moz-animation-name: $name; 372 | animation-name: $name; 373 | } 374 | @mixin animation-iteration-count($count) { 375 | -webkit-animation-iteration-count: $count; 376 | -moz-animation-iteration-count: $count; 377 | animation-iteration-count: $count; 378 | } 379 | 380 | 381 | // Transformation Mixins 382 | // -------------------------------------------------- 383 | 384 | @mixin rotate($degrees) { 385 | @include transform( rotate($degrees) ); 386 | } 387 | @mixin scale($ratio) { 388 | @include transform( scale($ratio) ); 389 | } 390 | @mixin translate($x, $y) { 391 | @include transform( translate($x, $y) ); 392 | } 393 | @mixin skew($x, $y) { 394 | @include transform( skew($x, $y) ); 395 | -webkit-backface-visibility: hidden; 396 | } 397 | @mixin translate3d($x, $y, $z) { 398 | @include transform( translate3d($x, $y, $z) ); 399 | } 400 | @mixin translateZ($z) { 401 | @include transform( translateZ($z) ); 402 | } 403 | @mixin transform($val) { 404 | -webkit-transform: $val; 405 | -moz-transform: $val; 406 | transform: $val; 407 | } 408 | 409 | @mixin transform-origin($left, $top) { 410 | -webkit-transform-origin: $left $top; 411 | -moz-transform-origin: $left $top; 412 | transform-origin: $left $top; 413 | } 414 | 415 | 416 | // Backface visibility 417 | // -------------------------------------------------- 418 | // Prevent browsers from flickering when using CSS 3D transforms. 419 | // Default value is `visible`, but can be changed to `hidden 420 | 421 | @mixin backface-visibility($visibility){ 422 | -webkit-backface-visibility: $visibility; 423 | backface-visibility: $visibility; 424 | } 425 | 426 | 427 | // Background clipping 428 | // -------------------------------------------------- 429 | 430 | @mixin background-clip($clip) { 431 | -webkit-background-clip: $clip; 432 | -moz-background-clip: $clip; 433 | background-clip: $clip; 434 | } 435 | 436 | 437 | // Background sizing 438 | // -------------------------------------------------- 439 | 440 | @mixin background-size($size) { 441 | -webkit-background-size: $size; 442 | -moz-background-size: $size; 443 | background-size: $size; 444 | } 445 | 446 | 447 | // Box sizing 448 | // -------------------------------------------------- 449 | 450 | @mixin box-sizing($boxmodel) { 451 | -webkit-box-sizing: $boxmodel; 452 | -moz-box-sizing: $boxmodel; 453 | box-sizing: $boxmodel; 454 | } 455 | 456 | 457 | // User select 458 | // -------------------------------------------------- 459 | 460 | @mixin user-select($select) { 461 | -webkit-user-select: $select; 462 | -moz-user-select: $select; 463 | -ms-user-select: $select; 464 | user-select: $select; 465 | } 466 | 467 | 468 | // Content Columns 469 | // -------------------------------------------------- 470 | 471 | @mixin content-columns($columnCount, $columnGap: $grid-gutter-width) { 472 | -webkit-column-count: $columnCount; 473 | -moz-column-count: $columnCount; 474 | column-count: $columnCount; 475 | -webkit-column-gap: $columnGap; 476 | -moz-column-gap: $columnGap; 477 | column-gap: $columnGap; 478 | } 479 | 480 | 481 | // Flexbox Mixins 482 | // -------------------------------------------------- 483 | // http://philipwalton.github.io/solved-by-flexbox/ 484 | // https://github.com/philipwalton/solved-by-flexbox 485 | 486 | @mixin display-flex { 487 | display: -webkit-box; 488 | display: -webkit-flex; 489 | display: -moz-box; 490 | display: -moz-flex; 491 | display: -ms-flexbox; 492 | display: flex; 493 | } 494 | 495 | @mixin dislay-inline-flex { 496 | display: -webkit-inline-box; 497 | display: -webkit-inline-flex; 498 | display: -moz-inline-flex; 499 | display: -ms-inline-flexbox; 500 | display: inline-flex; 501 | } 502 | 503 | @mixin flex-direction($value: row) { 504 | @if $value == row-reverse { 505 | -webkit-box-direction: reverse; 506 | -webkit-box-orient: horizontal; 507 | } @else if $value == column { 508 | -webkit-box-direction: normal; 509 | -webkit-box-orient: vertical; 510 | } @else if $value == column-reverse { 511 | -webkit-box-direction: reverse; 512 | -webkit-box-orient: vertical; 513 | } @else { 514 | -webkit-box-direction: normal; 515 | -webkit-box-orient: horizontal; 516 | } 517 | -webkit-flex-direction: $value; 518 | -moz-flex-direction: $value; 519 | -ms-flex-direction: $value; 520 | flex-direction: $value; 521 | } 522 | 523 | @mixin flex-wrap($value: nowrap) { 524 | // No Webkit Box fallback. 525 | -webkit-flex-wrap: $value; 526 | -moz-flex-wrap: $value; 527 | @if $value == nowrap { 528 | -ms-flex-wrap: none; 529 | } @else { 530 | -ms-flex-wrap: $value; 531 | } 532 | flex-wrap: $value; 533 | } 534 | 535 | @mixin flex($fg: 1, $fs: null, $fb: null) { 536 | -webkit-box-flex: $fg; 537 | -webkit-flex: $fg $fs $fb; 538 | -moz-box-flex: $fg; 539 | -moz-flex: $fg $fs $fb; 540 | -ms-flex: $fg $fs $fb; 541 | flex: $fg $fs $fb; 542 | } 543 | 544 | @mixin flex-flow($values: (row nowrap)) { 545 | // No Webkit Box fallback. 546 | -webkit-flex-flow: $values; 547 | -moz-flex-flow: $values; 548 | -ms-flex-flow: $values; 549 | flex-flow: $values; 550 | } 551 | 552 | @mixin align-items($value: stretch) { 553 | @if $value == flex-start { 554 | -webkit-box-align: start; 555 | -ms-flex-align: start; 556 | } @else if $value == flex-end { 557 | -webkit-box-align: end; 558 | -ms-flex-align: end; 559 | } @else { 560 | -webkit-box-align: $value; 561 | -ms-flex-align: $value; 562 | } 563 | -webkit-align-items: $value; 564 | -moz-align-items: $value; 565 | align-items: $value; 566 | } 567 | 568 | @mixin align-self($value: auto) { 569 | -webkit-align-self: $value; 570 | -moz-align-self: $value; 571 | @if $value == flex-start { 572 | -ms-flex-item-align: start; 573 | } @else if $value == flex-end { 574 | -ms-flex-item-align: end; 575 | } @else { 576 | -ms-flex-item-align: $value; 577 | } 578 | align-self: $value; 579 | } 580 | 581 | @mixin align-content($value: stretch) { 582 | -webkit-align-content: $value; 583 | -moz-align-content: $value; 584 | @if $value == flex-start { 585 | -ms-flex-line-pack: start; 586 | } @else if $value == flex-end { 587 | -ms-flex-line-pack: end; 588 | } @else { 589 | -ms-flex-line-pack: $value; 590 | } 591 | align-content: $value; 592 | } 593 | 594 | @mixin justify-content($value: stretch) { 595 | @if $value == flex-start { 596 | -webkit-box-pack: start; 597 | -ms-flex-pack: start; 598 | } @else if $value == flex-end { 599 | -webkit-box-pack: end; 600 | -ms-flex-pack: end; 601 | } @else if $value == space-between { 602 | -webkit-box-pack: justify; 603 | -ms-flex-pack: justify; 604 | } @else { 605 | -webkit-box-pack: $value; 606 | -ms-flex-pack: $value; 607 | } 608 | -webkit-justify-content: $value; 609 | -moz-justify-content: $value; 610 | justify-content: $value; 611 | } 612 | 613 | @mixin responsive-grid-break($selector, $max-width) { 614 | @media (max-width: $max-width) { 615 | #{$selector} { 616 | -webkit-box-direction: normal; 617 | -moz-box-direction: normal; 618 | -webkit-box-orient: vertical; 619 | -moz-box-orient: vertical; 620 | -webkit-flex-direction: column; 621 | -ms-flex-direction: column; 622 | flex-direction: column; 623 | 624 | .col, .col-10, .col-20, .col-25, .col-33, .col-34, .col-50, .col-66, .col-67, .col-75, .col-80, .col-90 { 625 | @include flex(1); 626 | margin-bottom: ($grid-padding-width * 3) / 2; 627 | margin-left: 0; 628 | max-width: 100%; 629 | width: 100%; 630 | } 631 | } 632 | } 633 | } 634 | -------------------------------------------------------------------------------- /www/lib/ionic/scss/_items.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Items 3 | * -------------------------------------------------- 4 | */ 5 | 6 | .item { 7 | @include item-style($item-default-bg, $item-default-border, $item-default-text); 8 | 9 | position: relative; 10 | z-index: $z-index-item; // Make sure the borders and stuff don't get hidden by children 11 | display: block; 12 | 13 | margin: $item-border-width * -1; 14 | padding: $item-padding; 15 | 16 | border-width: $item-border-width; 17 | border-style: solid; 18 | font-size: $item-font-size; 19 | 20 | h2 { 21 | margin: 0 0 4px 0; 22 | font-size: 16px; 23 | } 24 | h3 { 25 | margin: 0 0 4px 0; 26 | font-size: 14px; 27 | } 28 | h4 { 29 | margin: 0 0 4px 0; 30 | font-size: 12px; 31 | } 32 | h5, h6 { 33 | margin: 0 0 3px 0; 34 | font-size: 10px; 35 | } 36 | p { 37 | color: #666; 38 | font-size: 14px; 39 | } 40 | 41 | h1:last-child, 42 | h2:last-child, 43 | h3:last-child, 44 | h4:last-child, 45 | h5:last-child, 46 | h6:last-child, 47 | p:last-child { 48 | margin-bottom: 0; 49 | } 50 | 51 | // Align badges within items 52 | .badge { 53 | @include display-flex(); 54 | position: absolute; 55 | top: $item-padding; 56 | right: ($item-padding * 2) + 5; 57 | } 58 | &.item-button-right .badge { 59 | right: ($item-padding * 2) + 35; 60 | } 61 | &.item-divider .badge { 62 | top: $item-padding / 2; 63 | } 64 | .badge + .badge { 65 | margin-right: 5px; 66 | } 67 | 68 | // Different themes for items 69 | &.item-light { 70 | @include item-style($item-light-bg, $item-light-border, $item-light-text); 71 | } 72 | &.item-stable { 73 | @include item-style($item-stable-bg, $item-stable-border, $item-stable-text); 74 | } 75 | &.item-positive { 76 | @include item-style($item-positive-bg, $item-positive-border, $item-positive-text); 77 | } 78 | &.item-calm { 79 | @include item-style($item-calm-bg, $item-calm-border, $item-calm-text); 80 | } 81 | &.item-assertive { 82 | @include item-style($item-assertive-bg, $item-assertive-border, $item-assertive-text); 83 | } 84 | &.item-balanced { 85 | @include item-style($item-balanced-bg, $item-balanced-border, $item-balanced-text); 86 | } 87 | &.item-energized { 88 | @include item-style($item-energized-bg, $item-energized-border, $item-energized-text); 89 | } 90 | &.item-royal { 91 | @include item-style($item-royal-bg, $item-royal-border, $item-royal-text); 92 | } 93 | &.item-dark { 94 | @include item-style($item-dark-bg, $item-dark-border, $item-dark-text); 95 | } 96 | 97 | &[ng-click]:hover { 98 | cursor: pointer; 99 | } 100 | 101 | } 102 | 103 | // Link and Button Active States 104 | .item.active:not(.item-divider):not(.item-input):not(.item-input-inset), 105 | .item-complex.active .item-content { 106 | @include item-active-style($item-default-active-bg, $item-default-active-border); 107 | 108 | // Different active themes for and