├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── app ├── .buildignore ├── .htaccess ├── 404.html ├── cordova_plugins.json ├── favicon.ico ├── images │ ├── backgrounds │ │ └── gradient.jpg │ └── workouts │ │ ├── abdominal-crunch.png │ │ ├── high-knees-running-in-place.png │ │ ├── jumping-jacks.png │ │ ├── lunge.png │ │ ├── plank.png │ │ ├── push-up-and-rotation.png │ │ ├── push-up.png │ │ ├── side-plank.png │ │ ├── squat.png │ │ ├── step-up-onto-chair.png │ │ ├── triceps-dip-on-chair.png │ │ └── wall-sit.png ├── index.html ├── libraries │ └── angular-mobile.js ├── robots.txt ├── scripts │ ├── app.js │ ├── controllers │ │ ├── main.js │ │ ├── rest.js │ │ └── steps.js │ ├── filters.js │ ├── plugins │ │ └── cordova-analytics.js │ └── services.js ├── sounds │ ├── mailerror.wav │ ├── mailsent.wav │ ├── newmail.wav │ ├── tick-rest.wav │ └── tick.wav ├── styles │ ├── fonts │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── satisfy-webfont.ttf │ │ └── satisfy-webfont.woff │ ├── includes │ │ ├── animations.less │ │ ├── font-awesome.less │ │ └── page-transitions.less │ ├── main.css │ ├── main.less │ └── workouts.less └── views │ ├── done.html │ ├── main.html │ ├── rest.html │ └── step.html ├── bower.json ├── license.md ├── package.json ├── readme.md ├── takedown └── 20130506-nytimes.jpg └── test ├── karma-e2e.conf.js ├── karma.conf.js ├── runner.html └── spec └── controllers └── main.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/components" 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .tmp 3 | *.sublime-project 4 | *.sublime-workspace 5 | node_modules 6 | app/components 7 | dist 8 | cordova 9 | sources 10 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "node": true, 4 | "browser": true, 5 | "jquery": true, 6 | "devel": false, 7 | "es5": true, 8 | "esnext": true, 9 | "bitwise": true, 10 | 11 | "camelcase": false, 12 | "curly": false, 13 | "eqeqeq": true, 14 | "immed": true, 15 | "indent": 2, 16 | "latedef": true, 17 | "newcap": true, 18 | "noarg": true, 19 | "quotmark": "single", 20 | "regexp": true, 21 | "undef": true, 22 | "unused": false, 23 | "strict": true, 24 | "trailing": true, 25 | "smarttabs": true, 26 | 27 | "boss": false, 28 | "eqnull": false, 29 | "expr": true, 30 | 31 | "globals": { 32 | "angular": false 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | before_script: 6 | - export DISPLAY=:99.0 7 | - export PHANTOMJS_BIN=/usr/local/phantomjs/bin/phantomjs 8 | - sh -e /etc/init.d/xvfb start 9 | - sleep 3 # give xvfb some time to start 10 | - npm install -g grunt-cli 11 | 12 | script: 13 | - grunt jshint karma:unit 14 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (grunt) { 4 | 5 | // load all grunt tasks 6 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 7 | 8 | // livereload 9 | var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet; 10 | var mountFolder = function (connect, dir) { 11 | return connect.static(require('path').resolve(dir)); 12 | }; 13 | 14 | // configurable paths 15 | var yeomanConfig = { 16 | app: 'app', 17 | dist: 'src' 18 | }; 19 | 20 | grunt.initConfig({ 21 | yeoman: yeomanConfig, 22 | pkg: grunt.file.readJSON('package.json'), 23 | meta: { 24 | banner: '/**\n' + 25 | ' * <%= pkg.description %>\n' + 26 | ' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 27 | ' * @link <%= pkg.homepage %>\n' + 28 | ' * @author <%= pkg.author %>\n' + 29 | ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' + 30 | ' */\n' 31 | }, 32 | watch: { 33 | // coffee: { 34 | // files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'], 35 | // tasks: ['coffee:dist'] 36 | // }, 37 | // coffeeTest: { 38 | // files: ['test/spec/{,*/}*.coffee'], 39 | // tasks: ['coffee:test'] 40 | // }, 41 | // compass: { 42 | // files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], 43 | // tasks: ['compass'] 44 | // }, 45 | less: { 46 | files: ['<%= yeoman.app %>/styles/{,*/}*.less'], 47 | tasks: ['less:dist'] 48 | }, 49 | livereload: { 50 | files: [ 51 | '<%= yeoman.app %>/{,*/}*.html', 52 | '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css', 53 | '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js', 54 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' 55 | ], 56 | tasks: ['livereload'] 57 | } 58 | }, 59 | connect: { 60 | options: { 61 | port: 9000, 62 | // Change this to '0.0.0.0' to access the server from outside. 63 | hostname: 'localhost' 64 | }, 65 | livereload: { 66 | options: { 67 | middleware: function (connect) { 68 | return [ 69 | lrSnippet, 70 | mountFolder(connect, '.tmp'), 71 | mountFolder(connect, yeomanConfig.app) 72 | ]; 73 | } 74 | } 75 | }, 76 | test: { 77 | options: { 78 | middleware: function (connect) { 79 | return [ 80 | mountFolder(connect, '.tmp'), 81 | mountFolder(connect, 'test') 82 | ]; 83 | } 84 | } 85 | } 86 | }, 87 | open: { 88 | server: { 89 | url: 'http://localhost:<%= connect.options.port %>' 90 | } 91 | }, 92 | clean: { 93 | dist: { 94 | files: [{ 95 | dot: true, 96 | src: [ 97 | '.tmp', 98 | '<%= yeoman.dist %>/*', 99 | '!<%= yeoman.dist %>/.git*' 100 | ] 101 | }] 102 | }, 103 | server: '.tmp' 104 | }, 105 | jshint: { 106 | options: { 107 | jshintrc: '.jshintrc' 108 | }, 109 | all: [ 110 | 'Gruntfile.js', 111 | '<%= yeoman.app %>/scripts/{,*/}*.js' 112 | ] 113 | }, 114 | karma: { 115 | options: { 116 | configFile: 'test/karma.conf.js', 117 | browsers: ['PhantomJS'] 118 | }, 119 | unit: { 120 | port: 9090, 121 | singleRun: true 122 | }, 123 | server: { 124 | autoWatch: true 125 | } 126 | }, 127 | // coffee: { 128 | // dist: { 129 | // files: [{ 130 | // expand: true, 131 | // cwd: '<%= yeoman.app %>/scripts', 132 | // src: '{,*/}*.coffee', 133 | // dest: '.tmp/scripts', 134 | // ext: '.js' 135 | // }] 136 | // }, 137 | // test: { 138 | // files: [{ 139 | // expand: true, 140 | // cwd: 'test/spec', 141 | // src: '{,*/}*.coffee', 142 | // dest: '.tmp/spec', 143 | // ext: '.js' 144 | // }] 145 | // } 146 | // }, 147 | // compass: { 148 | // options: { 149 | // sassDir: '<%= yeoman.app %>/styles', 150 | // cssDir: '.tmp/styles', 151 | // imagesDir: '<%= yeoman.app %>/images', 152 | // javascriptsDir: '<%= yeoman.app %>/scripts', 153 | // fontsDir: '<%= yeoman.app %>/styles/fonts', 154 | // importPath: '<%= yeoman.app %>/components', 155 | // relativeAssets: true 156 | // }, 157 | // dist: {}, 158 | // server: { 159 | // options: { 160 | // debugInfo: true 161 | // } 162 | // } 163 | // }, 164 | less: { 165 | options: { 166 | paths: ['<%= yeoman.app %>/styles'], 167 | }, 168 | dist: { 169 | files: { 170 | '<%= yeoman.app %>/styles/main.css': '<%= yeoman.app %>/styles/main.less' 171 | } 172 | } 173 | }, 174 | concat: { 175 | options: { 176 | banner: '<%= meta.banner %>' 177 | }, 178 | dist: { 179 | files: { 180 | '<%= yeoman.dist %>/scripts/scripts.js': [ 181 | '.tmp/scripts/{,*/}*.js', 182 | '<%= yeoman.app %>/scripts/{,*/}*.js' 183 | ] 184 | } 185 | } 186 | }, 187 | useminPrepare: { 188 | html: '<%= yeoman.app %>/index.html', 189 | options: { 190 | dest: '<%= yeoman.dist %>' 191 | } 192 | }, 193 | usemin: { 194 | html: ['<%= yeoman.dist %>/{,*/}*.html'], 195 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 196 | options: { 197 | dirs: ['<%= yeoman.dist %>'] 198 | } 199 | }, 200 | imagemin: { 201 | dist: { 202 | files: [{ 203 | expand: true, 204 | cwd: '<%= yeoman.app %>/images', 205 | src: '{,*/}*.{png,jpg,jpeg}', 206 | dest: '<%= yeoman.dist %>/images' 207 | }] 208 | } 209 | }, 210 | cssmin: { 211 | dist: { 212 | files: { 213 | '<%= yeoman.dist %>/styles/main.css': [ 214 | '.tmp/styles/{,*/}*.css', 215 | '<%= yeoman.app %>/styles/{,*/}*.css' 216 | ] 217 | } 218 | } 219 | }, 220 | htmlmin: { 221 | dist: { 222 | options: { 223 | /*removeCommentsFromCDATA: true, 224 | // https://github.com/yeoman/grunt-usemin/issues/44 225 | //collapseWhitespace: true, 226 | collapseBooleanAttributes: true, 227 | removeAttributeQuotes: true, 228 | removeRedundantAttributes: true, 229 | useShortDoctype: true, 230 | removeEmptyAttributes: true, 231 | removeOptionalTags: true*/ 232 | }, 233 | files: [{ 234 | expand: true, 235 | cwd: '<%= yeoman.app %>', 236 | src: ['*.html', 'views/*.html'], 237 | dest: '<%= yeoman.dist %>' 238 | }] 239 | } 240 | }, 241 | cdnify: { 242 | dist: { 243 | html: ['<%= yeoman.dist %>/*.html'] 244 | } 245 | }, 246 | ngmin: { 247 | dist: { 248 | files: [{ 249 | expand: true, 250 | cwd: '<%= yeoman.dist %>/scripts', 251 | src: '*.js', 252 | dest: '<%= yeoman.dist %>/scripts' 253 | }] 254 | } 255 | }, 256 | uglify: { 257 | options: { 258 | banner: '<%= meta.banner %>', 259 | // report: 'gzip', 260 | useStrict: false 261 | }, 262 | dist: { 263 | files: { 264 | '<%= yeoman.dist %>/scripts/scripts.js': [ 265 | '<%= yeoman.dist %>/scripts/scripts.js' 266 | ], 267 | '<%= yeoman.dist %>/scripts/libs.js': [ 268 | '<%= yeoman.dist %>/scripts/libs.js' 269 | ] 270 | } 271 | } 272 | }, 273 | rev: { 274 | dist: { 275 | files: { 276 | src: [ 277 | '<%= yeoman.dist %>/scripts/{,*/}*.js', 278 | '<%= yeoman.dist %>/styles/{,*/}*.css', 279 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', 280 | '<%= yeoman.dist %>/styles/fonts/*' 281 | ] 282 | } 283 | } 284 | }, 285 | copy: { 286 | dist: { 287 | files: [{ 288 | expand: true, 289 | dot: true, 290 | cwd: '<%= yeoman.app %>', 291 | dest: '<%= yeoman.dist %>', 292 | src: [ 293 | '*.{ico,txt,json}', 294 | // '.htaccess', 295 | // 'components/**/*', 296 | 'sounds/{,*/}*.{wav,mp3}', 297 | 'images/{,*/}*.{gif,webp,png}', 298 | 'styles/fonts/*' 299 | ] 300 | }] 301 | } 302 | } 303 | }); 304 | 305 | grunt.renameTask('regarde', 'watch'); 306 | 307 | grunt.registerTask('server', [ 308 | 'clean:server', 309 | // 'coffee:dist', 310 | // 'compass:server', 311 | 'less:dist', 312 | 'livereload-start', 313 | 'connect:livereload', 314 | 'open', 315 | 'watch' 316 | ]); 317 | 318 | grunt.registerTask('test', [ 319 | 'clean:server', 320 | // 'coffee', 321 | // 'compass', 322 | 'connect:test', 323 | 'karma:unit' 324 | ]); 325 | 326 | grunt.registerTask('build', [ 327 | 'clean:dist', 328 | 'jshint', 329 | 'test', 330 | // 'coffee', 331 | // 'compass:dist', 332 | 'less:dist', 333 | 'useminPrepare', 334 | 'imagemin', 335 | 'cssmin', 336 | 'htmlmin', 337 | 'concat', 338 | 'copy', 339 | // 'cdnify', 340 | 'ngmin', 341 | 'uglify', 342 | 'rev', 343 | 'usemin' 344 | ]); 345 | 346 | grunt.registerTask('fast-build', [ 347 | 'clean:dist', 348 | 'less:dist', 349 | 'useminPrepare', 350 | // 'imagemin', 351 | 'cssmin', 352 | 'htmlmin', 353 | 'concat', 354 | 'copy', 355 | // 'cdnify', 356 | 'ngmin', 357 | 'uglify', 358 | 'rev', 359 | 'usemin' 360 | ]); 361 | 362 | grunt.registerTask('default', ['build']); 363 | }; 364 | -------------------------------------------------------------------------------- /app/.buildignore: -------------------------------------------------------------------------------- 1 | *.coffee -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | # Apache configuration file 2 | # httpd.apache.org/docs/2.2/mod/quickreference.html 3 | 4 | # Note .htaccess files are an overhead, this logic should be in your Apache 5 | # config if possible: httpd.apache.org/docs/2.2/howto/htaccess.html 6 | 7 | # Techniques in here adapted from all over, including: 8 | # Kroc Camen: camendesign.com/.htaccess 9 | # perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/ 10 | # Sample .htaccess file of CMS MODx: modxcms.com 11 | 12 | 13 | # ---------------------------------------------------------------------- 14 | # Better website experience for IE users 15 | # ---------------------------------------------------------------------- 16 | 17 | # Force the latest IE version, in various cases when it may fall back to IE7 mode 18 | # github.com/rails/rails/commit/123eb25#commitcomment-118920 19 | # Use ChromeFrame if it's installed for a better experience for the poor IE folk 20 | 21 | 22 | Header set X-UA-Compatible "IE=Edge,chrome=1" 23 | # mod_headers can't match by content-type, but we don't want to send this header on *everything*... 24 | 25 | Header unset X-UA-Compatible 26 | 27 | 28 | 29 | 30 | # ---------------------------------------------------------------------- 31 | # Cross-domain AJAX requests 32 | # ---------------------------------------------------------------------- 33 | 34 | # Serve cross-domain Ajax requests, disabled by default. 35 | # enable-cors.org 36 | # code.google.com/p/html5security/wiki/CrossOriginRequestSecurity 37 | 38 | # 39 | # Header set Access-Control-Allow-Origin "*" 40 | # 41 | 42 | 43 | # ---------------------------------------------------------------------- 44 | # CORS-enabled images (@crossorigin) 45 | # ---------------------------------------------------------------------- 46 | 47 | # Send CORS headers if browsers request them; enabled by default for images. 48 | # developer.mozilla.org/en/CORS_Enabled_Image 49 | # blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html 50 | # hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ 51 | # wiki.mozilla.org/Security/Reviews/crossoriginAttribute 52 | 53 | 54 | 55 | # mod_headers, y u no match by Content-Type?! 56 | 57 | SetEnvIf Origin ":" IS_CORS 58 | Header set Access-Control-Allow-Origin "*" env=IS_CORS 59 | 60 | 61 | 62 | 63 | 64 | # ---------------------------------------------------------------------- 65 | # Webfont access 66 | # ---------------------------------------------------------------------- 67 | 68 | # Allow access from all domains for webfonts. 69 | # Alternatively you could only whitelist your 70 | # subdomains like "subdomain.example.com". 71 | 72 | 73 | 74 | Header set Access-Control-Allow-Origin "*" 75 | 76 | 77 | 78 | 79 | # ---------------------------------------------------------------------- 80 | # Proper MIME type for all files 81 | # ---------------------------------------------------------------------- 82 | 83 | # JavaScript 84 | # Normalize to standard type (it's sniffed in IE anyways) 85 | # tools.ietf.org/html/rfc4329#section-7.2 86 | AddType application/javascript js jsonp 87 | AddType application/json json 88 | 89 | # Audio 90 | AddType audio/ogg oga ogg 91 | AddType audio/mp4 m4a f4a f4b 92 | 93 | # Video 94 | AddType video/ogg ogv 95 | AddType video/mp4 mp4 m4v f4v f4p 96 | AddType video/webm webm 97 | AddType video/x-flv flv 98 | 99 | # SVG 100 | # Required for svg webfonts on iPad 101 | # twitter.com/FontSquirrel/status/14855840545 102 | AddType image/svg+xml svg svgz 103 | AddEncoding gzip svgz 104 | 105 | # Webfonts 106 | AddType application/vnd.ms-fontobject eot 107 | AddType application/x-font-ttf ttf ttc 108 | AddType font/opentype otf 109 | AddType application/x-font-woff woff 110 | 111 | # Assorted types 112 | AddType image/x-icon ico 113 | AddType image/webp webp 114 | AddType text/cache-manifest appcache manifest 115 | AddType text/x-component htc 116 | AddType application/xml rss atom xml rdf 117 | AddType application/x-chrome-extension crx 118 | AddType application/x-opera-extension oex 119 | AddType application/x-xpinstall xpi 120 | AddType application/octet-stream safariextz 121 | AddType application/x-web-app-manifest+json webapp 122 | AddType text/x-vcard vcf 123 | AddType application/x-shockwave-flash swf 124 | AddType text/vtt vtt 125 | 126 | 127 | # ---------------------------------------------------------------------- 128 | # Allow concatenation from within specific js and css files 129 | # ---------------------------------------------------------------------- 130 | 131 | # e.g. Inside of script.combined.js you could have 132 | # 133 | # 134 | # and they would be included into this single file. 135 | 136 | # This is not in use in the boilerplate as it stands. You may 137 | # choose to use this technique if you do not have a build process. 138 | 139 | # 140 | # Options +Includes 141 | # AddOutputFilterByType INCLUDES application/javascript application/json 142 | # SetOutputFilter INCLUDES 143 | # 144 | 145 | # 146 | # Options +Includes 147 | # AddOutputFilterByType INCLUDES text/css 148 | # SetOutputFilter INCLUDES 149 | # 150 | 151 | 152 | # ---------------------------------------------------------------------- 153 | # Gzip compression 154 | # ---------------------------------------------------------------------- 155 | 156 | 157 | 158 | # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/ 159 | 160 | 161 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding 162 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding 163 | 164 | 165 | 166 | # HTML, TXT, CSS, JavaScript, JSON, XML, HTC: 167 | 168 | FilterDeclare COMPRESS 169 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html 170 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css 171 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain 172 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml 173 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component 174 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript 175 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json 176 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml 177 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml 178 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml 179 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml 180 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject 181 | FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml 182 | FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon 183 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf 184 | FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype 185 | FilterChain COMPRESS 186 | FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no 187 | 188 | 189 | 190 | # Legacy versions of Apache 191 | AddOutputFilterByType DEFLATE text/html text/plain text/css application/json 192 | AddOutputFilterByType DEFLATE application/javascript 193 | AddOutputFilterByType DEFLATE text/xml application/xml text/x-component 194 | AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml 195 | AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype 196 | 197 | 198 | 199 | 200 | 201 | # ---------------------------------------------------------------------- 202 | # Expires headers (for better cache control) 203 | # ---------------------------------------------------------------------- 204 | 205 | # These are pretty far-future expires headers. 206 | # They assume you control versioning with filename-based cache busting 207 | # Additionally, consider that outdated proxies may miscache 208 | # www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ 209 | 210 | # If you don't use filenames to version, lower the CSS and JS to something like 211 | # "access plus 1 week". 212 | 213 | 214 | ExpiresActive on 215 | 216 | # Perhaps better to whitelist expires rules? Perhaps. 217 | ExpiresDefault "access plus 1 month" 218 | 219 | # cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5) 220 | ExpiresByType text/cache-manifest "access plus 0 seconds" 221 | 222 | # Your document html 223 | ExpiresByType text/html "access plus 0 seconds" 224 | 225 | # Data 226 | ExpiresByType text/xml "access plus 0 seconds" 227 | ExpiresByType application/xml "access plus 0 seconds" 228 | ExpiresByType application/json "access plus 0 seconds" 229 | 230 | # Feed 231 | ExpiresByType application/rss+xml "access plus 1 hour" 232 | ExpiresByType application/atom+xml "access plus 1 hour" 233 | 234 | # Favicon (cannot be renamed) 235 | ExpiresByType image/x-icon "access plus 1 week" 236 | 237 | # Media: images, video, audio 238 | ExpiresByType image/gif "access plus 1 month" 239 | ExpiresByType image/png "access plus 1 month" 240 | ExpiresByType image/jpeg "access plus 1 month" 241 | ExpiresByType video/ogg "access plus 1 month" 242 | ExpiresByType audio/ogg "access plus 1 month" 243 | ExpiresByType video/mp4 "access plus 1 month" 244 | ExpiresByType video/webm "access plus 1 month" 245 | 246 | # HTC files (css3pie) 247 | ExpiresByType text/x-component "access plus 1 month" 248 | 249 | # Webfonts 250 | ExpiresByType application/x-font-ttf "access plus 1 month" 251 | ExpiresByType font/opentype "access plus 1 month" 252 | ExpiresByType application/x-font-woff "access plus 1 month" 253 | ExpiresByType image/svg+xml "access plus 1 month" 254 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month" 255 | 256 | # CSS and JavaScript 257 | ExpiresByType text/css "access plus 1 year" 258 | ExpiresByType application/javascript "access plus 1 year" 259 | 260 | 261 | 262 | 263 | # ---------------------------------------------------------------------- 264 | # Prevent mobile network providers from modifying your site 265 | # ---------------------------------------------------------------------- 266 | 267 | # The following header prevents modification of your code over 3G on some 268 | # European providers. 269 | # This is the official 'bypass' suggested by O2 in the UK. 270 | 271 | # 272 | # Header set Cache-Control "no-transform" 273 | # 274 | 275 | 276 | # ---------------------------------------------------------------------- 277 | # ETag removal 278 | # ---------------------------------------------------------------------- 279 | 280 | # FileETag None is not enough for every server. 281 | 282 | Header unset ETag 283 | 284 | 285 | # Since we're sending far-future expires, we don't need ETags for 286 | # static content. 287 | # developer.yahoo.com/performance/rules.html#etags 288 | FileETag None 289 | 290 | 291 | # ---------------------------------------------------------------------- 292 | # Stop screen flicker in IE on CSS rollovers 293 | # ---------------------------------------------------------------------- 294 | 295 | # The following directives stop screen flicker in IE on CSS rollovers - in 296 | # combination with the "ExpiresByType" rules for images (see above). 297 | 298 | # BrowserMatch "MSIE" brokenvary=1 299 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 300 | # BrowserMatch "Opera" !brokenvary 301 | # SetEnvIf brokenvary 1 force-no-vary 302 | 303 | 304 | # ---------------------------------------------------------------------- 305 | # Set Keep-Alive Header 306 | # ---------------------------------------------------------------------- 307 | 308 | # Keep-Alive allows the server to send multiple requests through one 309 | # TCP-connection. Be aware of possible disadvantages of this setting. Turn on 310 | # if you serve a lot of static content. 311 | 312 | # 313 | # Header set Connection Keep-Alive 314 | # 315 | 316 | 317 | # ---------------------------------------------------------------------- 318 | # Cookie setting from iframes 319 | # ---------------------------------------------------------------------- 320 | 321 | # Allow cookies to be set from iframes (for IE only) 322 | # If needed, specify a path or regex in the Location directive. 323 | 324 | # 325 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" 326 | # 327 | 328 | 329 | # ---------------------------------------------------------------------- 330 | # Start rewrite engine 331 | # ---------------------------------------------------------------------- 332 | 333 | # Turning on the rewrite engine is necessary for the following rules and 334 | # features. FollowSymLinks must be enabled for this to work. 335 | 336 | # Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN 337 | # If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where 338 | # 'foo' is your directory. 339 | 340 | # If your web host doesn't allow the FollowSymlinks option, you may need to 341 | # comment it out and use `Options +SymLinksOfOwnerMatch`, but be aware of the 342 | # performance impact: http://goo.gl/Mluzd 343 | 344 | 345 | Options +FollowSymlinks 346 | # Options +SymLinksIfOwnerMatch 347 | Options +FollowSymlinks 348 | RewriteEngine On 349 | # RewriteBase / 350 | 351 | 352 | 353 | # ---------------------------------------------------------------------- 354 | # Suppress or force the "www." at the beginning of URLs 355 | # ---------------------------------------------------------------------- 356 | 357 | # The same content should never be available under two different URLs - 358 | # especially not with and without "www." at the beginning, since this can cause 359 | # SEO problems (duplicate content). That's why you should choose one of the 360 | # alternatives and redirect the other one. 361 | 362 | # By default option 1 (no "www.") is activated. 363 | # no-www.org/faq.php?q=class_b 364 | 365 | # If you'd prefer to use option 2, just comment out all option 1 lines 366 | # and uncomment option 2. 367 | 368 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! 369 | 370 | # ---------------------------------------------------------------------- 371 | 372 | # Option 1: 373 | # Rewrite "www.example.com -> example.com". 374 | 375 | 376 | RewriteCond %{HTTPS} !=on 377 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 378 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] 379 | 380 | 381 | # ---------------------------------------------------------------------- 382 | 383 | # Option 2: 384 | # Rewrite "example.com -> www.example.com". 385 | # Be aware that the following rule might not be a good idea if you use "real" 386 | # subdomains for certain parts of your website. 387 | 388 | # 389 | # RewriteCond %{HTTPS} !=on 390 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC] 391 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 392 | # 393 | 394 | 395 | # ---------------------------------------------------------------------- 396 | # Built-in filename-based cache busting 397 | # ---------------------------------------------------------------------- 398 | 399 | # If you're not using the build script to manage your filename version revving, 400 | # you might want to consider enabling this, which will route requests for 401 | # /css/style.20110203.css to /css/style.css 402 | 403 | # To understand why this is important and a better idea than all.css?v1231, 404 | # read: github.com/h5bp/html5-boilerplate/wiki/cachebusting 405 | 406 | # 407 | # RewriteCond %{REQUEST_FILENAME} !-f 408 | # RewriteCond %{REQUEST_FILENAME} !-d 409 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] 410 | # 411 | 412 | 413 | # ---------------------------------------------------------------------- 414 | # Prevent SSL cert warnings 415 | # ---------------------------------------------------------------------- 416 | 417 | # Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent 418 | # https://www.example.com when your cert only allows https://secure.example.com 419 | 420 | # 421 | # RewriteCond %{SERVER_PORT} !^443 422 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] 423 | # 424 | 425 | 426 | # ---------------------------------------------------------------------- 427 | # Prevent 404 errors for non-existing redirected folders 428 | # ---------------------------------------------------------------------- 429 | 430 | # without -MultiViews, Apache will give a 404 for a rewrite if a folder of the 431 | # same name does not exist. 432 | # webmasterworld.com/apache/3808792.htm 433 | 434 | Options -MultiViews 435 | 436 | 437 | # ---------------------------------------------------------------------- 438 | # Custom 404 page 439 | # ---------------------------------------------------------------------- 440 | 441 | # You can add custom pages to handle 500 or 403 pretty easily, if you like. 442 | # If you are hosting your site in subdirectory, adjust this accordingly 443 | # e.g. ErrorDocument 404 /subdir/404.html 444 | ErrorDocument 404 /404.html 445 | 446 | 447 | # ---------------------------------------------------------------------- 448 | # UTF-8 encoding 449 | # ---------------------------------------------------------------------- 450 | 451 | # Use UTF-8 encoding for anything served text/plain or text/html 452 | AddDefaultCharset utf-8 453 | 454 | # Force UTF-8 for a number of file formats 455 | AddCharset utf-8 .atom .css .js .json .rss .vtt .xml 456 | 457 | 458 | # ---------------------------------------------------------------------- 459 | # A little more security 460 | # ---------------------------------------------------------------------- 461 | 462 | # To avoid displaying the exact version number of Apache being used, add the 463 | # following to httpd.conf (it will not work in .htaccess): 464 | # ServerTokens Prod 465 | 466 | # "-Indexes" will have Apache block users from browsing folders without a 467 | # default document Usually you should leave this activated, because you 468 | # shouldn't allow everybody to surf through every folder on your server (which 469 | # includes rather private places like CMS system folders). 470 | 471 | Options -Indexes 472 | 473 | 474 | # Block access to "hidden" directories or files whose names begin with a 475 | # period. This includes directories used by version control systems such as 476 | # Subversion or Git. 477 | 478 | RewriteCond %{SCRIPT_FILENAME} -d [OR] 479 | RewriteCond %{SCRIPT_FILENAME} -f 480 | RewriteRule "(^|/)\." - [F] 481 | 482 | 483 | # Block access to backup and source files. These files may be left by some 484 | # text/html editors and pose a great security danger, when anyone can access 485 | # them. 486 | 487 | Order allow,deny 488 | Deny from all 489 | Satisfy All 490 | 491 | 492 | # If your server is not already configured as such, the following directive 493 | # should be uncommented in order to set PHP's register_globals option to OFF. 494 | # This closes a major security hole that is abused by most XSS (cross-site 495 | # scripting) attacks. For more information: http://php.net/register_globals 496 | # 497 | # IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS: 498 | # 499 | # Your server does not allow PHP directives to be set via .htaccess. In that 500 | # case you must make this change in your php.ini file instead. If you are 501 | # using a commercial web host, contact the administrators for assistance in 502 | # doing this. Not all servers allow local php.ini files, and they should 503 | # include all PHP configurations (not just this one), or you will effectively 504 | # reset everything to PHP defaults. Consult www.php.net for more detailed 505 | # information about setting PHP directives. 506 | 507 | # php_flag register_globals Off 508 | 509 | # Rename session cookie to something else, than PHPSESSID 510 | # php_value session.name sid 511 | 512 | # Disable magic quotes (This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.) 513 | # php_flag magic_quotes_gpc Off 514 | 515 | # Do not show you are using PHP 516 | # Note: Move this line to php.ini since it won't work in .htaccess 517 | # php_flag expose_php Off 518 | 519 | # Level of log detail - log all errors 520 | # php_value error_reporting -1 521 | 522 | # Write errors to log file 523 | # php_flag log_errors On 524 | 525 | # Do not display errors in browser (production - Off, development - On) 526 | # php_flag display_errors Off 527 | 528 | # Do not display startup errors (production - Off, development - On) 529 | # php_flag display_startup_errors Off 530 | 531 | # Format errors in plain text 532 | # Note: Leave this setting 'On' for xdebug's var_dump() output 533 | # php_flag html_errors Off 534 | 535 | # Show multiple occurrence of error 536 | # php_flag ignore_repeated_errors Off 537 | 538 | # Show same errors from different sources 539 | # php_flag ignore_repeated_source Off 540 | 541 | # Size limit for error messages 542 | # php_value log_errors_max_len 1024 543 | 544 | # Don't precede error with string (doesn't accept empty string, use whitespace if you need) 545 | # php_value error_prepend_string " " 546 | 547 | # Don't prepend to error (doesn't accept empty string, use whitespace if you need) 548 | # php_value error_append_string " " 549 | 550 | # Increase cookie security 551 | 552 | php_value session.cookie_httponly true 553 | 554 | -------------------------------------------------------------------------------- /app/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found :( 6 | 141 | 142 | 143 |
144 |

Not found :(

145 |

Sorry, but the page you were trying to view does not exist.

146 |

It looks like this was the result of either:

147 | 151 | 154 | 155 |
156 | 157 | 158 | -------------------------------------------------------------------------------- /app/cordova_plugins.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/favicon.ico -------------------------------------------------------------------------------- /app/images/backgrounds/gradient.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/backgrounds/gradient.jpg -------------------------------------------------------------------------------- /app/images/workouts/abdominal-crunch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/abdominal-crunch.png -------------------------------------------------------------------------------- /app/images/workouts/high-knees-running-in-place.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/high-knees-running-in-place.png -------------------------------------------------------------------------------- /app/images/workouts/jumping-jacks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/jumping-jacks.png -------------------------------------------------------------------------------- /app/images/workouts/lunge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/lunge.png -------------------------------------------------------------------------------- /app/images/workouts/plank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/plank.png -------------------------------------------------------------------------------- /app/images/workouts/push-up-and-rotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/push-up-and-rotation.png -------------------------------------------------------------------------------- /app/images/workouts/push-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/push-up.png -------------------------------------------------------------------------------- /app/images/workouts/side-plank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/side-plank.png -------------------------------------------------------------------------------- /app/images/workouts/squat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/squat.png -------------------------------------------------------------------------------- /app/images/workouts/step-up-onto-chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/step-up-onto-chair.png -------------------------------------------------------------------------------- /app/images/workouts/triceps-dip-on-chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/triceps-dip-on-chair.png -------------------------------------------------------------------------------- /app/images/workouts/wall-sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/images/workouts/wall-sit.png -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Seven Minute 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/libraries/angular-mobile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.1.5-2a7043f 3 | * (c) 2010-2012 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) { 7 | 'use strict'; 8 | 9 | /** 10 | * @ngdoc overview 11 | * @name ngMobile 12 | * @description 13 | * Touch events and other mobile helpers. 14 | * Based on jQuery Mobile touch event handling (jquerymobile.com) 15 | */ 16 | 17 | // define ngMobile module 18 | var ngMobile = angular.module('ngMobile', []); 19 | 20 | /** 21 | * @ngdoc directive 22 | * @name ngMobile.directive:ngClick 23 | * 24 | * @description 25 | * A more powerful replacement for the default ngClick designed to be used on touchscreen 26 | * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending 27 | * the click event. This version handles them immediately, and then prevents the 28 | * following click event from propagating. 29 | * 30 | * This directive can fall back to using an ordinary click event, and so works on desktop 31 | * browsers as well as mobile. 32 | * 33 | * This directive also sets the CSS class `ng-click-active` while the element is being held 34 | * down (by a mouse click or touch) so you can restyle the depressed element if you wish. 35 | * 36 | * @element ANY 37 | * @param {expression} ngClick {@link guide/expression Expression} to evaluate 38 | * upon tap. (Event object is available as `$event`) 39 | * 40 | * @example 41 | 42 | 43 | 46 | count: {{ count }} 47 | 48 | 49 | */ 50 | 51 | ngMobile.config(['$provide', function($provide) { 52 | $provide.decorator('ngClickDirective', ['$delegate', function($delegate) { 53 | // drop the default ngClick directive 54 | $delegate.shift(); 55 | return $delegate; 56 | }]); 57 | }]); 58 | 59 | ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement', 60 | function($parse, $timeout, $rootElement) { 61 | var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag. 62 | var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers. 63 | var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click 64 | var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks. 65 | 66 | var ACTIVE_CLASS_NAME = 'ng-click-active'; 67 | var lastPreventedTime; 68 | var touchCoordinates; 69 | 70 | 71 | // TAP EVENTS AND GHOST CLICKS 72 | // 73 | // Why tap events? 74 | // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're 75 | // double-tapping, and then fire a click event. 76 | // 77 | // This delay sucks and makes mobile apps feel unresponsive. 78 | // So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when 79 | // the user has tapped on something. 80 | // 81 | // What happens when the browser then generates a click event? 82 | // The browser, of course, also detects the tap and fires a click after a delay. This results in 83 | // tapping/clicking twice. So we do "clickbusting" to prevent it. 84 | // 85 | // How does it work? 86 | // We attach global touchstart and click handlers, that run during the capture (early) phase. 87 | // So the sequence for a tap is: 88 | // - global touchstart: Sets an "allowable region" at the point touched. 89 | // - element's touchstart: Starts a touch 90 | // (- touchmove or touchcancel ends the touch, no click follows) 91 | // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold 92 | // too long) and fires the user's tap handler. The touchend also calls preventGhostClick(). 93 | // - preventGhostClick() removes the allowable region the global touchstart created. 94 | // - The browser generates a click event. 95 | // - The global click handler catches the click, and checks whether it was in an allowable region. 96 | // - If preventGhostClick was called, the region will have been removed, the click is busted. 97 | // - If the region is still there, the click proceeds normally. Therefore clicks on links and 98 | // other elements without ngTap on them work normally. 99 | // 100 | // This is an ugly, terrible hack! 101 | // Yeah, tell me about it. The alternatives are using the slow click events, or making our users 102 | // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular 103 | // encapsulates this ugly logic away from the user. 104 | // 105 | // Why not just put click handlers on the element? 106 | // We do that too, just to be sure. The problem is that the tap event might have caused the DOM 107 | // to change, so that the click fires in the same position but something else is there now. So 108 | // the handlers are global and care only about coordinates and not elements. 109 | 110 | // Checks if the coordinates are close enough to be within the region. 111 | function hit(x1, y1, x2, y2) { 112 | return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD; 113 | } 114 | 115 | // Checks a list of allowable regions against a click location. 116 | // Returns true if the click should be allowed. 117 | // Splices out the allowable region from the list after it has been used. 118 | function checkAllowableRegions(touchCoordinates, x, y) { 119 | for (var i = 0; i < touchCoordinates.length; i += 2) { 120 | if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) { 121 | touchCoordinates.splice(i, i + 2); 122 | return true; // allowable region 123 | } 124 | } 125 | return false; // No allowable region; bust it. 126 | } 127 | 128 | // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick 129 | // was called recently. 130 | function onClick(event) { 131 | if (Date.now() - lastPreventedTime > PREVENT_DURATION) { 132 | return; // Too old. 133 | } 134 | 135 | var touches = event.touches && event.touches.length ? event.touches : [event]; 136 | var x = touches[0].clientX; 137 | var y = touches[0].clientY; 138 | // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label 139 | // and on the input element). Depending on the exact browser, this second click we don't want 140 | // to bust has either (0,0) or negative coordinates. 141 | if (x < 1 && y < 1) { 142 | return; // offscreen 143 | } 144 | 145 | // Look for an allowable region containing this click. 146 | // If we find one, that means it was created by touchstart and not removed by 147 | // preventGhostClick, so we don't bust it. 148 | if (checkAllowableRegions(touchCoordinates, x, y)) { 149 | return; 150 | } 151 | 152 | // If we didn't find an allowable region, bust the click. 153 | event.stopPropagation(); 154 | event.preventDefault(); 155 | } 156 | 157 | 158 | // Global touchstart handler that creates an allowable region for a click event. 159 | // This allowable region can be removed by preventGhostClick if we want to bust it. 160 | function onTouchStart(event) { 161 | var touches = event.touches && event.touches.length ? event.touches : [event]; 162 | var x = touches[0].clientX; 163 | var y = touches[0].clientY; 164 | touchCoordinates.push(x, y); 165 | 166 | $timeout(function() { 167 | // Remove the allowable region. 168 | for (var i = 0; i < touchCoordinates.length; i += 2) { 169 | if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) { 170 | touchCoordinates.splice(i, i + 2); 171 | return; 172 | } 173 | } 174 | }, PREVENT_DURATION, false); 175 | } 176 | 177 | // On the first call, attaches some event handlers. Then whenever it gets called, it creates a 178 | // zone around the touchstart where clicks will get busted. 179 | function preventGhostClick(x, y) { 180 | if (!touchCoordinates) { 181 | $rootElement[0].addEventListener('click', onClick, true); 182 | $rootElement[0].addEventListener('touchstart', onTouchStart, true); 183 | touchCoordinates = []; 184 | } 185 | 186 | lastPreventedTime = Date.now(); 187 | 188 | checkAllowableRegions(touchCoordinates, x, y); 189 | } 190 | 191 | // Actual linking function. 192 | return function(scope, element, attr) { 193 | var clickHandler = $parse(attr.ngClick), 194 | tapping = false, 195 | tapElement, // Used to blur the element after a tap. 196 | startTime, // Used to check if the tap was held too long. 197 | touchStartX, 198 | touchStartY; 199 | 200 | function resetState() { 201 | tapping = false; 202 | element.removeClass(ACTIVE_CLASS_NAME); 203 | } 204 | 205 | element.bind('touchstart', function(event) { 206 | tapping = true; 207 | tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement. 208 | // Hack for Safari, which can target text nodes instead of containers. 209 | if(tapElement.nodeType == 3) { 210 | tapElement = tapElement.parentNode; 211 | } 212 | 213 | element.addClass(ACTIVE_CLASS_NAME); 214 | 215 | startTime = Date.now(); 216 | 217 | var touches = event.touches && event.touches.length ? event.touches : [event]; 218 | var e = touches[0].originalEvent || touches[0]; 219 | touchStartX = e.clientX; 220 | touchStartY = e.clientY; 221 | }); 222 | 223 | element.bind('touchmove', function(event) { 224 | resetState(); 225 | }); 226 | 227 | element.bind('touchcancel', function(event) { 228 | resetState(); 229 | }); 230 | 231 | element.bind('touchend', function(event) { 232 | var diff = Date.now() - startTime; 233 | 234 | var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches : 235 | ((event.touches && event.touches.length) ? event.touches : [event]); 236 | var e = touches[0].originalEvent || touches[0]; 237 | var x = e.clientX; 238 | var y = e.clientY; 239 | var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) ); 240 | 241 | if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) { 242 | // Call preventGhostClick so the clickbuster will catch the corresponding click. 243 | preventGhostClick(x, y); 244 | 245 | // Blur the focused element (the button, probably) before firing the callback. 246 | // This doesn't work perfectly on Android Chrome, but seems to work elsewhere. 247 | // I couldn't get anything to work reliably on Android Chrome. 248 | if (tapElement) { 249 | tapElement.blur(); 250 | } 251 | 252 | scope.$apply(function() { 253 | // TODO(braden): This is sending the touchend, not a tap or click. Is that kosher? 254 | clickHandler(scope, {$event: event}); 255 | }); 256 | } 257 | 258 | resetState(); 259 | }); 260 | 261 | // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click 262 | // something else nearby. 263 | element.onclick = function(event) { }; 264 | 265 | // Fallback click handler. 266 | // Busted clicks don't get this far, and adding this handler allows ng-tap to be used on 267 | // desktop as well, to allow more portable sites. 268 | element.bind('click', function(event) { 269 | scope.$apply(function() { 270 | clickHandler(scope, {$event: event}); 271 | }); 272 | }); 273 | 274 | element.bind('mousedown', function(event) { 275 | element.addClass(ACTIVE_CLASS_NAME); 276 | }); 277 | 278 | element.bind('mousemove mouseup', function(event) { 279 | element.removeClass(ACTIVE_CLASS_NAME); 280 | }); 281 | 282 | }; 283 | }]); 284 | 285 | /** 286 | * @ngdoc directive 287 | * @name ngMobile.directive:ngSwipeLeft 288 | * 289 | * @description 290 | * Specify custom behavior when an element is swiped to the left on a touchscreen device. 291 | * A leftward swipe is a quick, right-to-left slide of the finger. 292 | * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag too. 293 | * 294 | * @element ANY 295 | * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate 296 | * upon left swipe. (Event object is available as `$event`) 297 | * 298 | * @example 299 | 300 | 301 |
302 | Some list content, like an email in the inbox 303 |
304 |
305 | 306 | 307 |
308 |
309 |
310 | */ 311 | 312 | /** 313 | * @ngdoc directive 314 | * @name ngMobile.directive:ngSwipeRight 315 | * 316 | * @description 317 | * Specify custom behavior when an element is swiped to the right on a touchscreen device. 318 | * A rightward swipe is a quick, left-to-right slide of the finger. 319 | * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag too. 320 | * 321 | * @element ANY 322 | * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate 323 | * upon right swipe. (Event object is available as `$event`) 324 | * 325 | * @example 326 | 327 | 328 |
329 | Some list content, like an email in the inbox 330 |
331 |
332 | 333 | 334 |
335 |
336 |
337 | */ 338 | 339 | function makeSwipeDirective(directiveName, direction) { 340 | ngMobile.directive(directiveName, ['$parse', function($parse) { 341 | // The maximum vertical delta for a swipe should be less than 75px. 342 | var MAX_VERTICAL_DISTANCE = 75; 343 | // Vertical distance should not be more than a fraction of the horizontal distance. 344 | var MAX_VERTICAL_RATIO = 0.3; 345 | // At least a 30px lateral motion is necessary for a swipe. 346 | var MIN_HORIZONTAL_DISTANCE = 30; 347 | // The total distance in any direction before we make the call on swipe vs. scroll. 348 | var MOVE_BUFFER_RADIUS = 10; 349 | 350 | function getCoordinates(event) { 351 | var touches = event.touches && event.touches.length ? event.touches : [event]; 352 | var e = (event.changedTouches && event.changedTouches[0]) || 353 | (event.originalEvent && event.originalEvent.changedTouches && 354 | event.originalEvent.changedTouches[0]) || 355 | touches[0].originalEvent || touches[0]; 356 | 357 | return { 358 | x: e.clientX, 359 | y: e.clientY 360 | }; 361 | } 362 | 363 | return function(scope, element, attr) { 364 | var swipeHandler = $parse(attr[directiveName]); 365 | var startCoords, valid; 366 | var totalX, totalY; 367 | var lastX, lastY; 368 | 369 | function validSwipe(event) { 370 | // Check that it's within the coordinates. 371 | // Absolute vertical distance must be within tolerances. 372 | // Horizontal distance, we take the current X - the starting X. 373 | // This is negative for leftward swipes and positive for rightward swipes. 374 | // After multiplying by the direction (-1 for left, +1 for right), legal swipes 375 | // (ie. same direction as the directive wants) will have a positive delta and 376 | // illegal ones a negative delta. 377 | // Therefore this delta must be positive, and larger than the minimum. 378 | if (!startCoords) return false; 379 | var coords = getCoordinates(event); 380 | var deltaY = Math.abs(coords.y - startCoords.y); 381 | var deltaX = (coords.x - startCoords.x) * direction; 382 | return valid && // Short circuit for already-invalidated swipes. 383 | deltaY < MAX_VERTICAL_DISTANCE && 384 | deltaX > 0 && 385 | deltaX > MIN_HORIZONTAL_DISTANCE && 386 | deltaY / deltaX < MAX_VERTICAL_RATIO; 387 | } 388 | 389 | element.bind('touchstart mousedown', function(event) { 390 | startCoords = getCoordinates(event); 391 | valid = true; 392 | totalX = 0; 393 | totalY = 0; 394 | lastX = startCoords.x; 395 | lastY = startCoords.y; 396 | }); 397 | 398 | element.bind('touchcancel', function(event) { 399 | valid = false; 400 | }); 401 | 402 | element.bind('touchmove mousemove', function(event) { 403 | if (!valid) return; 404 | 405 | // Android will send a touchcancel if it thinks we're starting to scroll. 406 | // So when the total distance (+ or - or both) exceeds 10px in either direction, 407 | // we either: 408 | // - On totalX > totalY, we send preventDefault() and treat this as a swipe. 409 | // - On totalY > totalX, we let the browser handle it as a scroll. 410 | 411 | // Invalidate a touch while it's in progress if it strays too far away vertically. 412 | // We don't want a scroll down and back up while drifting sideways to be a swipe just 413 | // because you happened to end up vertically close in the end. 414 | if (!startCoords) return; 415 | var coords = getCoordinates(event); 416 | 417 | if (Math.abs(coords.y - startCoords.y) > MAX_VERTICAL_DISTANCE) { 418 | valid = false; 419 | return; 420 | } 421 | 422 | totalX += Math.abs(coords.x - lastX); 423 | totalY += Math.abs(coords.y - lastY); 424 | 425 | lastX = coords.x; 426 | lastY = coords.y; 427 | 428 | if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) { 429 | return; 430 | } 431 | 432 | // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll. 433 | if (totalY > totalX) { 434 | valid = false; 435 | return; 436 | } else { 437 | event.preventDefault(); 438 | } 439 | }); 440 | 441 | element.bind('touchend mouseup', function(event) { 442 | if (validSwipe(event)) { 443 | // Prevent this swipe from bubbling up to any other elements with ngSwipes. 444 | event.stopPropagation(); 445 | scope.$apply(function() { 446 | swipeHandler(scope, {$event:event}); 447 | }); 448 | } 449 | }); 450 | }; 451 | }]); 452 | } 453 | 454 | // Left is negative X-coordinate, right is positive. 455 | makeSwipeDirective('ngSwipeLeft', -1); 456 | makeSwipeDirective('ngSwipeRight', 1); 457 | 458 | 459 | 460 | })(window, window.angular); 461 | -------------------------------------------------------------------------------- /app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /app/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* global FastClick */ 3 | 4 | angular.$debug = true; 5 | 6 | var userAgent = navigator.userAgent.toLowerCase(); 7 | if(false && /(ipad|iphone)/.test(userAgent)) { 8 | document.addEventListener('deviceready', function() { 9 | angular.bootstrap(document, ['$app']); 10 | }, false); 11 | } else { 12 | setTimeout(function() { 13 | angular.bootstrap(document, ['$app']); 14 | }); 15 | } 16 | 17 | angular.module('$app', [/*'ngMobile', */'ajoslin.mobile-navigate', 'cordova.analytics']) 18 | 19 | .service('console', function($window) { 20 | return angular.$debug ? $window.console : {log: function() {}, warn: function() {}, error: function() {}}; 21 | }) 22 | 23 | .constant('workouts', [ 24 | {id:'jumping-jacks', name: 'Jumping Jacks'}, 25 | {id:'wall-sit', name: 'Wall Sit'}, 26 | {id:'push-up', name: 'Push Up'}, 27 | {id:'abdominal-crunch', name: 'Abdominal Crunch'}, 28 | {id:'step-up-onto-chair', name: 'Step-Up onto Chair'}, 29 | {id:'squat', name: 'Squat'}, 30 | {id:'triceps-dip-on-chair', name: 'Triceps Dip on Chair'}, 31 | {id:'plank', name: 'Plank'}, 32 | {id:'high-knees-running-in-place', name: 'High Knees Running in Place'}, 33 | {id:'lunge', name: 'Lunge'}, 34 | {id:'push-up-and-rotation', name: 'Push-up and Rotation'}, 35 | {id:'side-plank', name: 'Side Plank'} 36 | ]) 37 | 38 | .value('workout', { 39 | duration: 420, 40 | rest: { 41 | name: 'Rest', 42 | time: 0.25 43 | }, 44 | list: ['jumping-jacks', 'wall-sit', 'push-up', 'abdominal-crunch', 'step-up-onto-chair', 'squat', 'triceps-dip-on-chair', 'plank', 'high-knees-running-in-place', 'lunge', 'push-up-and-rotation', 'side-plank'] 45 | }) 46 | 47 | .config(function ($routeProvider) { 48 | $routeProvider 49 | .when('/', { 50 | templateUrl: 'views/main.html', 51 | controller: 'MainCtrl' 52 | }) 53 | .when('/step/:step', { 54 | templateUrl: 'views/step.html', 55 | controller: 'StepsCtrl' 56 | }) 57 | .when('/rest/:step', { 58 | templateUrl: 'views/rest.html', 59 | controller: 'RestCtrl' 60 | }) 61 | .when('/done', { 62 | templateUrl: 'views/done.html', 63 | controller: 'MainCtrl' 64 | }) 65 | .otherwise({ 66 | redirectTo: '/' 67 | }); 68 | }) 69 | 70 | .run(function(console, $rootScope, $location, $navigate, $route, $analytics) { 71 | $rootScope.$location = $location; 72 | $rootScope.$navigate = $navigate; 73 | 74 | $analytics.init('UA-1813303-9', 10); 75 | $analytics.trackEvent('application', 'start'); 76 | 77 | setTimeout(function() { 78 | navigator.splashscreen && navigator.splashscreen.hide(); 79 | }, 150); 80 | 81 | }); 82 | 83 | // FastClick 84 | window.addEventListener('load', function() { 85 | new FastClick(document.body); 86 | }, false); -------------------------------------------------------------------------------- /app/scripts/controllers/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('$app') 4 | 5 | .controller('AppCtrl', function($scope, $location, $navigate, $routeParams, $countdown, audioFiles, workouts, workout) { 6 | 7 | $scope.exit = function() { 8 | $navigate.go('/', 'cubeToLeft'); 9 | }; 10 | 11 | }) 12 | 13 | .controller('MainCtrl', function($scope, $location, $navigate, $routeParams, $countdown, $analytics, audioFiles, workouts, workout) { 14 | 15 | $scope.timer = 3; 16 | $scope.next = '/step/1'; 17 | $scope.countdown = false; 18 | $scope.workout = workout; 19 | 20 | $scope.startText = function() { 21 | return $scope.countdown ? $scope.timer : 'Start'; 22 | }; 23 | 24 | $scope.start = function() { 25 | audioFiles.play('tick'); 26 | $scope.countdown = $countdown({scope: $scope, prop: 'timer', duration: 3, tick: function() { audioFiles.play('tick'); }, callback: function() { 27 | audioFiles.play('start'); 28 | $navigate.go($scope.next, 'glueTopFromBottom'); // cubeToLeft 29 | }}); 30 | $analytics.trackEvent('workout', 'start'); 31 | }; 32 | 33 | $scope.restart = function() { 34 | audioFiles.play('skip'); 35 | $navigate.go($scope.next, 'glueTopFromBottom'); // cubeToLeft 36 | $analytics.trackEvent('workout', 'restart'); 37 | }; 38 | 39 | $scope.minus = function() { 40 | if(workout.duration <= 240) return; 41 | workout.duration -= 60; 42 | }; 43 | $scope.plus = function() { 44 | if(workout.duration >= 1200) return; 45 | workout.duration += 60; 46 | }; 47 | 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /app/scripts/controllers/rest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('$app') 4 | 5 | .controller('RestCtrl', function($scope, $location, $navigate, $routeParams, $countdown, audioFiles, workouts, workout) { 6 | $scope.step = $routeParams.step * 1; 7 | $scope.total = workout.list.length; 8 | $scope.next = '/step/' + ($scope.step + 1); 9 | 10 | $scope.rest = workout.rest; 11 | var workoutId = workout.list[$scope.step]; 12 | $scope.workout = workouts.filter(function(workout) { return workout.id === workoutId; }).pop(); 13 | 14 | $scope.duration = parseInt((workout.duration / workout.list.length) * (workout.rest.time), 10); 15 | $scope.timer = $scope.duration; 16 | var countdown = $countdown({scope: $scope, prop: 'timer', duration: $scope.duration, tick: function() { audioFiles.play('rest'); }, callback: function() { 17 | audioFiles.play('start'); 18 | $scope.skip(); 19 | }}); 20 | 21 | $scope.paused = false; 22 | $scope.pauseText = function() { 23 | return $scope.paused ? 'Play' : 'Pause'; 24 | }; 25 | $scope.pause = function() { 26 | audioFiles.play('skip'); 27 | countdown.toggle(); 28 | $scope.paused = !$scope.paused; 29 | }; 30 | $scope.skip = function() { 31 | audioFiles.play('skip'); 32 | $navigate.go($scope.next, 'glueBottomFromTop'); 33 | }; 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /app/scripts/controllers/steps.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('$app') 4 | 5 | .controller('StepsCtrl', function($scope, $location, $navigate, $routeParams, $countdown, $analytics, audioFiles, workouts, workout) { 6 | $scope.step = $routeParams.step * 1; 7 | $scope.total = workout.list.length; 8 | $scope.next = $scope.step < $scope.total ? '/rest/' + $scope.step : '/done'; 9 | 10 | var workoutId = workout.list[$scope.step - 1]; 11 | $scope.workout = workouts.filter(function(workout) { return workout.id === workoutId; }).pop(); 12 | 13 | $scope.duration = parseInt((workout.duration / $scope.total) * (1 - workout.rest.time), 10); 14 | $scope.timer = $scope.duration; 15 | var countdown = $countdown({scope: $scope, prop: 'timer', duration: $scope.duration, tick: function() { audioFiles.play('tick'); }, callback: function() { 16 | audioFiles.play('stop'); 17 | $scope.skip(); 18 | }}); 19 | 20 | $scope.paused = false; 21 | $scope.pauseText = function() { 22 | return $scope.paused ? 'Play' : 'Pause'; 23 | }; 24 | $scope.pause = function() { 25 | audioFiles.play('skip'); 26 | countdown.toggle(); 27 | $scope.paused = !$scope.paused; 28 | }; 29 | $scope.skipText = function() { 30 | return $scope.paused ? 'Restart' : 'Skip'; 31 | }; 32 | $scope.skip = function() { 33 | audioFiles.play('skip'); 34 | if($scope.paused) { 35 | $scope.timer = $scope.duration; 36 | $scope.pause(); 37 | } else { 38 | $navigate.go($scope.next, 'glueTopFromBottom'); // cubeToLeft 39 | } 40 | $analytics.trackEvent('workout', 'skip'); 41 | }; 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /app/scripts/filters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('$app') 4 | 5 | .constant('numbers', { 6 | ones: ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'], 7 | tens: ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'], 8 | teens: ['ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'] 9 | }) 10 | 11 | .filter('firstWord', function() { 12 | return function(obj) { 13 | return obj.split(' ').shift(); 14 | }; 15 | }) 16 | 17 | .filter('followingWords', function() { 18 | return function(obj) { 19 | return obj.split(' ').slice(1).join(' '); 20 | }; 21 | }) 22 | 23 | .filter('numberAsText', function(numbers) { 24 | return function(num) { 25 | if(!num) return 'zero'; 26 | if (num < 10) return numbers.ones[num]; 27 | else if (num >= 10 && num < 20) return numbers.teens[num - 10]; 28 | else return numbers.tens[Math.floor(num / 10)] + ' ' + numbers.ones[num % 10]; 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /app/scripts/plugins/cordova-analytics.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cordova.analytics', []) 4 | 5 | .service('$analytics', function($window, $q) { 6 | 7 | var qExec = function(name, args) { 8 | var deferred = $q.defer(); 9 | if(!$window.cordova || ! $window.cordova.exec) return; 10 | $window.cordova.exec(function onSuccess(res) { 11 | deferred.resolve(res); 12 | }, function onError(err) { 13 | deferred.reject(err); 14 | }, 'GAPlugin', name, args); 15 | return deferred.promise; 16 | }; 17 | 18 | // id = the GA account ID of the form 'UA-00000000-0' 19 | // period = the minimum interval for transmitting tracking events if any exist in the queue 20 | this.init = function(id, period) { 21 | return qExec('initGA', [id, period || 10]); 22 | }; 23 | 24 | // category = The event category. This parameter is required to be non-empty. 25 | // eventAction = The event action. This parameter is required to be non-empty. 26 | // eventLabel = The event label. This parameter may be a blank string to indicate no label. 27 | // eventValue = The event value. This parameter may be -1 to indicate no value. 28 | this.trackEvent = function(category, eventAction, eventLabel, eventValue) { 29 | return qExec('trackEvent', [category, eventAction, eventLabel || '', eventValue || -1]); 30 | }; 31 | 32 | // url = the URL of the page view 33 | this.trackPage = function(url) { 34 | return qExec('trackPage', [url]); 35 | }; 36 | 37 | // index = the numerical index of the dimension to which this variable will be assigned (1 - 20) 38 | // value = the value of the variable you are logging 39 | this.setVariable = function(index, value) { 40 | return qExec('setVariable', [index, value]); 41 | }; 42 | 43 | this.destroy = function(index, value) { 44 | return qExec('exitGA', []); 45 | }; 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /app/scripts/services.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('$app') 4 | 5 | .service('audioFiles', function($window) { 6 | 7 | var Audio = $window.Media || $window.Audio; 8 | 9 | var files = { 10 | tick: {src: './sounds/tick.wav', volume: 0.35}, 11 | rest: {src: './sounds/tick-rest.wav', volume: 0.05}, 12 | start: {src: './sounds/newmail.wav', volume: 0.75}, 13 | stop: {src: './sounds/mailsent.wav', volume: 0.75}, 14 | skip: {src: './sounds/mailerror.wav', volume: 1}, 15 | }; 16 | 17 | angular.forEach(files, function(file) { 18 | file.audio = new Audio(file.src); 19 | if(file.volume) file.audio.volume = file.volume; 20 | }); 21 | 22 | this.play = function(file) { 23 | if(!files[file]) return false; 24 | files[file].audio.play(); 25 | }; 26 | 27 | }) 28 | 29 | .factory('$countdown', function() { 30 | 31 | function CountdownFactory(options) { 32 | 33 | var defaults = { 34 | interval: 1000 35 | }; 36 | 37 | var Countdown = function(options) { 38 | this.options = angular.extend({}, defaults, options); 39 | return this.init(options); 40 | }; 41 | 42 | Countdown.prototype = { 43 | 44 | constructor: Countdown, 45 | 46 | init: function(initOptions) { 47 | 48 | var that = this, 49 | options = this.options, 50 | $scope = this.options.scope; 51 | 52 | $scope[options.prop] = parseInt(options.duration || $scope[options.prop], 10); 53 | 54 | this.start(); 55 | $scope.$on('$destroy', function() { 56 | that.stop(); 57 | }); 58 | 59 | return this; 60 | 61 | }, 62 | 63 | toggle: function() { 64 | 65 | var that = this, 66 | options = this.options, 67 | $scope = this.options.scope; 68 | 69 | if(!$scope[options.prop]) return; 70 | this.interval ? this.stop() : this.start(); 71 | }, 72 | 73 | start: function() { 74 | 75 | var that = this, 76 | options = this.options, 77 | $scope = this.options.scope; 78 | 79 | this.interval = setInterval(function() { 80 | $scope.$apply(function() { 81 | $scope[options.prop]--; 82 | if(!$scope[options.prop]) { 83 | that.stop(); 84 | if(angular.isFunction(options.callback)) { 85 | options.callback.call(null); 86 | } 87 | } else { 88 | if(angular.isFunction(options.tick)) { 89 | options.tick.call(null); 90 | } 91 | } 92 | }); 93 | }, options.interval); 94 | }, 95 | 96 | stop: function() { 97 | clearInterval(this.interval); 98 | this.interval = undefined; 99 | } 100 | 101 | }; 102 | 103 | return new Countdown(options); 104 | 105 | } 106 | 107 | return CountdownFactory; 108 | 109 | }); -------------------------------------------------------------------------------- /app/sounds/mailerror.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/sounds/mailerror.wav -------------------------------------------------------------------------------- /app/sounds/mailsent.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/sounds/mailsent.wav -------------------------------------------------------------------------------- /app/sounds/newmail.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/sounds/newmail.wav -------------------------------------------------------------------------------- /app/sounds/tick-rest.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/sounds/tick-rest.wav -------------------------------------------------------------------------------- /app/sounds/tick.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/sounds/tick.wav -------------------------------------------------------------------------------- /app/styles/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/styles/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/styles/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/styles/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/styles/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/styles/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/styles/fonts/satisfy-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/styles/fonts/satisfy-webfont.ttf -------------------------------------------------------------------------------- /app/styles/fonts/satisfy-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/app/styles/fonts/satisfy-webfont.woff -------------------------------------------------------------------------------- /app/styles/includes/animations.less: -------------------------------------------------------------------------------- 1 | @import "page-transitions.less"; 2 | 3 | .pt-page-ontop { 4 | z-index: 999; 5 | } 6 | 7 | @-webkit-keyframes fadeIn { 8 | 0% {opacity: 0;} 9 | 100% {opacity: 1;} 10 | } 11 | @-moz-keyframes fadeIn { 12 | 0% {opacity: 0;} 13 | 100% {opacity: 1;} 14 | } 15 | @keyframes fadeIn { 16 | 0% {opacity: 0;} 17 | 100% {opacity: 1;} 18 | } 19 | .fadeIn { 20 | -webkit-animation: fadeIn .6s ease both; 21 | -moz-animation: fadeIn .6s ease both; 22 | animation: fadeIn .6s ease both; 23 | } 24 | .fadeInDelay { 25 | .fadeIn; 26 | .pt-page-delay1000; 27 | } 28 | 29 | 30 | // glueTopFromBottom 31 | // outClass = 'pt-page-rotateTopSideFirst'; 32 | // inClass = 'pt-page-moveFromTop pt-page-delay200 pt-page-ontop'; 33 | .mb-glueTopFromBottom { 34 | &.mb-out { 35 | .pt-page-rotateTopSideFirst; 36 | } 37 | &.mb-in { 38 | .pt-page-moveFromTop; 39 | .pt-page-delay200; 40 | .pt-page-ontop; 41 | } 42 | } 43 | 44 | // glueBottomFromTop 45 | // outClass = 'pt-page-rotateBottomSideFirst'; 46 | // inClass = 'pt-page-moveFromBottom pt-page-delay200 pt-page-ontop'; 47 | .mb-glueBottomFromTop { 48 | &.mb-out { 49 | .pt-page-rotateBottomSideFirst; 50 | } 51 | &.mb-in { 52 | .pt-page-moveFromBottom; 53 | .pt-page-delay200; 54 | .pt-page-ontop; 55 | } 56 | } 57 | 58 | // pushTopFromBottom 59 | // outClass = 'pt-page-rotatePushTop'; 60 | // inClass = 'pt-page-moveFromBottom'; 61 | .mb-pushTopFromBottom { 62 | &.mb-out { 63 | .pt-page-rotatePushTop; 64 | } 65 | &.mb-in { 66 | .pt-page-moveFromBottom; 67 | } 68 | } 69 | 70 | // cubeToLeft 71 | .mb-cubeToLeft { 72 | &.mb-out { 73 | .pt-page-rotateCubeLeftOut; 74 | .pt-page-ontop; 75 | } 76 | &.mb-in { 77 | .pt-page-rotateCubeLeftIn; 78 | } 79 | } 80 | // outClass = 'pt-page-rotateCubeLeftOut pt-page-ontop'; 81 | // inClass = 'pt-page-rotateCubeLeftIn'; 82 | 83 | // @-webkit-keyframes slideInFromRight { 84 | // 0% { -webkit-transform: translate3d(100%, 0, 0); } 85 | // 100% { -webkit-transform: translate3d(0, 0, 0); } 86 | // } 87 | // @-webkit-keyframes slideOutToRight { 88 | // 0% { -webkit-transform: translate3d(0, 0, 0); } 89 | // 100% { -webkit-transform: translate3d(100%, 0, 0); } 90 | // } 91 | // @-webkit-keyframes slideInFromLeft { 92 | // 0% { -webkit-transform: translate3d(-100%,0,0); } 93 | // 100% { -webkit-transform: translate3d(0, 0, 0); } 94 | // } 95 | // @-webkit-keyframes slideOutToLeft { 96 | // 0% { -webkit-transform: translate3d(0,0,0); } 97 | // 100% { -webkit-transform: translate3d(-100%, 0, 0); } 98 | // } 99 | // .mb-slide { 100 | // -webkit-animation-duration: 0.3s; 101 | // -webkit-animation-timing-function: ease; 102 | // } 103 | // .mb-slide.mb-in { 104 | // -webkit-animation-name: slideInFromRight; 105 | // } 106 | // .mb-slide.mb-in.mb-reverse { 107 | // -webkit-animation-name: slideOutToRight; 108 | // -webkit-transform: translate3d(100%, 0, 0); 109 | // } 110 | // .mb-slide.mb-out { 111 | // -webkit-animation-name: slideOutToLeft; 112 | // -webkit-transform: translate3d(-100%, 0, 0); 113 | // } 114 | // .mb-slide.mb-out.mb-reverse { 115 | // -webkit-animation-name: slideInFromLeft; 116 | // } 117 | -------------------------------------------------------------------------------- /app/styles/includes/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 3.1.0 3 | * the iconic font designed for Bootstrap 4 | * ------------------------------------------------------- 5 | * The full suite of pictographic icons, examples, and documentation 6 | * can be found at: http://fontawesome.io 7 | * 8 | * License 9 | * ------------------------------------------------------- 10 | * - The Font Awesome font is licensed under the SIL Open Font License v1.1 - 11 | * http://scripts.sil.org/OFL 12 | * - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License - 13 | * http://opensource.org/licenses/mit-license.html 14 | * - Font Awesome documentation licensed under CC BY 3.0 License - 15 | * http://creativecommons.org/licenses/by/3.0/ 16 | * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: 17 | * "Font Awesome by Dave Gandy - http://fontawesome.io" 18 | 19 | * Contact 20 | * ------------------------------------------------------- 21 | * Email: dave@fontawesome.io 22 | * Twitter: http://twitter.com/fortaweso_me 23 | * Work: Lead Product Designer @ http://kyruus.com 24 | */ 25 | /* FONT PATH 26 | * -------------------------- */ 27 | @font-face { 28 | font-family: 'FontAwesome'; 29 | src: url('./fonts/fontawesome-webfont.eot?v=3.1.0'); 30 | src: url('./fonts/fontawesome-webfont.eot?#iefix&v=3.1.0') format('embedded-opentype'), url('./fonts/fontawesome-webfont.woff?v=3.1.0') format('woff'), url('./fonts/fontawesome-webfont.ttf?v=3.1.0') format('truetype'), url('./fonts/fontawesome-webfont.svg#fontawesomeregular?v=3.1.0') format('svg'); 31 | font-weight: normal; 32 | font-style: normal; 33 | } 34 | /* FONT AWESOME CORE 35 | * -------------------------- */ 36 | [class^="icon-"], 37 | [class*=" icon-"] { 38 | font-family: FontAwesome; 39 | font-weight: normal; 40 | font-style: normal; 41 | text-decoration: inherit; 42 | -webkit-font-smoothing: antialiased; 43 | *margin-right: .3em; 44 | } 45 | [class^="icon-"]:before, 46 | [class*=" icon-"]:before { 47 | text-decoration: inherit; 48 | display: inline-block; 49 | speak: none; 50 | } 51 | /* makes the font 33% larger relative to the icon container */ 52 | .icon-large:before { 53 | vertical-align: -10%; 54 | font-size: 1.3333333333333333em; 55 | } 56 | /* makes sure icons active on rollover in links */ 57 | a [class^="icon-"], 58 | a [class*=" icon-"], 59 | a [class^="icon-"]:before, 60 | a [class*=" icon-"]:before { 61 | display: inline; 62 | } 63 | /* increased font size for icon-large */ 64 | [class^="icon-"].icon-fixed-width, 65 | [class*=" icon-"].icon-fixed-width { 66 | display: inline-block; 67 | width: 1.2857142857142858em; 68 | text-align: center; 69 | } 70 | [class^="icon-"].icon-fixed-width.icon-large, 71 | [class*=" icon-"].icon-fixed-width.icon-large { 72 | width: 1.5714285714285714em; 73 | } 74 | ul.icons-ul { 75 | list-style-type: none; 76 | text-indent: -0.7142857142857143em; 77 | margin-left: 2.142857142857143em; 78 | } 79 | ul.icons-ul > li .icon-li { 80 | width: 0.7142857142857143em; 81 | display: inline-block; 82 | text-align: center; 83 | } 84 | [class^="icon-"].hide, 85 | [class*=" icon-"].hide { 86 | display: none; 87 | } 88 | .icon-muted { 89 | color: #eeeeee; 90 | } 91 | .icon-light { 92 | color: #ffffff; 93 | } 94 | .icon-dark { 95 | color: #333333; 96 | } 97 | .icon-border { 98 | border: solid 1px #eeeeee; 99 | padding: .2em .25em .15em; 100 | -webkit-border-radius: 3px; 101 | -moz-border-radius: 3px; 102 | border-radius: 3px; 103 | } 104 | .icon-2x { 105 | font-size: 2em; 106 | } 107 | .icon-2x.icon-border { 108 | border-width: 2px; 109 | -webkit-border-radius: 4px; 110 | -moz-border-radius: 4px; 111 | border-radius: 4px; 112 | } 113 | .icon-3x { 114 | font-size: 3em; 115 | } 116 | .icon-3x.icon-border { 117 | border-width: 3px; 118 | -webkit-border-radius: 5px; 119 | -moz-border-radius: 5px; 120 | border-radius: 5px; 121 | } 122 | .icon-4x { 123 | font-size: 4em; 124 | } 125 | .icon-4x.icon-border { 126 | border-width: 4px; 127 | -webkit-border-radius: 6px; 128 | -moz-border-radius: 6px; 129 | border-radius: 6px; 130 | } 131 | .icon-5x { 132 | font-size: 5em; 133 | } 134 | .icon-5x.icon-border { 135 | border-width: 5px; 136 | -webkit-border-radius: 7px; 137 | -moz-border-radius: 7px; 138 | border-radius: 7px; 139 | } 140 | .pull-right { 141 | float: right; 142 | } 143 | .pull-left { 144 | float: left; 145 | } 146 | [class^="icon-"].pull-left, 147 | [class*=" icon-"].pull-left { 148 | margin-right: .3em; 149 | } 150 | [class^="icon-"].pull-right, 151 | [class*=" icon-"].pull-right { 152 | margin-left: .3em; 153 | } 154 | /* BOOTSTRAP SPECIFIC CLASSES 155 | * -------------------------- */ 156 | /* Bootstrap 2.0 sprites.less reset */ 157 | [class^="icon-"], 158 | [class*=" icon-"] { 159 | display: inline; 160 | width: auto; 161 | height: auto; 162 | line-height: normal; 163 | vertical-align: baseline; 164 | background-image: none; 165 | background-position: 0% 0%; 166 | background-repeat: repeat; 167 | margin-top: 0; 168 | } 169 | /* more sprites.less reset */ 170 | .icon-white, 171 | .nav-pills > .active > a > [class^="icon-"], 172 | .nav-pills > .active > a > [class*=" icon-"], 173 | .nav-list > .active > a > [class^="icon-"], 174 | .nav-list > .active > a > [class*=" icon-"], 175 | .navbar-inverse .nav > .active > a > [class^="icon-"], 176 | .navbar-inverse .nav > .active > a > [class*=" icon-"], 177 | .dropdown-menu > li > a:hover > [class^="icon-"], 178 | .dropdown-menu > li > a:hover > [class*=" icon-"], 179 | .dropdown-menu > .active > a > [class^="icon-"], 180 | .dropdown-menu > .active > a > [class*=" icon-"], 181 | .dropdown-submenu:hover > a > [class^="icon-"], 182 | .dropdown-submenu:hover > a > [class*=" icon-"] { 183 | background-image: none; 184 | } 185 | /* keeps Bootstrap styles with and without icons the same */ 186 | .btn [class^="icon-"].icon-large, 187 | .nav [class^="icon-"].icon-large, 188 | .btn [class*=" icon-"].icon-large, 189 | .nav [class*=" icon-"].icon-large { 190 | line-height: .9em; 191 | } 192 | .btn [class^="icon-"].icon-spin, 193 | .nav [class^="icon-"].icon-spin, 194 | .btn [class*=" icon-"].icon-spin, 195 | .nav [class*=" icon-"].icon-spin { 196 | display: inline-block; 197 | } 198 | .nav-tabs [class^="icon-"], 199 | .nav-pills [class^="icon-"], 200 | .nav-tabs [class*=" icon-"], 201 | .nav-pills [class*=" icon-"], 202 | .nav-tabs [class^="icon-"].icon-large, 203 | .nav-pills [class^="icon-"].icon-large, 204 | .nav-tabs [class*=" icon-"].icon-large, 205 | .nav-pills [class*=" icon-"].icon-large { 206 | line-height: .9em; 207 | } 208 | .btn [class^="icon-"].pull-left.icon-2x, 209 | .btn [class*=" icon-"].pull-left.icon-2x, 210 | .btn [class^="icon-"].pull-right.icon-2x, 211 | .btn [class*=" icon-"].pull-right.icon-2x { 212 | margin-top: .18em; 213 | } 214 | .btn [class^="icon-"].icon-spin.icon-large, 215 | .btn [class*=" icon-"].icon-spin.icon-large { 216 | line-height: .8em; 217 | } 218 | .btn.btn-small [class^="icon-"].pull-left.icon-2x, 219 | .btn.btn-small [class*=" icon-"].pull-left.icon-2x, 220 | .btn.btn-small [class^="icon-"].pull-right.icon-2x, 221 | .btn.btn-small [class*=" icon-"].pull-right.icon-2x { 222 | margin-top: .25em; 223 | } 224 | .btn.btn-large [class^="icon-"], 225 | .btn.btn-large [class*=" icon-"] { 226 | margin-top: 0; 227 | } 228 | .btn.btn-large [class^="icon-"].pull-left.icon-2x, 229 | .btn.btn-large [class*=" icon-"].pull-left.icon-2x, 230 | .btn.btn-large [class^="icon-"].pull-right.icon-2x, 231 | .btn.btn-large [class*=" icon-"].pull-right.icon-2x { 232 | margin-top: .05em; 233 | } 234 | .btn.btn-large [class^="icon-"].pull-left.icon-2x, 235 | .btn.btn-large [class*=" icon-"].pull-left.icon-2x { 236 | margin-right: .2em; 237 | } 238 | .btn.btn-large [class^="icon-"].pull-right.icon-2x, 239 | .btn.btn-large [class*=" icon-"].pull-right.icon-2x { 240 | margin-left: .2em; 241 | } 242 | /* EXTRAS 243 | * -------------------------- */ 244 | /* Stacked and layered icon */ 245 | .icon-stack { 246 | position: relative; 247 | display: inline-block; 248 | width: 2em; 249 | height: 2em; 250 | line-height: 2em; 251 | vertical-align: -35%; 252 | } 253 | .icon-stack [class^="icon-"], 254 | .icon-stack [class*=" icon-"] { 255 | display: block; 256 | text-align: center; 257 | position: absolute; 258 | width: 100%; 259 | height: 100%; 260 | font-size: 1em; 261 | line-height: inherit; 262 | *line-height: 2em; 263 | } 264 | .icon-stack .icon-stack-base { 265 | font-size: 2em; 266 | *line-height: 1em; 267 | } 268 | /* Animated rotating icon */ 269 | .icon-spin { 270 | display: inline-block; 271 | -moz-animation: spin 2s infinite linear; 272 | -o-animation: spin 2s infinite linear; 273 | -webkit-animation: spin 2s infinite linear; 274 | animation: spin 2s infinite linear; 275 | } 276 | @-moz-keyframes spin { 277 | 0% { 278 | -moz-transform: rotate(0deg); 279 | } 280 | 100% { 281 | -moz-transform: rotate(359deg); 282 | } 283 | } 284 | @-webkit-keyframes spin { 285 | 0% { 286 | -webkit-transform: rotate(0deg); 287 | } 288 | 100% { 289 | -webkit-transform: rotate(359deg); 290 | } 291 | } 292 | @-o-keyframes spin { 293 | 0% { 294 | -o-transform: rotate(0deg); 295 | } 296 | 100% { 297 | -o-transform: rotate(359deg); 298 | } 299 | } 300 | @-ms-keyframes spin { 301 | 0% { 302 | -ms-transform: rotate(0deg); 303 | } 304 | 100% { 305 | -ms-transform: rotate(359deg); 306 | } 307 | } 308 | @keyframes spin { 309 | 0% { 310 | transform: rotate(0deg); 311 | } 312 | 100% { 313 | transform: rotate(359deg); 314 | } 315 | } 316 | /* Icon rotations and mirroring */ 317 | .icon-rotate-90:before { 318 | -webkit-transform: rotate(90deg); 319 | -moz-transform: rotate(90deg); 320 | -ms-transform: rotate(90deg); 321 | -o-transform: rotate(90deg); 322 | transform: rotate(90deg); 323 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); 324 | } 325 | .icon-rotate-180:before { 326 | -webkit-transform: rotate(180deg); 327 | -moz-transform: rotate(180deg); 328 | -ms-transform: rotate(180deg); 329 | -o-transform: rotate(180deg); 330 | transform: rotate(180deg); 331 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); 332 | } 333 | .icon-rotate-270:before { 334 | -webkit-transform: rotate(270deg); 335 | -moz-transform: rotate(270deg); 336 | -ms-transform: rotate(270deg); 337 | -o-transform: rotate(270deg); 338 | transform: rotate(270deg); 339 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); 340 | } 341 | .icon-flip-horizontal:before { 342 | -webkit-transform: scale(-1, 1); 343 | -moz-transform: scale(-1, 1); 344 | -ms-transform: scale(-1, 1); 345 | -o-transform: scale(-1, 1); 346 | transform: scale(-1, 1); 347 | } 348 | .icon-flip-vertical:before { 349 | -webkit-transform: scale(1, -1); 350 | -moz-transform: scale(1, -1); 351 | -ms-transform: scale(1, -1); 352 | -o-transform: scale(1, -1); 353 | transform: scale(1, -1); 354 | } 355 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen 356 | readers do not read off random characters that represent icons */ 357 | .icon-glass:before { 358 | content: "\f000"; 359 | } 360 | .icon-music:before { 361 | content: "\f001"; 362 | } 363 | .icon-search:before { 364 | content: "\f002"; 365 | } 366 | .icon-envelope:before { 367 | content: "\f003"; 368 | } 369 | .icon-heart:before { 370 | content: "\f004"; 371 | } 372 | .icon-star:before { 373 | content: "\f005"; 374 | } 375 | .icon-star-empty:before { 376 | content: "\f006"; 377 | } 378 | .icon-user:before { 379 | content: "\f007"; 380 | } 381 | .icon-film:before { 382 | content: "\f008"; 383 | } 384 | .icon-th-large:before { 385 | content: "\f009"; 386 | } 387 | .icon-th:before { 388 | content: "\f00a"; 389 | } 390 | .icon-th-list:before { 391 | content: "\f00b"; 392 | } 393 | .icon-ok:before { 394 | content: "\f00c"; 395 | } 396 | .icon-remove:before { 397 | content: "\f00d"; 398 | } 399 | .icon-zoom-in:before { 400 | content: "\f00e"; 401 | } 402 | .icon-zoom-out:before { 403 | content: "\f010"; 404 | } 405 | .icon-off:before { 406 | content: "\f011"; 407 | } 408 | .icon-signal:before { 409 | content: "\f012"; 410 | } 411 | .icon-cog:before { 412 | content: "\f013"; 413 | } 414 | .icon-trash:before { 415 | content: "\f014"; 416 | } 417 | .icon-home:before { 418 | content: "\f015"; 419 | } 420 | .icon-file:before { 421 | content: "\f016"; 422 | } 423 | .icon-time:before { 424 | content: "\f017"; 425 | } 426 | .icon-road:before { 427 | content: "\f018"; 428 | } 429 | .icon-download-alt:before { 430 | content: "\f019"; 431 | } 432 | .icon-download:before { 433 | content: "\f01a"; 434 | } 435 | .icon-upload:before { 436 | content: "\f01b"; 437 | } 438 | .icon-inbox:before { 439 | content: "\f01c"; 440 | } 441 | .icon-play-circle:before { 442 | content: "\f01d"; 443 | } 444 | .icon-repeat:before, 445 | .icon-rotate-right:before { 446 | content: "\f01e"; 447 | } 448 | /* F020 doesn't work in Safari. all shifted one down */ 449 | .icon-refresh:before { 450 | content: "\f021"; 451 | } 452 | .icon-list-alt:before { 453 | content: "\f022"; 454 | } 455 | .icon-lock:before { 456 | content: "\f023"; 457 | } 458 | .icon-flag:before { 459 | content: "\f024"; 460 | } 461 | .icon-headphones:before { 462 | content: "\f025"; 463 | } 464 | .icon-volume-off:before { 465 | content: "\f026"; 466 | } 467 | .icon-volume-down:before { 468 | content: "\f027"; 469 | } 470 | .icon-volume-up:before { 471 | content: "\f028"; 472 | } 473 | .icon-qrcode:before { 474 | content: "\f029"; 475 | } 476 | .icon-barcode:before { 477 | content: "\f02a"; 478 | } 479 | .icon-tag:before { 480 | content: "\f02b"; 481 | } 482 | .icon-tags:before { 483 | content: "\f02c"; 484 | } 485 | .icon-book:before { 486 | content: "\f02d"; 487 | } 488 | .icon-bookmark:before { 489 | content: "\f02e"; 490 | } 491 | .icon-print:before { 492 | content: "\f02f"; 493 | } 494 | .icon-camera:before { 495 | content: "\f030"; 496 | } 497 | .icon-font:before { 498 | content: "\f031"; 499 | } 500 | .icon-bold:before { 501 | content: "\f032"; 502 | } 503 | .icon-italic:before { 504 | content: "\f033"; 505 | } 506 | .icon-text-height:before { 507 | content: "\f034"; 508 | } 509 | .icon-text-width:before { 510 | content: "\f035"; 511 | } 512 | .icon-align-left:before { 513 | content: "\f036"; 514 | } 515 | .icon-align-center:before { 516 | content: "\f037"; 517 | } 518 | .icon-align-right:before { 519 | content: "\f038"; 520 | } 521 | .icon-align-justify:before { 522 | content: "\f039"; 523 | } 524 | .icon-list:before { 525 | content: "\f03a"; 526 | } 527 | .icon-indent-left:before { 528 | content: "\f03b"; 529 | } 530 | .icon-indent-right:before { 531 | content: "\f03c"; 532 | } 533 | .icon-facetime-video:before { 534 | content: "\f03d"; 535 | } 536 | .icon-picture:before { 537 | content: "\f03e"; 538 | } 539 | .icon-pencil:before { 540 | content: "\f040"; 541 | } 542 | .icon-map-marker:before { 543 | content: "\f041"; 544 | } 545 | .icon-adjust:before { 546 | content: "\f042"; 547 | } 548 | .icon-tint:before { 549 | content: "\f043"; 550 | } 551 | .icon-edit:before { 552 | content: "\f044"; 553 | } 554 | .icon-share:before { 555 | content: "\f045"; 556 | } 557 | .icon-check:before { 558 | content: "\f046"; 559 | } 560 | .icon-move:before { 561 | content: "\f047"; 562 | } 563 | .icon-step-backward:before { 564 | content: "\f048"; 565 | } 566 | .icon-fast-backward:before { 567 | content: "\f049"; 568 | } 569 | .icon-backward:before { 570 | content: "\f04a"; 571 | } 572 | .icon-play:before { 573 | content: "\f04b"; 574 | } 575 | .icon-pause:before { 576 | content: "\f04c"; 577 | } 578 | .icon-stop:before { 579 | content: "\f04d"; 580 | } 581 | .icon-forward:before { 582 | content: "\f04e"; 583 | } 584 | .icon-fast-forward:before { 585 | content: "\f050"; 586 | } 587 | .icon-step-forward:before { 588 | content: "\f051"; 589 | } 590 | .icon-eject:before { 591 | content: "\f052"; 592 | } 593 | .icon-chevron-left:before { 594 | content: "\f053"; 595 | } 596 | .icon-chevron-right:before { 597 | content: "\f054"; 598 | } 599 | .icon-plus-sign:before { 600 | content: "\f055"; 601 | } 602 | .icon-minus-sign:before { 603 | content: "\f056"; 604 | } 605 | .icon-remove-sign:before { 606 | content: "\f057"; 607 | } 608 | .icon-ok-sign:before { 609 | content: "\f058"; 610 | } 611 | .icon-question-sign:before { 612 | content: "\f059"; 613 | } 614 | .icon-info-sign:before { 615 | content: "\f05a"; 616 | } 617 | .icon-screenshot:before { 618 | content: "\f05b"; 619 | } 620 | .icon-remove-circle:before { 621 | content: "\f05c"; 622 | } 623 | .icon-ok-circle:before { 624 | content: "\f05d"; 625 | } 626 | .icon-ban-circle:before { 627 | content: "\f05e"; 628 | } 629 | .icon-arrow-left:before { 630 | content: "\f060"; 631 | } 632 | .icon-arrow-right:before { 633 | content: "\f061"; 634 | } 635 | .icon-arrow-up:before { 636 | content: "\f062"; 637 | } 638 | .icon-arrow-down:before { 639 | content: "\f063"; 640 | } 641 | .icon-share-alt:before, 642 | .icon-mail-forward:before { 643 | content: "\f064"; 644 | } 645 | .icon-resize-full:before { 646 | content: "\f065"; 647 | } 648 | .icon-resize-small:before { 649 | content: "\f066"; 650 | } 651 | .icon-plus:before { 652 | content: "\f067"; 653 | } 654 | .icon-minus:before { 655 | content: "\f068"; 656 | } 657 | .icon-asterisk:before { 658 | content: "\f069"; 659 | } 660 | .icon-exclamation-sign:before { 661 | content: "\f06a"; 662 | } 663 | .icon-gift:before { 664 | content: "\f06b"; 665 | } 666 | .icon-leaf:before { 667 | content: "\f06c"; 668 | } 669 | .icon-fire:before { 670 | content: "\f06d"; 671 | } 672 | .icon-eye-open:before { 673 | content: "\f06e"; 674 | } 675 | .icon-eye-close:before { 676 | content: "\f070"; 677 | } 678 | .icon-warning-sign:before { 679 | content: "\f071"; 680 | } 681 | .icon-plane:before { 682 | content: "\f072"; 683 | } 684 | .icon-calendar:before { 685 | content: "\f073"; 686 | } 687 | .icon-random:before { 688 | content: "\f074"; 689 | } 690 | .icon-comment:before { 691 | content: "\f075"; 692 | } 693 | .icon-magnet:before { 694 | content: "\f076"; 695 | } 696 | .icon-chevron-up:before { 697 | content: "\f077"; 698 | } 699 | .icon-chevron-down:before { 700 | content: "\f078"; 701 | } 702 | .icon-retweet:before { 703 | content: "\f079"; 704 | } 705 | .icon-shopping-cart:before { 706 | content: "\f07a"; 707 | } 708 | .icon-folder-close:before { 709 | content: "\f07b"; 710 | } 711 | .icon-folder-open:before { 712 | content: "\f07c"; 713 | } 714 | .icon-resize-vertical:before { 715 | content: "\f07d"; 716 | } 717 | .icon-resize-horizontal:before { 718 | content: "\f07e"; 719 | } 720 | .icon-bar-chart:before { 721 | content: "\f080"; 722 | } 723 | .icon-twitter-sign:before { 724 | content: "\f081"; 725 | } 726 | .icon-facebook-sign:before { 727 | content: "\f082"; 728 | } 729 | .icon-camera-retro:before { 730 | content: "\f083"; 731 | } 732 | .icon-key:before { 733 | content: "\f084"; 734 | } 735 | .icon-cogs:before { 736 | content: "\f085"; 737 | } 738 | .icon-comments:before { 739 | content: "\f086"; 740 | } 741 | .icon-thumbs-up:before { 742 | content: "\f087"; 743 | } 744 | .icon-thumbs-down:before { 745 | content: "\f088"; 746 | } 747 | .icon-star-half:before { 748 | content: "\f089"; 749 | } 750 | .icon-heart-empty:before { 751 | content: "\f08a"; 752 | } 753 | .icon-signout:before { 754 | content: "\f08b"; 755 | } 756 | .icon-linkedin-sign:before { 757 | content: "\f08c"; 758 | } 759 | .icon-pushpin:before { 760 | content: "\f08d"; 761 | } 762 | .icon-external-link:before { 763 | content: "\f08e"; 764 | } 765 | .icon-signin:before { 766 | content: "\f090"; 767 | } 768 | .icon-trophy:before { 769 | content: "\f091"; 770 | } 771 | .icon-github-sign:before { 772 | content: "\f092"; 773 | } 774 | .icon-upload-alt:before { 775 | content: "\f093"; 776 | } 777 | .icon-lemon:before { 778 | content: "\f094"; 779 | } 780 | .icon-phone:before { 781 | content: "\f095"; 782 | } 783 | .icon-check-empty:before { 784 | content: "\f096"; 785 | } 786 | .icon-bookmark-empty:before { 787 | content: "\f097"; 788 | } 789 | .icon-phone-sign:before { 790 | content: "\f098"; 791 | } 792 | .icon-twitter:before { 793 | content: "\f099"; 794 | } 795 | .icon-facebook:before { 796 | content: "\f09a"; 797 | } 798 | .icon-github:before { 799 | content: "\f09b"; 800 | } 801 | .icon-unlock:before { 802 | content: "\f09c"; 803 | } 804 | .icon-credit-card:before { 805 | content: "\f09d"; 806 | } 807 | .icon-rss:before { 808 | content: "\f09e"; 809 | } 810 | .icon-hdd:before { 811 | content: "\f0a0"; 812 | } 813 | .icon-bullhorn:before { 814 | content: "\f0a1"; 815 | } 816 | .icon-bell:before { 817 | content: "\f0a2"; 818 | } 819 | .icon-certificate:before { 820 | content: "\f0a3"; 821 | } 822 | .icon-hand-right:before { 823 | content: "\f0a4"; 824 | } 825 | .icon-hand-left:before { 826 | content: "\f0a5"; 827 | } 828 | .icon-hand-up:before { 829 | content: "\f0a6"; 830 | } 831 | .icon-hand-down:before { 832 | content: "\f0a7"; 833 | } 834 | .icon-circle-arrow-left:before { 835 | content: "\f0a8"; 836 | } 837 | .icon-circle-arrow-right:before { 838 | content: "\f0a9"; 839 | } 840 | .icon-circle-arrow-up:before { 841 | content: "\f0aa"; 842 | } 843 | .icon-circle-arrow-down:before { 844 | content: "\f0ab"; 845 | } 846 | .icon-globe:before { 847 | content: "\f0ac"; 848 | } 849 | .icon-wrench:before { 850 | content: "\f0ad"; 851 | } 852 | .icon-tasks:before { 853 | content: "\f0ae"; 854 | } 855 | .icon-filter:before { 856 | content: "\f0b0"; 857 | } 858 | .icon-briefcase:before { 859 | content: "\f0b1"; 860 | } 861 | .icon-fullscreen:before { 862 | content: "\f0b2"; 863 | } 864 | .icon-group:before { 865 | content: "\f0c0"; 866 | } 867 | .icon-link:before { 868 | content: "\f0c1"; 869 | } 870 | .icon-cloud:before { 871 | content: "\f0c2"; 872 | } 873 | .icon-beaker:before { 874 | content: "\f0c3"; 875 | } 876 | .icon-cut:before { 877 | content: "\f0c4"; 878 | } 879 | .icon-copy:before { 880 | content: "\f0c5"; 881 | } 882 | .icon-paper-clip:before { 883 | content: "\f0c6"; 884 | } 885 | .icon-save:before { 886 | content: "\f0c7"; 887 | } 888 | .icon-sign-blank:before { 889 | content: "\f0c8"; 890 | } 891 | .icon-reorder:before { 892 | content: "\f0c9"; 893 | } 894 | .icon-list-ul:before { 895 | content: "\f0ca"; 896 | } 897 | .icon-list-ol:before { 898 | content: "\f0cb"; 899 | } 900 | .icon-strikethrough:before { 901 | content: "\f0cc"; 902 | } 903 | .icon-underline:before { 904 | content: "\f0cd"; 905 | } 906 | .icon-table:before { 907 | content: "\f0ce"; 908 | } 909 | .icon-magic:before { 910 | content: "\f0d0"; 911 | } 912 | .icon-truck:before { 913 | content: "\f0d1"; 914 | } 915 | .icon-pinterest:before { 916 | content: "\f0d2"; 917 | } 918 | .icon-pinterest-sign:before { 919 | content: "\f0d3"; 920 | } 921 | .icon-google-plus-sign:before { 922 | content: "\f0d4"; 923 | } 924 | .icon-google-plus:before { 925 | content: "\f0d5"; 926 | } 927 | .icon-money:before { 928 | content: "\f0d6"; 929 | } 930 | .icon-caret-down:before { 931 | content: "\f0d7"; 932 | } 933 | .icon-caret-up:before { 934 | content: "\f0d8"; 935 | } 936 | .icon-caret-left:before { 937 | content: "\f0d9"; 938 | } 939 | .icon-caret-right:before { 940 | content: "\f0da"; 941 | } 942 | .icon-columns:before { 943 | content: "\f0db"; 944 | } 945 | .icon-sort:before { 946 | content: "\f0dc"; 947 | } 948 | .icon-sort-down:before { 949 | content: "\f0dd"; 950 | } 951 | .icon-sort-up:before { 952 | content: "\f0de"; 953 | } 954 | .icon-envelope-alt:before { 955 | content: "\f0e0"; 956 | } 957 | .icon-linkedin:before { 958 | content: "\f0e1"; 959 | } 960 | .icon-undo:before, 961 | .icon-rotate-left:before { 962 | content: "\f0e2"; 963 | } 964 | .icon-legal:before { 965 | content: "\f0e3"; 966 | } 967 | .icon-dashboard:before { 968 | content: "\f0e4"; 969 | } 970 | .icon-comment-alt:before { 971 | content: "\f0e5"; 972 | } 973 | .icon-comments-alt:before { 974 | content: "\f0e6"; 975 | } 976 | .icon-bolt:before { 977 | content: "\f0e7"; 978 | } 979 | .icon-sitemap:before { 980 | content: "\f0e8"; 981 | } 982 | .icon-umbrella:before { 983 | content: "\f0e9"; 984 | } 985 | .icon-paste:before { 986 | content: "\f0ea"; 987 | } 988 | .icon-lightbulb:before { 989 | content: "\f0eb"; 990 | } 991 | .icon-exchange:before { 992 | content: "\f0ec"; 993 | } 994 | .icon-cloud-download:before { 995 | content: "\f0ed"; 996 | } 997 | .icon-cloud-upload:before { 998 | content: "\f0ee"; 999 | } 1000 | .icon-user-md:before { 1001 | content: "\f0f0"; 1002 | } 1003 | .icon-stethoscope:before { 1004 | content: "\f0f1"; 1005 | } 1006 | .icon-suitcase:before { 1007 | content: "\f0f2"; 1008 | } 1009 | .icon-bell-alt:before { 1010 | content: "\f0f3"; 1011 | } 1012 | .icon-coffee:before { 1013 | content: "\f0f4"; 1014 | } 1015 | .icon-food:before { 1016 | content: "\f0f5"; 1017 | } 1018 | .icon-file-alt:before { 1019 | content: "\f0f6"; 1020 | } 1021 | .icon-building:before { 1022 | content: "\f0f7"; 1023 | } 1024 | .icon-hospital:before { 1025 | content: "\f0f8"; 1026 | } 1027 | .icon-ambulance:before { 1028 | content: "\f0f9"; 1029 | } 1030 | .icon-medkit:before { 1031 | content: "\f0fa"; 1032 | } 1033 | .icon-fighter-jet:before { 1034 | content: "\f0fb"; 1035 | } 1036 | .icon-beer:before { 1037 | content: "\f0fc"; 1038 | } 1039 | .icon-h-sign:before { 1040 | content: "\f0fd"; 1041 | } 1042 | .icon-plus-sign-alt:before { 1043 | content: "\f0fe"; 1044 | } 1045 | .icon-double-angle-left:before { 1046 | content: "\f100"; 1047 | } 1048 | .icon-double-angle-right:before { 1049 | content: "\f101"; 1050 | } 1051 | .icon-double-angle-up:before { 1052 | content: "\f102"; 1053 | } 1054 | .icon-double-angle-down:before { 1055 | content: "\f103"; 1056 | } 1057 | .icon-angle-left:before { 1058 | content: "\f104"; 1059 | } 1060 | .icon-angle-right:before { 1061 | content: "\f105"; 1062 | } 1063 | .icon-angle-up:before { 1064 | content: "\f106"; 1065 | } 1066 | .icon-angle-down:before { 1067 | content: "\f107"; 1068 | } 1069 | .icon-desktop:before { 1070 | content: "\f108"; 1071 | } 1072 | .icon-laptop:before { 1073 | content: "\f109"; 1074 | } 1075 | .icon-tablet:before { 1076 | content: "\f10a"; 1077 | } 1078 | .icon-mobile-phone:before { 1079 | content: "\f10b"; 1080 | } 1081 | .icon-circle-blank:before { 1082 | content: "\f10c"; 1083 | } 1084 | .icon-quote-left:before { 1085 | content: "\f10d"; 1086 | } 1087 | .icon-quote-right:before { 1088 | content: "\f10e"; 1089 | } 1090 | .icon-spinner:before { 1091 | content: "\f110"; 1092 | } 1093 | .icon-circle:before { 1094 | content: "\f111"; 1095 | } 1096 | .icon-reply:before, 1097 | .icon-mail-reply:before { 1098 | content: "\f112"; 1099 | } 1100 | .icon-folder-close-alt:before { 1101 | content: "\f114"; 1102 | } 1103 | .icon-folder-open-alt:before { 1104 | content: "\f115"; 1105 | } 1106 | .icon-expand-alt:before { 1107 | content: "\f116"; 1108 | } 1109 | .icon-collapse-alt:before { 1110 | content: "\f117"; 1111 | } 1112 | .icon-smile:before { 1113 | content: "\f118"; 1114 | } 1115 | .icon-frown:before { 1116 | content: "\f119"; 1117 | } 1118 | .icon-meh:before { 1119 | content: "\f11a"; 1120 | } 1121 | .icon-gamepad:before { 1122 | content: "\f11b"; 1123 | } 1124 | .icon-keyboard:before { 1125 | content: "\f11c"; 1126 | } 1127 | .icon-flag-alt:before { 1128 | content: "\f11d"; 1129 | } 1130 | .icon-flag-checkered:before { 1131 | content: "\f11e"; 1132 | } 1133 | .icon-terminal:before { 1134 | content: "\f120"; 1135 | } 1136 | .icon-code:before { 1137 | content: "\f121"; 1138 | } 1139 | .icon-reply-all:before { 1140 | content: "\f122"; 1141 | } 1142 | .icon-mail-reply-all:before { 1143 | content: "\f122"; 1144 | } 1145 | .icon-star-half-full:before, 1146 | .icon-star-half-empty:before { 1147 | content: "\f123"; 1148 | } 1149 | .icon-location-arrow:before { 1150 | content: "\f124"; 1151 | } 1152 | .icon-crop:before { 1153 | content: "\f125"; 1154 | } 1155 | .icon-code-fork:before { 1156 | content: "\f126"; 1157 | } 1158 | .icon-unlink:before { 1159 | content: "\f127"; 1160 | } 1161 | .icon-question:before { 1162 | content: "\f128"; 1163 | } 1164 | .icon-info:before { 1165 | content: "\f129"; 1166 | } 1167 | .icon-exclamation:before { 1168 | content: "\f12a"; 1169 | } 1170 | .icon-superscript:before { 1171 | content: "\f12b"; 1172 | } 1173 | .icon-subscript:before { 1174 | content: "\f12c"; 1175 | } 1176 | .icon-eraser:before { 1177 | content: "\f12d"; 1178 | } 1179 | .icon-puzzle-piece:before { 1180 | content: "\f12e"; 1181 | } 1182 | .icon-microphone:before { 1183 | content: "\f130"; 1184 | } 1185 | .icon-microphone-off:before { 1186 | content: "\f131"; 1187 | } 1188 | .icon-shield:before { 1189 | content: "\f132"; 1190 | } 1191 | .icon-calendar-empty:before { 1192 | content: "\f133"; 1193 | } 1194 | .icon-fire-extinguisher:before { 1195 | content: "\f134"; 1196 | } 1197 | .icon-rocket:before { 1198 | content: "\f135"; 1199 | } 1200 | .icon-maxcdn:before { 1201 | content: "\f136"; 1202 | } 1203 | .icon-chevron-sign-left:before { 1204 | content: "\f137"; 1205 | } 1206 | .icon-chevron-sign-right:before { 1207 | content: "\f138"; 1208 | } 1209 | .icon-chevron-sign-up:before { 1210 | content: "\f139"; 1211 | } 1212 | .icon-chevron-sign-down:before { 1213 | content: "\f13a"; 1214 | } 1215 | .icon-html5:before { 1216 | content: "\f13b"; 1217 | } 1218 | .icon-css3:before { 1219 | content: "\f13c"; 1220 | } 1221 | .icon-anchor:before { 1222 | content: "\f13d"; 1223 | } 1224 | .icon-unlock-alt:before { 1225 | content: "\f13e"; 1226 | } 1227 | .icon-bullseye:before { 1228 | content: "\f140"; 1229 | } 1230 | .icon-ellipsis-horizontal:before { 1231 | content: "\f141"; 1232 | } 1233 | .icon-ellipsis-vertical:before { 1234 | content: "\f142"; 1235 | } 1236 | .icon-rss-sign:before { 1237 | content: "\f143"; 1238 | } 1239 | .icon-play-sign:before { 1240 | content: "\f144"; 1241 | } 1242 | .icon-ticket:before { 1243 | content: "\f145"; 1244 | } 1245 | .icon-minus-sign-alt:before { 1246 | content: "\f146"; 1247 | } 1248 | .icon-check-minus:before { 1249 | content: "\f147"; 1250 | } 1251 | .icon-level-up:before { 1252 | content: "\f148"; 1253 | } 1254 | .icon-level-down:before { 1255 | content: "\f149"; 1256 | } 1257 | .icon-check-sign:before { 1258 | content: "\f14a"; 1259 | } 1260 | .icon-edit-sign:before { 1261 | content: "\f14b"; 1262 | } 1263 | .icon-external-link-sign:before { 1264 | content: "\f14c"; 1265 | } 1266 | .icon-share-sign:before { 1267 | content: "\f14d"; 1268 | } 1269 | -------------------------------------------------------------------------------- /app/styles/includes/page-transitions.less: -------------------------------------------------------------------------------- 1 | /* animation sets */ 2 | 3 | /* move from / to */ 4 | 5 | .pt-page-moveToLeft { 6 | -webkit-animation: moveToLeft .6s ease both; 7 | -moz-animation: moveToLeft .6s ease both; 8 | animation: moveToLeft .6s ease both; 9 | } 10 | 11 | .pt-page-moveFromLeft { 12 | -webkit-animation: moveFromLeft .6s ease both; 13 | -moz-animation: moveFromLeft .6s ease both; 14 | animation: moveFromLeft .6s ease both; 15 | } 16 | 17 | .pt-page-moveToRight { 18 | -webkit-animation: moveToRight .6s ease both; 19 | -moz-animation: moveToRight .6s ease both; 20 | animation: moveToRight .6s ease both; 21 | } 22 | 23 | .pt-page-moveFromRight { 24 | -webkit-animation: moveFromRight .6s ease both; 25 | -moz-animation: moveFromRight .6s ease both; 26 | animation: moveFromRight .6s ease both; 27 | } 28 | 29 | .pt-page-moveToTop { 30 | -webkit-animation: moveToTop .6s ease both; 31 | -moz-animation: moveToTop .6s ease both; 32 | animation: moveToTop .6s ease both; 33 | } 34 | 35 | .pt-page-moveFromTop { 36 | -webkit-animation: moveFromTop .6s ease both; 37 | -moz-animation: moveFromTop .6s ease both; 38 | animation: moveFromTop .6s ease both; 39 | } 40 | 41 | .pt-page-moveToBottom { 42 | -webkit-animation: moveToBottom .6s ease both; 43 | -moz-animation: moveToBottom .6s ease both; 44 | animation: moveToBottom .6s ease both; 45 | } 46 | 47 | .pt-page-moveFromBottom { 48 | -webkit-animation: moveFromBottom .6s ease both; 49 | -moz-animation: moveFromBottom .6s ease both; 50 | animation: moveFromBottom .6s ease both; 51 | } 52 | 53 | /* fade */ 54 | 55 | .pt-page-fade { 56 | -webkit-animation: fade .7s ease both; 57 | -moz-animation: fade .7s ease both; 58 | animation: fade .7s ease both; 59 | } 60 | 61 | /* move from / to and fade */ 62 | 63 | .pt-page-moveToLeftFade { 64 | -webkit-animation: moveToLeftFade .7s ease both; 65 | -moz-animation: moveToLeftFade .7s ease both; 66 | animation: moveToLeftFade .7s ease both; 67 | } 68 | 69 | .pt-page-moveFromLeftFade { 70 | -webkit-animation: moveFromLeftFade .7s ease both; 71 | -moz-animation: moveFromLeftFade .7s ease both; 72 | animation: moveFromLeftFade .7s ease both; 73 | } 74 | 75 | .pt-page-moveToRightFade { 76 | -webkit-animation: moveToRightFade .7s ease both; 77 | -moz-animation: moveToRightFade .7s ease both; 78 | animation: moveToRightFade .7s ease both; 79 | } 80 | 81 | .pt-page-moveFromRightFade { 82 | -webkit-animation: moveFromRightFade .7s ease both; 83 | -moz-animation: moveFromRightFade .7s ease both; 84 | animation: moveFromRightFade .7s ease both; 85 | } 86 | 87 | .pt-page-moveToTopFade { 88 | -webkit-animation: moveToTopFade .7s ease both; 89 | -moz-animation: moveToTopFade .7s ease both; 90 | animation: moveToTopFade .7s ease both; 91 | } 92 | 93 | .pt-page-moveFromTopFade { 94 | -webkit-animation: moveFromTopFade .7s ease both; 95 | -moz-animation: moveFromTopFade .7s ease both; 96 | animation: moveFromTopFade .7s ease both; 97 | } 98 | 99 | .pt-page-moveToBottomFade { 100 | -webkit-animation: moveToBottomFade .7s ease both; 101 | -moz-animation: moveToBottomFade .7s ease both; 102 | animation: moveToBottomFade .7s ease both; 103 | } 104 | 105 | .pt-page-moveFromBottomFade { 106 | -webkit-animation: moveFromBottomFade .7s ease both; 107 | -moz-animation: moveFromBottomFade .7s ease both; 108 | animation: moveFromBottomFade .7s ease both; 109 | } 110 | 111 | /* move to with different easing */ 112 | 113 | .pt-page-moveToLeftEasing { 114 | -webkit-animation: moveToLeft .7s ease-in-out both; 115 | -moz-animation: moveToLeft .7s ease-in-out both; 116 | animation: moveToLeft .7s ease-in-out both; 117 | } 118 | .pt-page-moveToRightEasing { 119 | -webkit-animation: moveToRight .7s ease-in-out both; 120 | -moz-animation: moveToRight .7s ease-in-out both; 121 | animation: moveToRight .7s ease-in-out both; 122 | } 123 | .pt-page-moveToTopEasing { 124 | -webkit-animation: moveToTop .7s ease-in-out both; 125 | -moz-animation: moveToTop .7s ease-in-out both; 126 | animation: moveToTop .7s ease-in-out both; 127 | } 128 | .pt-page-moveToBottomEasing { 129 | -webkit-animation: moveToBottom .7s ease-in-out both; 130 | -moz-animation: moveToBottom .7s ease-in-out both; 131 | animation: moveToBottom .7s ease-in-out both; 132 | } 133 | 134 | /********************************* keyframes **************************************/ 135 | 136 | /* move from / to */ 137 | 138 | @-webkit-keyframes moveToLeft { 139 | to { -webkit-transform: translateX(-100%); } 140 | } 141 | @-moz-keyframes moveToLeft { 142 | to { -moz-transform: translateX(-100%); } 143 | } 144 | @keyframes moveToLeft { 145 | to { transform: translateX(-100%); } 146 | } 147 | 148 | @-webkit-keyframes moveFromLeft { 149 | from { -webkit-transform: translateX(-100%); } 150 | } 151 | @-moz-keyframes moveFromLeft { 152 | from { -moz-transform: translateX(-100%); } 153 | } 154 | @keyframes moveFromLeft { 155 | from { transform: translateX(-100%); } 156 | } 157 | 158 | @-webkit-keyframes moveToRight { 159 | to { -webkit-transform: translateX(100%); } 160 | } 161 | @-moz-keyframes moveToRight { 162 | to { -moz-transform: translateX(100%); } 163 | } 164 | @keyframes moveToRight { 165 | to { transform: translateX(100%); } 166 | } 167 | 168 | @-webkit-keyframes moveFromRight { 169 | from { -webkit-transform: translateX(100%); } 170 | } 171 | @-moz-keyframes moveFromRight { 172 | from { -moz-transform: translateX(100%); } 173 | } 174 | @keyframes moveFromRight { 175 | from { transform: translateX(100%); } 176 | } 177 | 178 | @-webkit-keyframes moveToTop { 179 | to { -webkit-transform: translateY(-100%); } 180 | } 181 | @-moz-keyframes moveToTop { 182 | to { -moz-transform: translateY(-100%); } 183 | } 184 | @keyframes moveToTop { 185 | to { transform: translateY(-100%); } 186 | } 187 | 188 | @-webkit-keyframes moveFromTop { 189 | from { -webkit-transform: translateY(-100%); } 190 | } 191 | @-moz-keyframes moveFromTop { 192 | from { -moz-transform: translateY(-100%); } 193 | } 194 | @keyframes moveFromTop { 195 | from { transform: translateY(-100%); } 196 | } 197 | 198 | @-webkit-keyframes moveToBottom { 199 | to { -webkit-transform: translateY(100%); } 200 | } 201 | @-moz-keyframes moveToBottom { 202 | to { -moz-transform: translateY(100%); } 203 | } 204 | @keyframes moveToBottom { 205 | to { transform: translateY(100%); } 206 | } 207 | 208 | @-webkit-keyframes moveFromBottom { 209 | from { -webkit-transform: translateY(100%); } 210 | } 211 | @-moz-keyframes moveFromBottom { 212 | from { -moz-transform: translateY(100%); } 213 | } 214 | @keyframes moveFromBottom { 215 | from { transform: translateY(100%); } 216 | } 217 | 218 | /* fade */ 219 | 220 | @-webkit-keyframes fade { 221 | to { opacity: 0.3; } 222 | } 223 | @-moz-keyframes fade { 224 | to { opacity: 0.3; } 225 | } 226 | @keyframes fade { 227 | to { opacity: 0.3; } 228 | } 229 | 230 | /* move from / to and fade */ 231 | 232 | @-webkit-keyframes moveToLeftFade { 233 | to { opacity: 0.3; -webkit-transform: translateX(-100%); } 234 | } 235 | @-moz-keyframes moveToLeftFade { 236 | to { opacity: 0.3; -moz-transform: translateX(-100%); } 237 | } 238 | @keyframes moveToLeftFade { 239 | to { opacity: 0.3; transform: translateX(-100%); } 240 | } 241 | 242 | @-webkit-keyframes moveFromLeftFade { 243 | from { opacity: 0.3; -webkit-transform: translateX(-100%); } 244 | } 245 | @-moz-keyframes moveFromLeftFade { 246 | from { opacity: 0.3; -moz-transform: translateX(-100%); } 247 | } 248 | @keyframes moveFromLeftFade { 249 | from { opacity: 0.3; transform: translateX(-100%); } 250 | } 251 | 252 | @-webkit-keyframes moveToRightFade { 253 | to { opacity: 0.3; -webkit-transform: translateX(100%); } 254 | } 255 | @-moz-keyframes moveToRightFade { 256 | to { opacity: 0.3; -moz-transform: translateX(100%); } 257 | } 258 | @keyframes moveToRightFade { 259 | to { opacity: 0.3; transform: translateX(100%); } 260 | } 261 | 262 | @-webkit-keyframes moveFromRightFade { 263 | from { opacity: 0.3; -webkit-transform: translateX(100%); } 264 | } 265 | @-moz-keyframes moveFromRightFade { 266 | from { opacity: 0.3; -moz-transform: translateX(100%); } 267 | } 268 | @keyframes moveFromRightFade { 269 | from { opacity: 0.3; transform: translateX(100%); } 270 | } 271 | 272 | @-webkit-keyframes moveToTopFade { 273 | to { opacity: 0.3; -webkit-transform: translateY(-100%); } 274 | } 275 | @-moz-keyframes moveToTopFade { 276 | to { opacity: 0.3; -moz-transform: translateY(-100%); } 277 | } 278 | @keyframes moveToTopFade { 279 | to { opacity: 0.3; transform: translateY(-100%); } 280 | } 281 | 282 | @-webkit-keyframes moveFromTopFade { 283 | from { opacity: 0.3; -webkit-transform: translateY(-100%); } 284 | } 285 | @-moz-keyframes moveFromTopFade { 286 | from { opacity: 0.3; -moz-transform: translateY(-100%); } 287 | } 288 | @keyframes moveFromTopFade { 289 | from { opacity: 0.3; transform: translateY(-100%); } 290 | } 291 | 292 | @-webkit-keyframes moveToBottomFade { 293 | to { opacity: 0.3; -webkit-transform: translateY(100%); } 294 | } 295 | @-moz-keyframes moveToBottomFade { 296 | to { opacity: 0.3; -moz-transform: translateY(100%); } 297 | } 298 | @keyframes moveToBottomFade { 299 | to { opacity: 0.3; transform: translateY(100%); } 300 | } 301 | 302 | @-webkit-keyframes moveFromBottomFade { 303 | from { opacity: 0.3; -webkit-transform: translateY(100%); } 304 | } 305 | @-moz-keyframes moveFromBottomFade { 306 | from { opacity: 0.3; -moz-transform: translateY(100%); } 307 | } 308 | @keyframes moveFromBottomFade { 309 | from { opacity: 0.3; transform: translateY(100%); } 310 | } 311 | 312 | /* scale and fade */ 313 | 314 | .pt-page-scaleDown { 315 | -webkit-animation: scaleDown .7s ease both; 316 | -moz-animation: scaleDown .7s ease both; 317 | animation: scaleDown .7s ease both; 318 | } 319 | 320 | .pt-page-scaleUp { 321 | -webkit-animation: scaleUp .7s ease both; 322 | -moz-animation: scaleUp .7s ease both; 323 | animation: scaleUp .7s ease both; 324 | } 325 | 326 | .pt-page-scaleUpDown { 327 | -webkit-animation: scaleUpDown .5s ease both; 328 | -moz-animation: scaleUpDown .5s ease both; 329 | animation: scaleUpDown .5s ease both; 330 | } 331 | 332 | .pt-page-scaleDownUp { 333 | -webkit-animation: scaleDownUp .5s ease both; 334 | -moz-animation: scaleDownUp .5s ease both; 335 | animation: scaleDownUp .5s ease both; 336 | } 337 | 338 | .pt-page-scaleDownCenter { 339 | -webkit-animation: scaleDownCenter .4s ease-in both; 340 | -moz-animation: scaleDownCenter .4s ease-in both; 341 | animation: scaleDownCenter .4s ease-in both; 342 | } 343 | 344 | .pt-page-scaleUpCenter { 345 | -webkit-animation: scaleUpCenter .4s ease-out both; 346 | -moz-animation: scaleUpCenter .4s ease-out both; 347 | animation: scaleUpCenter .4s ease-out both; 348 | } 349 | 350 | /********************************* keyframes **************************************/ 351 | 352 | /* scale and fade */ 353 | 354 | @-webkit-keyframes scaleDown { 355 | to { opacity: 0; -webkit-transform: scale(.8); } 356 | } 357 | @-moz-keyframes scaleDown { 358 | to { opacity: 0; -moz-transform: scale(.8); } 359 | } 360 | @keyframes scaleDown { 361 | to { opacity: 0; transform: scale(.8); } 362 | } 363 | 364 | @-webkit-keyframes scaleUp { 365 | from { opacity: 0; -webkit-transform: scale(.8); } 366 | } 367 | @-moz-keyframes scaleUp { 368 | from { opacity: 0; -moz-transform: scale(.8); } 369 | } 370 | @keyframes scaleUp { 371 | from { opacity: 0; transform: scale(.8); } 372 | } 373 | 374 | @-webkit-keyframes scaleUpDown { 375 | from { opacity: 0; -webkit-transform: scale(1.2); } 376 | } 377 | @-moz-keyframes scaleUpDown { 378 | from { opacity: 0; -moz-transform: scale(1.2); } 379 | } 380 | @keyframes scaleUpDown { 381 | from { opacity: 0; transform: scale(1.2); } 382 | } 383 | 384 | @-webkit-keyframes scaleDownUp { 385 | to { opacity: 0; -webkit-transform: scale(1.2); } 386 | } 387 | @-moz-keyframes scaleDownUp { 388 | to { opacity: 0; -moz-transform: scale(1.2); } 389 | } 390 | @keyframes scaleDownUp { 391 | to { opacity: 0; transform: scale(1.2); } 392 | } 393 | 394 | @-webkit-keyframes scaleDownCenter { 395 | to { opacity: 0; -webkit-transform: scale(.7); } 396 | } 397 | @-moz-keyframes scaleDownCenter { 398 | to { opacity: 0; -moz-transform: scale(.7); } 399 | } 400 | @keyframes scaleDownCenter { 401 | to { opacity: 0; transform: scale(.7); } 402 | } 403 | 404 | @-webkit-keyframes scaleUpCenter { 405 | from { opacity: 0; -webkit-transform: scale(.7); } 406 | } 407 | @-moz-keyframes scaleUpCenter { 408 | from { opacity: 0; -moz-transform: scale(.7); } 409 | } 410 | @keyframes scaleUpCenter { 411 | from { opacity: 0; transform: scale(.7); } 412 | } 413 | 414 | /* rotate sides first and scale */ 415 | 416 | .pt-page-rotateRightSideFirst { 417 | -webkit-transform-origin: 0% 50%; 418 | -webkit-animation: rotateRightSideFirst .8s both ease-in; 419 | -moz-transform-origin: 0% 50%; 420 | -moz-animation: rotateRightSideFirst .8s both ease-in; 421 | transform-origin: 0% 50%; 422 | animation: rotateRightSideFirst .8s both ease-in; 423 | } 424 | .pt-page-rotateLeftSideFirst { 425 | -webkit-transform-origin: 100% 50%; 426 | -webkit-animation: rotateLeftSideFirst .8s both ease-in; 427 | -moz-transform-origin: 100% 50%; 428 | -moz-animation: rotateLeftSideFirst .8s both ease-in; 429 | transform-origin: 100% 50%; 430 | animation: rotateLeftSideFirst .8s both ease-in; 431 | } 432 | .pt-page-rotateTopSideFirst { 433 | -webkit-transform-origin: 50% 100%; 434 | -webkit-animation: rotateTopSideFirst .8s both ease-in; 435 | -moz-transform-origin: 50% 100%; 436 | -moz-animation: rotateTopSideFirst .8s both ease-in; 437 | transform-origin: 50% 100%; 438 | animation: rotateTopSideFirst .8s both ease-in; 439 | } 440 | .pt-page-rotateBottomSideFirst { 441 | -webkit-transform-origin: 50% 0%; 442 | -webkit-animation: rotateBottomSideFirst .8s both ease-in; 443 | -moz-transform-origin: 50% 0%; 444 | -moz-animation: rotateBottomSideFirst .8s both ease-in; 445 | transform-origin: 50% 0%; 446 | animation: rotateBottomSideFirst .8s both ease-in; 447 | } 448 | 449 | /* flip */ 450 | 451 | .pt-page-flipOutRight { 452 | -webkit-transform-origin: 50% 50%; 453 | -webkit-animation: flipOutRight .5s both ease-in; 454 | -moz-transform-origin: 50% 50%; 455 | -moz-animation: flipOutRight .5s both ease-in; 456 | transform-origin: 50% 50%; 457 | animation: flipOutRight .5s both ease-in; 458 | } 459 | .pt-page-flipInLeft { 460 | -webkit-transform-origin: 50% 50%; 461 | -webkit-animation: flipInLeft .5s both ease-out; 462 | -moz-transform-origin: 50% 50%; 463 | -moz-animation: flipInLeft .5s both ease-out; 464 | transform-origin: 50% 50%; 465 | animation: flipInLeft .5s both ease-out; 466 | } 467 | .pt-page-flipOutLeft { 468 | -webkit-transform-origin: 50% 50%; 469 | -webkit-animation: flipOutLeft .5s both ease-in; 470 | -moz-transform-origin: 50% 50%; 471 | -moz-animation: flipOutLeft .5s both ease-in; 472 | transform-origin: 50% 50%; 473 | animation: flipOutLeft .5s both ease-in; 474 | } 475 | .pt-page-flipInRight { 476 | -webkit-transform-origin: 50% 50%; 477 | -webkit-animation: flipInRight .5s both ease-out; 478 | -moz-transform-origin: 50% 50%; 479 | -moz-animation: flipInRight .5s both ease-out; 480 | transform-origin: 50% 50%; 481 | animation: flipInRight .5s both ease-out; 482 | } 483 | .pt-page-flipOutTop { 484 | -webkit-transform-origin: 50% 50%; 485 | -webkit-animation: flipOutTop .5s both ease-in; 486 | -moz-transform-origin: 50% 50%; 487 | -moz-animation: flipOutTop .5s both ease-in; 488 | transform-origin: 50% 50%; 489 | animation: flipOutTop .5s both ease-in; 490 | } 491 | .pt-page-flipInBottom { 492 | -webkit-transform-origin: 50% 50%; 493 | -webkit-animation: flipInBottom .5s both ease-out; 494 | -moz-transform-origin: 50% 50%; 495 | -moz-animation: flipInBottom .5s both ease-out; 496 | transform-origin: 50% 50%; 497 | animation: flipInBottom .5s both ease-out; 498 | } 499 | .pt-page-flipOutBottom { 500 | -webkit-transform-origin: 50% 50%; 501 | -webkit-animation: flipOutBottom .5s both ease-in; 502 | -moz-transform-origin: 50% 50%; 503 | -moz-animation: flipOutBottom .5s both ease-in; 504 | transform-origin: 50% 50%; 505 | animation: flipOutBottom .5s both ease-in; 506 | } 507 | .pt-page-flipInTop { 508 | -webkit-transform-origin: 50% 50%; 509 | -webkit-animation: flipInTop .5s both ease-out; 510 | -moz-transform-origin: 50% 50%; 511 | -moz-animation: flipInTop .5s both ease-out; 512 | transform-origin: 50% 50%; 513 | animation: flipInTop .5s both ease-out; 514 | } 515 | 516 | /* rotate fall */ 517 | 518 | .pt-page-rotateFall { 519 | -webkit-transform-origin: 0% 0%; 520 | -webkit-animation: rotateFall 1s both ease-in; 521 | -moz-transform-origin: 0% 0%; 522 | -moz-animation: rotateFall 1s both ease-in; 523 | transform-origin: 0% 0%; 524 | animation: rotateFall 1s both ease-in; 525 | } 526 | 527 | /* rotate newspaper */ 528 | .pt-page-rotateOutNewspaper { 529 | -webkit-transform-origin: 50% 50%; 530 | -webkit-animation: rotateOutNewspaper .5s both ease-in; 531 | -moz-transform-origin: 50% 50%; 532 | -moz-animation: rotateOutNewspaper .5s both ease-in; 533 | transform-origin: 50% 50%; 534 | animation: rotateOutNewspaper .5s both ease-in; 535 | } 536 | .pt-page-rotateInNewspaper { 537 | -webkit-transform-origin: 50% 50%; 538 | -webkit-animation: rotateInNewspaper .5s both ease-out; 539 | -moz-transform-origin: 50% 50%; 540 | -moz-animation: rotateInNewspaper .5s both ease-out; 541 | transform-origin: 50% 50%; 542 | animation: rotateInNewspaper .5s both ease-out; 543 | } 544 | 545 | /* push */ 546 | .pt-page-rotatePushLeft { 547 | -webkit-transform-origin: 0% 50%; 548 | -webkit-animation: rotatePushLeft .8s both ease; 549 | -moz-transform-origin: 0% 50%; 550 | -moz-animation: rotatePushLeft .8s both ease; 551 | transform-origin: 0% 50%; 552 | animation: rotatePushLeft .8s both ease; 553 | } 554 | .pt-page-rotatePushRight { 555 | -webkit-transform-origin: 100% 50%; 556 | -webkit-animation: rotatePushRight .8s both ease; 557 | -moz-transform-origin: 100% 50%; 558 | -moz-animation: rotatePushRight .8s both ease; 559 | transform-origin: 100% 50%; 560 | animation: rotatePushRight .8s both ease; 561 | } 562 | .pt-page-rotatePushTop { 563 | -webkit-transform-origin: 50% 0%; 564 | -webkit-animation: rotatePushTop .8s both ease; 565 | -moz-transform-origin: 50% 0%; 566 | -moz-animation: rotatePushTop .8s both ease; 567 | transform-origin: 50% 0%; 568 | animation: rotatePushTop .8s both ease; 569 | } 570 | .pt-page-rotatePushBottom { 571 | -webkit-transform-origin: 50% 100%; 572 | -webkit-animation: rotatePushBottom .8s both ease; 573 | -moz-transform-origin: 50% 100%; 574 | -moz-animation: rotatePushBottom .8s both ease; 575 | transform-origin: 50% 100%; 576 | animation: rotatePushBottom .8s both ease; 577 | } 578 | 579 | /* pull */ 580 | .pt-page-rotatePullRight { 581 | -webkit-transform-origin: 100% 50%; 582 | -webkit-animation: rotatePullRight .5s both ease; 583 | -moz-transform-origin: 100% 50%; 584 | -moz-animation: rotatePullRight .5s both ease; 585 | transform-origin: 100% 50%; 586 | animation: rotatePullRight .5s both ease; 587 | } 588 | .pt-page-rotatePullLeft { 589 | -webkit-transform-origin: 0% 50%; 590 | -webkit-animation: rotatePullLeft .5s both ease; 591 | -moz-transform-origin: 0% 50%; 592 | -moz-animation: rotatePullLeft .5s both ease; 593 | transform-origin: 0% 50%; 594 | animation: rotatePullLeft .5s both ease; 595 | } 596 | .pt-page-rotatePullTop { 597 | -webkit-transform-origin: 50% 0%; 598 | -webkit-animation: rotatePullTop .5s both ease; 599 | -moz-transform-origin: 50% 0%; 600 | -moz-animation: rotatePullTop .5s both ease; 601 | transform-origin: 50% 0%; 602 | animation: rotatePullTop .5s both ease; 603 | } 604 | .pt-page-rotatePullBottom { 605 | -webkit-transform-origin: 50% 100%; 606 | -webkit-animation: rotatePullBottom .5s both ease; 607 | -moz-transform-origin: 50% 100%; 608 | -moz-animation: rotatePullBottom .5s both ease; 609 | transform-origin: 50% 100%; 610 | animation: rotatePullBottom .5s both ease; 611 | } 612 | 613 | /* fold */ 614 | .pt-page-rotateFoldRight { 615 | -webkit-transform-origin: 0% 50%; 616 | -webkit-animation: rotateFoldRight .7s both ease; 617 | -moz-transform-origin: 0% 50%; 618 | -moz-animation: rotateFoldRight .7s both ease; 619 | transform-origin: 0% 50%; 620 | animation: rotateFoldRight .7s both ease; 621 | } 622 | .pt-page-rotateFoldLeft { 623 | -webkit-transform-origin: 100% 50%; 624 | -webkit-animation: rotateFoldLeft .7s both ease; 625 | -moz-transform-origin: 100% 50%; 626 | -moz-animation: rotateFoldLeft .7s both ease; 627 | transform-origin: 100% 50%; 628 | animation: rotateFoldLeft .7s both ease; 629 | } 630 | .pt-page-rotateFoldTop { 631 | -webkit-transform-origin: 50% 100%; 632 | -webkit-animation: rotateFoldTop .7s both ease; 633 | -moz-transform-origin: 50% 100%; 634 | -moz-animation: rotateFoldTop .7s both ease; 635 | transform-origin: 50% 100%; 636 | animation: rotateFoldTop .7s both ease; 637 | } 638 | .pt-page-rotateFoldBottom { 639 | -webkit-transform-origin: 50% 0%; 640 | -webkit-animation: rotateFoldBottom .7s both ease; 641 | -moz-transform-origin: 50% 0%; 642 | -moz-animation: rotateFoldBottom .7s both ease; 643 | transform-origin: 50% 0%; 644 | animation: rotateFoldBottom .7s both ease; 645 | } 646 | 647 | /* unfold */ 648 | .pt-page-rotateUnfoldLeft { 649 | -webkit-transform-origin: 100% 50%; 650 | -webkit-animation: rotateUnfoldLeft .7s both ease; 651 | -moz-transform-origin: 100% 50%; 652 | -moz-animation: rotateUnfoldLeft .7s both ease; 653 | transform-origin: 100% 50%; 654 | animation: rotateUnfoldLeft .7s both ease; 655 | } 656 | .pt-page-rotateUnfoldRight { 657 | -webkit-transform-origin: 0% 50%; 658 | -webkit-animation: rotateUnfoldRight .7s both ease; 659 | -moz-transform-origin: 0% 50%; 660 | -moz-animation: rotateUnfoldRight .7s both ease; 661 | transform-origin: 0% 50%; 662 | animation: rotateUnfoldRight .7s both ease; 663 | } 664 | .pt-page-rotateUnfoldTop { 665 | -webkit-transform-origin: 50% 100%; 666 | -webkit-animation: rotateUnfoldTop .7s both ease; 667 | -moz-transform-origin: 50% 100%; 668 | -moz-animation: rotateUnfoldTop .7s both ease; 669 | transform-origin: 50% 100%; 670 | animation: rotateUnfoldTop .7s both ease; 671 | } 672 | .pt-page-rotateUnfoldBottom { 673 | -webkit-transform-origin: 50% 0%; 674 | -webkit-animation: rotateUnfoldBottom .7s both ease; 675 | -moz-transform-origin: 50% 0%; 676 | -moz-animation: rotateUnfoldBottom .7s both ease; 677 | transform-origin: 50% 0%; 678 | animation: rotateUnfoldBottom .7s both ease; 679 | } 680 | 681 | /* room walls */ 682 | .pt-page-rotateRoomLeftOut { 683 | -webkit-transform-origin: 100% 50%; 684 | -webkit-animation: rotateRoomLeftOut .8s both ease; 685 | -moz-transform-origin: 100% 50%; 686 | -moz-animation: rotateRoomLeftOut .8s both ease; 687 | transform-origin: 100% 50%; 688 | animation: rotateRoomLeftOut .8s both ease; 689 | } 690 | .pt-page-rotateRoomLeftIn { 691 | -webkit-transform-origin: 0% 50%; 692 | -webkit-animation: rotateRoomLeftIn .8s both ease; 693 | -moz-transform-origin: 0% 50%; 694 | -moz-animation: rotateRoomLeftIn .8s both ease; 695 | transform-origin: 0% 50%; 696 | animation: rotateRoomLeftIn .8s both ease; 697 | } 698 | .pt-page-rotateRoomRightOut { 699 | -webkit-transform-origin: 0% 50%; 700 | -webkit-animation: rotateRoomRightOut .8s both ease; 701 | -moz-transform-origin: 0% 50%; 702 | -moz-animation: rotateRoomRightOut .8s both ease; 703 | transform-origin: 0% 50%; 704 | animation: rotateRoomRightOut .8s both ease; 705 | } 706 | .pt-page-rotateRoomRightIn { 707 | -webkit-transform-origin: 100% 50%; 708 | -webkit-animation: rotateRoomRightIn .8s both ease; 709 | -moz-transform-origin: 100% 50%; 710 | -moz-animation: rotateRoomRightIn .8s both ease; 711 | transform-origin: 100% 50%; 712 | animation: rotateRoomRightIn .8s both ease; 713 | } 714 | .pt-page-rotateRoomTopOut { 715 | -webkit-transform-origin: 50% 100%; 716 | -webkit-animation: rotateRoomTopOut .8s both ease; 717 | -moz-transform-origin: 50% 100%; 718 | -moz-animation: rotateRoomTopOut .8s both ease; 719 | transform-origin: 50% 100%; 720 | animation: rotateRoomTopOut .8s both ease; 721 | } 722 | .pt-page-rotateRoomTopIn { 723 | -webkit-transform-origin: 50% 0%; 724 | -webkit-animation: rotateRoomTopIn .8s both ease; 725 | -moz-transform-origin: 50% 0%; 726 | -moz-animation: rotateRoomTopIn .8s both ease; 727 | transform-origin: 50% 0%; 728 | animation: rotateRoomTopIn .8s both ease; 729 | } 730 | .pt-page-rotateRoomBottomOut { 731 | -webkit-transform-origin: 50% 0%; 732 | -webkit-animation: rotateRoomBottomOut .8s both ease; 733 | -moz-transform-origin: 50% 0%; 734 | -moz-animation: rotateRoomBottomOut .8s both ease; 735 | transform-origin: 50% 0%; 736 | animation: rotateRoomBottomOut .8s both ease; 737 | } 738 | .pt-page-rotateRoomBottomIn { 739 | -webkit-transform-origin: 50% 100%; 740 | -webkit-animation: rotateRoomBottomIn .8s both ease; 741 | -moz-transform-origin: 50% 100%; 742 | -moz-animation: rotateRoomBottomIn .8s both ease; 743 | transform-origin: 50% 100%; 744 | animation: rotateRoomBottomIn .8s both ease; 745 | } 746 | 747 | /* cube */ 748 | .pt-page-rotateCubeLeftOut { 749 | -webkit-transform-origin: 100% 50%; 750 | -webkit-animation: rotateCubeLeftOut .6s both ease-in; 751 | -moz-transform-origin: 100% 50%; 752 | -moz-animation: rotateCubeLeftOut .6s both ease-in; 753 | transform-origin: 100% 50%; 754 | animation: rotateCubeLeftOut .6s both ease-in; 755 | } 756 | .pt-page-rotateCubeLeftIn { 757 | -webkit-transform-origin: 0% 50%; 758 | -webkit-animation: rotateCubeLeftIn .6s both ease-in; 759 | -moz-transform-origin: 0% 50%; 760 | -moz-animation: rotateCubeLeftIn .6s both ease-in; 761 | transform-origin: 0% 50%; 762 | animation: rotateCubeLeftIn .6s both ease-in; 763 | } 764 | .pt-page-rotateCubeRightOut { 765 | -webkit-transform-origin: 0% 50%; 766 | -webkit-animation: rotateCubeRightOut .6s both ease-in; 767 | -moz-transform-origin: 0% 50%; 768 | -moz-animation: rotateCubeRightOut .6s both ease-in; 769 | transform-origin: 0% 50%; 770 | animation: rotateCubeRightOut .6s both ease-in; 771 | } 772 | .pt-page-rotateCubeRightIn { 773 | -webkit-transform-origin: 100% 50%; 774 | -webkit-animation: rotateCubeRightIn .6s both ease-in; 775 | -moz-transform-origin: 100% 50%; 776 | -moz-animation: rotateCubeRightIn .6s both ease-in; 777 | transform-origin: 100% 50%; 778 | animation: rotateCubeRightIn .6s both ease-in; 779 | } 780 | .pt-page-rotateCubeTopOut { 781 | -webkit-transform-origin: 50% 100%; 782 | -webkit-animation: rotateCubeTopOut .6s both ease-in; 783 | -moz-transform-origin: 50% 100%; 784 | -moz-animation: rotateCubeTopOut .6s both ease-in; 785 | transform-origin: 50% 100%; 786 | animation: rotateCubeTopOut .6s both ease-in; 787 | } 788 | .pt-page-rotateCubeTopIn { 789 | -webkit-transform-origin: 50% 0%; 790 | -webkit-animation: rotateCubeTopIn .6s both ease-in; 791 | -moz-transform-origin: 50% 0%; 792 | -moz-animation: rotateCubeTopIn .6s both ease-in; 793 | transform-origin: 50% 0%; 794 | animation: rotateCubeTopIn .6s both ease-in; 795 | } 796 | .pt-page-rotateCubeBottomOut { 797 | -webkit-transform-origin: 50% 0%; 798 | -webkit-animation: rotateCubeBottomOut .6s both ease-in; 799 | -moz-transform-origin: 50% 0%; 800 | -moz-animation: rotateCubeBottomOut .6s both ease-in; 801 | transform-origin: 50% 0%; 802 | animation: rotateCubeBottomOut .6s both ease-in; 803 | } 804 | .pt-page-rotateCubeBottomIn { 805 | -webkit-transform-origin: 50% 100%; 806 | -webkit-animation: rotateCubeBottomIn .6s both ease-in; 807 | -moz-transform-origin: 50% 100%; 808 | -moz-animation: rotateCubeBottomIn .6s both ease-in; 809 | transform-origin: 50% 100%; 810 | animation: rotateCubeBottomIn .6s both ease-in; 811 | } 812 | 813 | /* carousel */ 814 | .pt-page-rotateCarouselLeftOut { 815 | -webkit-transform-origin: 100% 50%; 816 | -webkit-animation: rotateCarouselLeftOut .8s both ease; 817 | -moz-transform-origin: 100% 50%; 818 | -moz-animation: rotateCarouselLeftOut .8s both ease; 819 | transform-origin: 100% 50%; 820 | animation: rotateCarouselLeftOut .8s both ease; 821 | } 822 | .pt-page-rotateCarouselLeftIn { 823 | -webkit-transform-origin: 0% 50%; 824 | -webkit-animation: rotateCarouselLeftIn .8s both ease; 825 | -moz-transform-origin: 0% 50%; 826 | -moz-animation: rotateCarouselLeftIn .8s both ease; 827 | transform-origin: 0% 50%; 828 | animation: rotateCarouselLeftIn .8s both ease; 829 | } 830 | .pt-page-rotateCarouselRightOut { 831 | -webkit-transform-origin: 0% 50%; 832 | -webkit-animation: rotateCarouselRightOut .8s both ease; 833 | -moz-transform-origin: 0% 50%; 834 | -moz-animation: rotateCarouselRightOut .8s both ease; 835 | transform-origin: 0% 50%; 836 | animation: rotateCarouselRightOut .8s both ease; 837 | } 838 | .pt-page-rotateCarouselRightIn { 839 | -webkit-transform-origin: 100% 50%; 840 | -webkit-animation: rotateCarouselRightIn .8s both ease; 841 | -moz-transform-origin: 100% 50%; 842 | -moz-animation: rotateCarouselRightIn .8s both ease; 843 | transform-origin: 100% 50%; 844 | animation: rotateCarouselRightIn .8s both ease; 845 | } 846 | .pt-page-rotateCarouselTopOut { 847 | -webkit-transform-origin: 50% 100%; 848 | -webkit-animation: rotateCarouselTopOut .8s both ease; 849 | -moz-transform-origin: 50% 100%; 850 | -moz-animation: rotateCarouselTopOut .8s both ease; 851 | transform-origin: 50% 100%; 852 | animation: rotateCarouselTopOut .8s both ease; 853 | } 854 | .pt-page-rotateCarouselTopIn { 855 | -webkit-transform-origin: 50% 0%; 856 | -webkit-animation: rotateCarouselTopIn .8s both ease; 857 | -moz-transform-origin: 50% 0%; 858 | -moz-animation: rotateCarouselTopIn .8s both ease; 859 | transform-origin: 50% 0%; 860 | animation: rotateCarouselTopIn .8s both ease; 861 | } 862 | .pt-page-rotateCarouselBottomOut { 863 | -webkit-transform-origin: 50% 0%; 864 | -webkit-animation: rotateCarouselBottomOut .8s both ease; 865 | -moz-transform-origin: 50% 0%; 866 | -moz-animation: rotateCarouselBottomOut .8s both ease; 867 | transform-origin: 50% 0%; 868 | animation: rotateCarouselBottomOut .8s both ease; 869 | } 870 | .pt-page-rotateCarouselBottomIn { 871 | -webkit-transform-origin: 50% 100%; 872 | -webkit-animation: rotateCarouselBottomIn .8s both ease; 873 | -moz-transform-origin: 50% 100%; 874 | -moz-animation: rotateCarouselBottomIn .8s both ease; 875 | transform-origin: 50% 100%; 876 | animation: rotateCarouselBottomIn .8s both ease; 877 | } 878 | 879 | /* sides */ 880 | .pt-page-rotateSidesOut { 881 | -webkit-transform-origin: -50% 50%; 882 | -webkit-animation: rotateSidesOut .5s both ease-in; 883 | -moz-transform-origin: -50% 50%; 884 | -moz-animation: rotateSidesOut .5s both ease-in; 885 | transform-origin: -50% 50%; 886 | animation: rotateSidesOut .5s both ease-in; 887 | } 888 | .pt-page-rotateSidesIn { 889 | -webkit-transform-origin: 150% 50%; 890 | -webkit-animation: rotateSidesIn .5s both ease-out; 891 | -moz-transform-origin: 150% 50%; 892 | -moz-animation: rotateSidesIn .5s both ease-out; 893 | transform-origin: 150% 50%; 894 | animation: rotateSidesIn .5s both ease-out; 895 | } 896 | 897 | /* slide */ 898 | .pt-page-rotateSlideOut { 899 | -webkit-animation: rotateSlideOut 1s both ease; 900 | -moz-animation: rotateSlideOut 1s both ease; 901 | animation: rotateSlideOut 1s both ease; 902 | } 903 | .pt-page-rotateSlideIn { 904 | -webkit-animation: rotateSlideIn 1s both ease; 905 | -moz-animation: rotateSlideIn 1s both ease; 906 | animation: rotateSlideIn 1s both ease; 907 | } 908 | 909 | /********************************* keyframes **************************************/ 910 | 911 | /* rotate sides first and scale */ 912 | 913 | @-webkit-keyframes rotateRightSideFirst { 914 | 40% { -webkit-transform: rotateY(15deg); opacity: .8; -webkit-animation-timing-function: ease-out; } 915 | 100% { -webkit-transform: scale(0.8) translateZ(-200px); opacity:0; } 916 | } 917 | @-moz-keyframes rotateRightSideFirst { 918 | 40% { -moz-transform: rotateY(15deg); opacity: .8; -moz-animation-timing-function: ease-out; } 919 | 100% { -moz-transform: scale(0.8) translateZ(-200px); opacity:0; } 920 | } 921 | @keyframes rotateRightSideFirst { 922 | 40% { transform: rotateY(15deg); opacity: .8; animation-timing-function: ease-out; } 923 | 100% { transform: scale(0.8) translateZ(-200px); opacity:0; } 924 | } 925 | 926 | @-webkit-keyframes rotateLeftSideFirst { 927 | 40% { -webkit-transform: rotateY(-15deg); opacity: .8; -webkit-animation-timing-function: ease-out; } 928 | 100% { -webkit-transform: scale(0.8) translateZ(-200px); opacity:0; } 929 | } 930 | @-moz-keyframes rotateLeftSideFirst { 931 | 40% { -moz-transform: rotateY(-15deg); opacity: .8; -moz-animation-timing-function: ease-out; } 932 | 100% { -moz-transform: scale(0.8) translateZ(-200px); opacity:0; } 933 | } 934 | @keyframes rotateLeftSideFirst { 935 | 40% { transform: rotateY(-15deg); opacity: .8; animation-timing-function: ease-out; } 936 | 100% { transform: scale(0.8) translateZ(-200px); opacity:0; } 937 | } 938 | 939 | @-webkit-keyframes rotateTopSideFirst { 940 | 40% { -webkit-transform: rotateX(15deg); opacity: .8; -webkit-animation-timing-function: ease-out; } 941 | 100% { -webkit-transform: scale(0.8) translateZ(-200px); opacity:0; } 942 | } 943 | @-moz-keyframes rotateTopSideFirst { 944 | 40% { -moz-transform: rotateX(15deg); opacity: .8; -moz-animation-timing-function: ease-out; } 945 | 100% { -moz-transform: scale(0.8) translateZ(-200px); opacity:0; } 946 | } 947 | @keyframes rotateTopSideFirst { 948 | 40% { transform: rotateX(15deg); opacity: .8; animation-timing-function: ease-out; } 949 | 100% { transform: scale(0.8) translateZ(-200px); opacity:0; } 950 | } 951 | 952 | @-webkit-keyframes rotateBottomSideFirst { 953 | 40% { -webkit-transform: rotateX(-15deg); opacity: .8; -webkit-animation-timing-function: ease-out; } 954 | 100% { -webkit-transform: scale(0.8) translateZ(-200px); opacity:0; } 955 | } 956 | @-moz-keyframes rotateBottomSideFirst { 957 | 40% { -moz-transform: rotateX(-15deg); opacity: .8; -moz-animation-timing-function: ease-out; } 958 | 100% { -moz-transform: scale(0.8) translateZ(-200px); opacity:0; } 959 | } 960 | @keyframes rotateBottomSideFirst { 961 | 40% { transform: rotateX(-15deg); opacity: .8; animation-timing-function: ease-out; } 962 | 100% { transform: scale(0.8) translateZ(-200px); opacity:0; } 963 | } 964 | 965 | /* flip */ 966 | 967 | @-webkit-keyframes flipOutRight { 968 | to { -webkit-transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 969 | } 970 | @-moz-keyframes flipOutRight { 971 | to { -moz-transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 972 | } 973 | @keyframes flipOutRight { 974 | to { transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 975 | } 976 | 977 | @-webkit-keyframes flipInLeft { 978 | from { -webkit-transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 979 | } 980 | @-moz-keyframes flipInLeft { 981 | from { -moz-transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 982 | } 983 | @keyframes flipInLeft { 984 | from { transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 985 | } 986 | 987 | @-webkit-keyframes flipOutLeft { 988 | to { -webkit-transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 989 | } 990 | @-moz-keyframes flipOutLeft { 991 | to { -moz-transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 992 | } 993 | @keyframes flipOutLeft { 994 | to { transform: translateZ(-1000px) rotateY(-90deg); opacity: 0.2; } 995 | } 996 | 997 | @-webkit-keyframes flipInRight { 998 | from { -webkit-transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 999 | } 1000 | @-moz-keyframes flipInRight { 1001 | from { -moz-transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 1002 | } 1003 | @keyframes flipInRight { 1004 | from { transform: translateZ(-1000px) rotateY(90deg); opacity: 0.2; } 1005 | } 1006 | 1007 | @-webkit-keyframes flipOutTop { 1008 | to { -webkit-transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1009 | } 1010 | @-moz-keyframes flipOutTop { 1011 | to { -moz-transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1012 | } 1013 | @keyframes flipOutTop { 1014 | to { transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1015 | } 1016 | 1017 | @-webkit-keyframes flipInBottom { 1018 | from { -webkit-transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1019 | } 1020 | @-moz-keyframes flipInBottom { 1021 | from { -moz-transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1022 | } 1023 | @keyframes flipInBottom { 1024 | from { transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1025 | } 1026 | 1027 | @-webkit-keyframes flipOutBottom { 1028 | to { -webkit-transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1029 | } 1030 | @-moz-keyframes flipOutBottom { 1031 | to { -moz-transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1032 | } 1033 | @keyframes flipOutBottom { 1034 | to { transform: translateZ(-1000px) rotateX(-90deg); opacity: 0.2; } 1035 | } 1036 | 1037 | @-webkit-keyframes flipInTop { 1038 | from { -webkit-transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1039 | } 1040 | @-moz-keyframes flipInTop { 1041 | from { -moz-transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1042 | } 1043 | @keyframes flipInTop { 1044 | from { transform: translateZ(-1000px) rotateX(90deg); opacity: 0.2; } 1045 | } 1046 | 1047 | /* fall */ 1048 | 1049 | @-webkit-keyframes rotateFall { 1050 | 0% { -webkit-transform: rotateZ(0deg); } 1051 | 20% { -webkit-transform: rotateZ(10deg); -webkit-animation-timing-function: ease-out; } 1052 | 40% { -webkit-transform: rotateZ(17deg); } 1053 | 60% { -webkit-transform: rotateZ(16deg); } 1054 | 100% { -webkit-transform: translateY(100%) rotateZ(17deg); } 1055 | } 1056 | @-moz-keyframes rotateFall { 1057 | 0% { -moz-transform: rotateZ(0deg); } 1058 | 20% { -moz-transform: rotateZ(10deg); -moz-animation-timing-function: ease-out; } 1059 | 40% { -moz-transform: rotateZ(17deg); } 1060 | 60% { -moz-transform: rotateZ(16deg); } 1061 | 100% { -moz-transform: translateY(100%) rotateZ(17deg); } 1062 | } 1063 | @keyframes rotateFall { 1064 | 0% { transform: rotateZ(0deg); } 1065 | 20% { transform: rotateZ(10deg); animation-timing-function: ease-out; } 1066 | 40% { transform: rotateZ(17deg); } 1067 | 60% { transform: rotateZ(16deg); } 1068 | 100% { transform: translateY(100%) rotateZ(17deg); } 1069 | } 1070 | 1071 | /* newspaper */ 1072 | 1073 | @-webkit-keyframes rotateOutNewspaper { 1074 | to { -webkit-transform: translateZ(-3000px) rotateZ(360deg); opacity: 0; } 1075 | } 1076 | @-moz-keyframes rotateOutNewspaper { 1077 | to { -moz-transform: translateZ(-3000px) rotateZ(360deg); opacity: 0; } 1078 | } 1079 | @keyframes rotateOutNewspaper { 1080 | to { transform: translateZ(-3000px) rotateZ(360deg); opacity: 0; } 1081 | } 1082 | 1083 | @-webkit-keyframes rotateInNewspaper { 1084 | from { -webkit-transform: translateZ(-3000px) rotateZ(-360deg); opacity: 0; } 1085 | } 1086 | @-moz-keyframes rotateInNewspaper { 1087 | from { -moz-transform: translateZ(-3000px) rotateZ(-360deg); opacity: 0; } 1088 | } 1089 | @keyframes rotateInNewspaper { 1090 | from { transform: translateZ(-3000px) rotateZ(-360deg); opacity: 0; } 1091 | } 1092 | 1093 | /* push */ 1094 | 1095 | @-webkit-keyframes rotatePushLeft { 1096 | to { opacity: 0; -webkit-transform: rotateY(90deg); } 1097 | } 1098 | @-moz-keyframes rotatePushLeft { 1099 | to { opacity: 0; -moz-transform: rotateY(90deg); } 1100 | } 1101 | @keyframes rotatePushLeft { 1102 | to { opacity: 0; transform: rotateY(90deg); } 1103 | } 1104 | 1105 | @-webkit-keyframes rotatePushRight { 1106 | to { opacity: 0; -webkit-transform: rotateY(-90deg); } 1107 | } 1108 | @-moz-keyframes rotatePushRight { 1109 | to { opacity: 0; -moz-transform: rotateY(-90deg); } 1110 | } 1111 | @keyframes rotatePushRight { 1112 | to { opacity: 0; transform: rotateY(-90deg); } 1113 | } 1114 | 1115 | @-webkit-keyframes rotatePushTop { 1116 | to { opacity: 0; -webkit-transform: rotateX(-90deg); } 1117 | } 1118 | @-moz-keyframes rotatePushTop { 1119 | to { opacity: 0; -moz-transform: rotateX(-90deg); } 1120 | } 1121 | @keyframes rotatePushTop { 1122 | to { opacity: 0; transform: rotateX(-90deg); } 1123 | } 1124 | 1125 | @-webkit-keyframes rotatePushBottom { 1126 | to { opacity: 0; -webkit-transform: rotateX(90deg); } 1127 | } 1128 | @-moz-keyframes rotatePushBottom { 1129 | to { opacity: 0; -moz-transform: rotateX(90deg); } 1130 | } 1131 | @keyframes rotatePushBottom { 1132 | to { opacity: 0; transform: rotateX(90deg); } 1133 | } 1134 | 1135 | /* pull */ 1136 | 1137 | @-webkit-keyframes rotatePullRight { 1138 | from { opacity: 0; -webkit-transform: rotateY(-90deg); } 1139 | } 1140 | @-moz-keyframes rotatePullRight { 1141 | from { opacity: 0; -moz-transform: rotateY(-90deg); } 1142 | } 1143 | @keyframes rotatePullRight { 1144 | from { opacity: 0; transform: rotateY(-90deg); } 1145 | } 1146 | 1147 | @-webkit-keyframes rotatePullLeft { 1148 | from { opacity: 0; -webkit-transform: rotateY(90deg); } 1149 | } 1150 | @-moz-keyframes rotatePullLeft { 1151 | from { opacity: 0; -moz-transform: rotateY(90deg); } 1152 | } 1153 | @keyframes rotatePullLeft { 1154 | from { opacity: 0; transform: rotateY(90deg); } 1155 | } 1156 | 1157 | @-webkit-keyframes rotatePullTop { 1158 | from { opacity: 0; -webkit-transform: rotateX(-90deg); } 1159 | } 1160 | @-moz-keyframes rotatePullTop { 1161 | from { opacity: 0; -moz-transform: rotateX(-90deg); } 1162 | } 1163 | @keyframes rotatePullTop { 1164 | from { opacity: 0; transform: rotateX(-90deg); } 1165 | } 1166 | 1167 | @-webkit-keyframes rotatePullBottom { 1168 | from { opacity: 0; -webkit-transform: rotateX(90deg); } 1169 | } 1170 | @-moz-keyframes rotatePullBottom { 1171 | from { opacity: 0; -moz-transform: rotateX(90deg); } 1172 | } 1173 | @keyframes rotatePullBottom { 1174 | from { opacity: 0; transform: rotateX(90deg); } 1175 | } 1176 | 1177 | /* fold */ 1178 | 1179 | @-webkit-keyframes rotateFoldRight { 1180 | to { opacity: 0; -webkit-transform: translateX(100%) rotateY(90deg); } 1181 | } 1182 | @-moz-keyframes rotateFoldRight { 1183 | to { opacity: 0; -moz-transform: translateX(100%) rotateY(90deg); } 1184 | } 1185 | @keyframes rotateFoldRight { 1186 | to { opacity: 0; transform: translateX(100%) rotateY(90deg); } 1187 | } 1188 | 1189 | @-webkit-keyframes rotateFoldLeft { 1190 | to { opacity: 0; -webkit-transform: translateX(-100%) rotateY(-90deg); } 1191 | } 1192 | @-moz-keyframes rotateFoldLeft { 1193 | to { opacity: 0; -moz-transform: translateX(-100%) rotateY(-90deg); } 1194 | } 1195 | @keyframes rotateFoldLeft { 1196 | to { opacity: 0; transform: translateX(-100%) rotateY(-90deg); } 1197 | } 1198 | 1199 | @-webkit-keyframes rotateFoldTop { 1200 | to { opacity: 0; -webkit-transform: translateY(-100%) rotateX(90deg); } 1201 | } 1202 | @-moz-keyframes rotateFoldTop { 1203 | to { opacity: 0; -moz-transform: translateY(-100%) rotateX(90deg); } 1204 | } 1205 | @keyframes rotateFoldTop { 1206 | to { opacity: 0; transform: translateY(-100%) rotateX(90deg); } 1207 | } 1208 | 1209 | @-webkit-keyframes rotateFoldBottom { 1210 | to { opacity: 0; -webkit-transform: translateY(100%) rotateX(-90deg); } 1211 | } 1212 | @-moz-keyframes rotateFoldBottom { 1213 | to { opacity: 0; -moz-transform: translateY(100%) rotateX(-90deg); } 1214 | } 1215 | @keyframes rotateFoldBottom { 1216 | to { opacity: 0; transform: translateY(100%) rotateX(-90deg); } 1217 | } 1218 | 1219 | /* unfold */ 1220 | 1221 | @-webkit-keyframes rotateUnfoldLeft { 1222 | from { opacity: 0; -webkit-transform: translateX(-100%) rotateY(-90deg); } 1223 | } 1224 | @-moz-keyframes rotateUnfoldLeft { 1225 | from { opacity: 0; -moz-transform: translateX(-100%) rotateY(-90deg); } 1226 | } 1227 | @keyframes rotateUnfoldLeft { 1228 | from { opacity: 0; transform: translateX(-100%) rotateY(-90deg); } 1229 | } 1230 | 1231 | @-webkit-keyframes rotateUnfoldRight { 1232 | from { opacity: 0; -webkit-transform: translateX(100%) rotateY(90deg); } 1233 | } 1234 | @-moz-keyframes rotateUnfoldRight { 1235 | from { opacity: 0; -moz-transform: translateX(100%) rotateY(90deg); } 1236 | } 1237 | @keyframes rotateUnfoldRight { 1238 | from { opacity: 0; transform: translateX(100%) rotateY(90deg); } 1239 | } 1240 | 1241 | @-webkit-keyframes rotateUnfoldTop { 1242 | from { opacity: 0; -webkit-transform: translateY(-100%) rotateX(90deg); } 1243 | } 1244 | @-moz-keyframes rotateUnfoldTop { 1245 | from { opacity: 0; -moz-transform: translateY(-100%) rotateX(90deg); } 1246 | } 1247 | @keyframes rotateUnfoldTop { 1248 | from { opacity: 0; transform: translateY(-100%) rotateX(90deg); } 1249 | } 1250 | 1251 | @-webkit-keyframes rotateUnfoldBottom { 1252 | from { opacity: 0; -webkit-transform: translateY(100%) rotateX(-90deg); } 1253 | } 1254 | @-moz-keyframes rotateUnfoldBottom { 1255 | from { opacity: 0; -moz-transform: translateY(100%) rotateX(-90deg); } 1256 | } 1257 | @keyframes rotateUnfoldBottom { 1258 | from { opacity: 0; transform: translateY(100%) rotateX(-90deg); } 1259 | } 1260 | 1261 | /* room walls */ 1262 | 1263 | @-webkit-keyframes rotateRoomLeftOut { 1264 | to { opacity: .3; -webkit-transform: translateX(-100%) rotateY(90deg); } 1265 | } 1266 | @-moz-keyframes rotateRoomLeftOut { 1267 | to { opacity: .3; -moz-transform: translateX(-100%) rotateY(90deg); } 1268 | } 1269 | @keyframes rotateRoomLeftOut { 1270 | to { opacity: .3; transform: translateX(-100%) rotateY(90deg); } 1271 | } 1272 | 1273 | @-webkit-keyframes rotateRoomLeftIn { 1274 | from { opacity: .3; -webkit-transform: translateX(100%) rotateY(-90deg); } 1275 | } 1276 | @-moz-keyframes rotateRoomLeftIn { 1277 | from { opacity: .3; -moz-transform: translateX(100%) rotateY(-90deg); } 1278 | } 1279 | @keyframes rotateRoomLeftIn { 1280 | from { opacity: .3; transform: translateX(100%) rotateY(-90deg); } 1281 | } 1282 | 1283 | @-webkit-keyframes rotateRoomRightOut { 1284 | to { opacity: .3; -webkit-transform: translateX(100%) rotateY(-90deg); } 1285 | } 1286 | @-moz-keyframes rotateRoomRightOut { 1287 | to { opacity: .3; -moz-transform: translateX(100%) rotateY(-90deg); } 1288 | } 1289 | @keyframes rotateRoomRightOut { 1290 | to { opacity: .3; transform: translateX(100%) rotateY(-90deg); } 1291 | } 1292 | 1293 | @-webkit-keyframes rotateRoomRightIn { 1294 | from { opacity: .3; -webkit-transform: translateX(-100%) rotateY(90deg); } 1295 | } 1296 | @-moz-keyframes rotateRoomRightIn { 1297 | from { opacity: .3; -moz-transform: translateX(-100%) rotateY(90deg); } 1298 | } 1299 | @keyframes rotateRoomRightIn { 1300 | from { opacity: .3; transform: translateX(-100%) rotateY(90deg); } 1301 | } 1302 | 1303 | @-webkit-keyframes rotateRoomTopOut { 1304 | to { opacity: .3; -webkit-transform: translateY(-100%) rotateX(-90deg); } 1305 | } 1306 | @-moz-keyframes rotateRoomTopOut { 1307 | to { opacity: .3; -moz-transform: translateY(-100%) rotateX(-90deg); } 1308 | } 1309 | @keyframes rotateRoomTopOut { 1310 | to { opacity: .3; transform: translateY(-100%) rotateX(-90deg); } 1311 | } 1312 | 1313 | @-webkit-keyframes rotateRoomTopIn { 1314 | from { opacity: .3; -webkit-transform: translateY(100%) rotateX(90deg); } 1315 | } 1316 | @-moz-keyframes rotateRoomTopIn { 1317 | from { opacity: .3; -moz-transform: translateY(100%) rotateX(90deg); } 1318 | } 1319 | @keyframes rotateRoomTopIn { 1320 | from { opacity: .3; transform: translateY(100%) rotateX(90deg); } 1321 | } 1322 | 1323 | @-webkit-keyframes rotateRoomBottomOut { 1324 | to { opacity: .3; -webkit-transform: translateY(100%) rotateX(90deg); } 1325 | } 1326 | @-moz-keyframes rotateRoomBottomOut { 1327 | to { opacity: .3; -moz-transform: translateY(100%) rotateX(90deg); } 1328 | } 1329 | @keyframes rotateRoomBottomOut { 1330 | to { opacity: .3; transform: translateY(100%) rotateX(90deg); } 1331 | } 1332 | 1333 | @-webkit-keyframes rotateRoomBottomIn { 1334 | from { opacity: .3; -webkit-transform: translateY(-100%) rotateX(-90deg); } 1335 | } 1336 | @-moz-keyframes rotateRoomBottomIn { 1337 | from { opacity: .3; -moz-transform: translateY(-100%) rotateX(-90deg); } 1338 | } 1339 | @keyframes rotateRoomBottomIn { 1340 | from { opacity: .3; transform: translateY(-100%) rotateX(-90deg); } 1341 | } 1342 | 1343 | /* cube */ 1344 | 1345 | @-webkit-keyframes rotateCubeLeftOut { 1346 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1347 | 100% { opacity: .3; -webkit-transform: translateX(-100%) rotateY(-90deg); } 1348 | } 1349 | @-moz-keyframes rotateCubeLeftOut { 1350 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1351 | 100% { opacity: .3; -moz-transform: translateX(-100%) rotateY(-90deg); } 1352 | } 1353 | @keyframes rotateCubeLeftOut { 1354 | 50% { animation-timing-function: ease-out; transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1355 | 100% { opacity: .3; transform: translateX(-100%) rotateY(-90deg); } 1356 | } 1357 | 1358 | @-webkit-keyframes rotateCubeLeftIn { 1359 | 0% { opacity: .3; -webkit-transform: translateX(100%) rotateY(90deg); } 1360 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1361 | } 1362 | @-moz-keyframes rotateCubeLeftIn { 1363 | 0% { opacity: .3; -moz-transform: translateX(100%) rotateY(90deg); } 1364 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1365 | } 1366 | @keyframes rotateCubeLeftIn { 1367 | 0% { opacity: .3; transform: translateX(100%) rotateY(90deg); } 1368 | 50% { animation-timing-function: ease-out; transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1369 | } 1370 | 1371 | @-webkit-keyframes rotateCubeRightOut { 1372 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1373 | 100% { opacity: .3; -webkit-transform: translateX(100%) rotateY(90deg); } 1374 | } 1375 | @-moz-keyframes rotateCubeRightOut { 1376 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1377 | 100% { opacity: .3; -moz-transform: translateX(100%) rotateY(90deg); } 1378 | } 1379 | @keyframes rotateCubeRightOut { 1380 | 50% { animation-timing-function: ease-out; transform: translateX(50%) translateZ(-200px) rotateY(45deg); } 1381 | 100% { opacity: .3; transform: translateX(100%) rotateY(90deg); } 1382 | } 1383 | 1384 | @-webkit-keyframes rotateCubeRightIn { 1385 | 0% { opacity: .3; -webkit-transform: translateX(-100%) rotateY(-90deg); } 1386 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1387 | } 1388 | @-moz-keyframes rotateCubeRightIn { 1389 | 0% { opacity: .3; -moz-transform: translateX(-100%) rotateY(-90deg); } 1390 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1391 | } 1392 | @keyframes rotateCubeRightIn { 1393 | 0% { opacity: .3; transform: translateX(-100%) rotateY(-90deg); } 1394 | 50% { animation-timing-function: ease-out; transform: translateX(-50%) translateZ(-200px) rotateY(-45deg); } 1395 | } 1396 | 1397 | @-webkit-keyframes rotateCubeTopOut { 1398 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1399 | 100% { opacity: .3; -webkit-transform: translateY(-100%) rotateX(90deg); } 1400 | } 1401 | @-moz-keyframes rotateCubeTopOut { 1402 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1403 | 100% { opacity: .3; -moz-transform: translateY(-100%) rotateX(90deg); } 1404 | } 1405 | @keyframes rotateCubeTopOut { 1406 | 50% { animation-timing-function: ease-out; transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1407 | 100% { opacity: .3; transform: translateY(-100%) rotateX(90deg); } 1408 | } 1409 | 1410 | @-webkit-keyframes rotateCubeTopIn { 1411 | 0% { opacity: .3; -webkit-transform: translateY(100%) rotateX(-90deg); } 1412 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1413 | } 1414 | @-moz-keyframes rotateCubeTopIn { 1415 | 0% { opacity: .3; -moz-transform: translateY(100%) rotateX(-90deg); } 1416 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1417 | } 1418 | @keyframes rotateCubeTopIn { 1419 | 0% { opacity: .3; transform: translateY(100%) rotateX(-90deg); } 1420 | 50% { animation-timing-function: ease-out; transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1421 | } 1422 | 1423 | @-webkit-keyframes rotateCubeBottomOut { 1424 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1425 | 100% { opacity: .3; -webkit-transform: translateY(100%) rotateX(-90deg); } 1426 | } 1427 | @-moz-keyframes rotateCubeBottomOut { 1428 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1429 | 100% { opacity: .3; -moz-transform: translateY(100%) rotateX(-90deg); } 1430 | } 1431 | @keyframes rotateCubeBottomOut { 1432 | 50% { animation-timing-function: ease-out; transform: translateY(50%) translateZ(-200px) rotateX(-45deg); } 1433 | 100% { opacity: .3; transform: translateY(100%) rotateX(-90deg); } 1434 | } 1435 | 1436 | @-webkit-keyframes rotateCubeBottomIn { 1437 | 0% { opacity: .3; -webkit-transform: translateY(-100%) rotateX(90deg); } 1438 | 50% { -webkit-animation-timing-function: ease-out; -webkit-transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1439 | } 1440 | @-moz-keyframes rotateCubeBottomIn { 1441 | 0% { opacity: .3; -moz-transform: translateY(-100%) rotateX(90deg); } 1442 | 50% { -moz-animation-timing-function: ease-out; -moz-transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1443 | } 1444 | @keyframes rotateCubeBottomIn { 1445 | 0% { opacity: .3; transform: translateY(-100%) rotateX(90deg); } 1446 | 50% { animation-timing-function: ease-out; transform: translateY(-50%) translateZ(-200px) rotateX(45deg); } 1447 | } 1448 | 1449 | /* carousel */ 1450 | 1451 | @-webkit-keyframes rotateCarouselLeftOut { 1452 | to { opacity: .3; -webkit-transform: translateX(-150%) scale(.4) rotateY(-65deg); } 1453 | } 1454 | @-moz-keyframes rotateCarouselLeftOut { 1455 | to { opacity: .3; -moz-transform: translateX(-150%) scale(.4) rotateY(-65deg); } 1456 | } 1457 | @keyframes rotateCarouselLeftOut { 1458 | to { opacity: .3; transform: translateX(-150%) scale(.4) rotateY(-65deg); } 1459 | } 1460 | 1461 | @-webkit-keyframes rotateCarouselLeftIn { 1462 | from { opacity: .3; -webkit-transform: translateX(200%) scale(.4) rotateY(65deg); } 1463 | } 1464 | @-moz-keyframes rotateCarouselLeftIn { 1465 | from { opacity: .3; -moz-transform: translateX(200%) scale(.4) rotateY(65deg); } 1466 | } 1467 | @keyframes rotateCarouselLeftIn { 1468 | from { opacity: .3; transform: translateX(200%) scale(.4) rotateY(65deg); } 1469 | } 1470 | 1471 | @-webkit-keyframes rotateCarouselRightOut { 1472 | to { opacity: .3; -webkit-transform: translateX(200%) scale(.4) rotateY(65deg); } 1473 | } 1474 | @-moz-keyframes rotateCarouselRightOut { 1475 | to { opacity: .3; -moz-transform: translateX(200%) scale(.4) rotateY(65deg); } 1476 | } 1477 | @keyframes rotateCarouselRightOut { 1478 | to { opacity: .3; transform: translateX(200%) scale(.4) rotateY(65deg); } 1479 | } 1480 | 1481 | @-webkit-keyframes rotateCarouselRightIn { 1482 | from { opacity: .3; -webkit-transform: translateX(-200%) scale(.4) rotateY(-65deg); } 1483 | } 1484 | @-moz-keyframes rotateCarouselRightIn { 1485 | from { opacity: .3; -moz-transform: translateX(-200%) scale(.4) rotateY(-65deg); } 1486 | } 1487 | @keyframes rotateCarouselRightIn { 1488 | from { opacity: .3; transform: translateX(-200%) scale(.4) rotateY(-65deg); } 1489 | } 1490 | 1491 | @-webkit-keyframes rotateCarouselTopOut { 1492 | to { opacity: .3; -webkit-transform: translateY(-200%) scale(.4) rotateX(65deg); } 1493 | } 1494 | @-moz-keyframes rotateCarouselTopOut { 1495 | to { opacity: .3; -moz-transform: translateY(-200%) scale(.4) rotateX(65deg); } 1496 | } 1497 | @keyframes rotateCarouselTopOut { 1498 | to { opacity: .3; transform: translateY(-200%) scale(.4) rotateX(65deg); } 1499 | } 1500 | 1501 | @-webkit-keyframes rotateCarouselTopIn { 1502 | from { opacity: .3; -webkit-transform: translateY(200%) scale(.4) rotateX(-65deg); } 1503 | } 1504 | @-moz-keyframes rotateCarouselTopIn { 1505 | from { opacity: .3; -moz-transform: translateY(200%) scale(.4) rotateX(-65deg); } 1506 | } 1507 | @keyframes rotateCarouselTopIn { 1508 | from { opacity: .3; transform: translateY(200%) scale(.4) rotateX(-65deg); } 1509 | } 1510 | 1511 | @-webkit-keyframes rotateCarouselBottomOut { 1512 | to { opacity: .3; -webkit-transform: translateY(200%) scale(.4) rotateX(-65deg); } 1513 | } 1514 | @-moz-keyframes rotateCarouselBottomOut { 1515 | to { opacity: .3; -moz-transform: translateY(200%) scale(.4) rotateX(-65deg); } 1516 | } 1517 | @keyframes rotateCarouselBottomOut { 1518 | to { opacity: .3; transform: translateY(200%) scale(.4) rotateX(-65deg); } 1519 | } 1520 | 1521 | @-webkit-keyframes rotateCarouselBottomIn { 1522 | from { opacity: .3; -webkit-transform: translateY(-200%) scale(.4) rotateX(65deg); } 1523 | } 1524 | @-moz-keyframes rotateCarouselBottomIn { 1525 | from { opacity: .3; -moz-transform: translateY(-200%) scale(.4) rotateX(65deg); } 1526 | } 1527 | @keyframes rotateCarouselBottomIn { 1528 | from { opacity: .3; transform: translateY(-200%) scale(.4) rotateX(65deg); } 1529 | } 1530 | 1531 | /* sides */ 1532 | 1533 | @-webkit-keyframes rotateSidesOut { 1534 | to { opacity: 0; -webkit-transform: translateZ(-500px) rotateY(90deg); } 1535 | } 1536 | @-moz-keyframes rotateSidesOut { 1537 | to { opacity: 0; -moz-transform: translateZ(-500px) rotateY(90deg); } 1538 | } 1539 | @keyframes rotateSidesOut { 1540 | to { opacity: 0; transform: translateZ(-500px) rotateY(90deg); } 1541 | } 1542 | 1543 | @-webkit-keyframes rotateSidesIn { 1544 | from { opacity: 0; -webkit-transform: translateZ(-500px) rotateY(-90deg); } 1545 | } 1546 | @-moz-keyframes rotateSidesIn { 1547 | from { opacity: 0; -moz-transform: translateZ(-500px) rotateY(-90deg); } 1548 | } 1549 | @keyframes rotateSidesIn { 1550 | from { opacity: 0; transform: translateZ(-500px) rotateY(-90deg); } 1551 | } 1552 | 1553 | /* slide */ 1554 | 1555 | @-webkit-keyframes rotateSlideOut { 1556 | 25% { opacity: .5; -webkit-transform: translateZ(-500px); } 1557 | 75% { opacity: .5; -webkit-transform: translateZ(-500px) translateX(-200%); } 1558 | 100% { opacity: .5; -webkit-transform: translateZ(-500px) translateX(-200%); } 1559 | } 1560 | @-moz-keyframes rotateSlideOut { 1561 | 25% { opacity: .5; -moz-transform: translateZ(-500px); } 1562 | 75% { opacity: .5; -moz-transform: translateZ(-500px) translateX(-200%); } 1563 | 100% { opacity: .5; -moz-transform: translateZ(-500px) translateX(-200%); } 1564 | } 1565 | @keyframes rotateSlideOut { 1566 | 25% { opacity: .5; transform: translateZ(-500px); } 1567 | 75% { opacity: .5; transform: translateZ(-500px) translateX(-200%); } 1568 | 100% { opacity: .5; transform: translateZ(-500px) translateX(-200%); } 1569 | } 1570 | 1571 | @-webkit-keyframes rotateSlideIn { 1572 | 0%, 25% { opacity: .5; -webkit-transform: translateZ(-500px) translateX(200%); } 1573 | 75% { opacity: .5; -webkit-transform: translateZ(-500px); } 1574 | 100% { opacity: 1; -webkit-transform: translateZ(0) translateX(0); } 1575 | } 1576 | @-moz-keyframes rotateSlideIn { 1577 | 0%, 25% { opacity: .5; -moz-transform: translateZ(-500px) translateX(200%); } 1578 | 75% { opacity: .5; -moz-transform: translateZ(-500px); } 1579 | 100% { opacity: 1; -moz-transform: translateZ(0) translateX(0); } 1580 | } 1581 | @keyframes rotateSlideIn { 1582 | 0%, 25% { opacity: .5; transform: translateZ(-500px) translateX(200%); } 1583 | 75% { opacity: .5; transform: translateZ(-500px); } 1584 | 100% { opacity: 1; transform: translateZ(0) translateX(0); } 1585 | } 1586 | 1587 | /* animation delay classes */ 1588 | 1589 | .pt-page-delay100 { 1590 | -webkit-animation-delay: .1s; 1591 | -moz-animation-delay: .1s; 1592 | animation-delay: .1s; 1593 | } 1594 | .pt-page-delay180 { 1595 | -webkit-animation-delay: .180s; 1596 | -moz-animation-delay: .180s; 1597 | animation-delay: .180s; 1598 | } 1599 | .pt-page-delay200 { 1600 | -webkit-animation-delay: .2s; 1601 | -moz-animation-delay: .2s; 1602 | animation-delay: .2s; 1603 | } 1604 | .pt-page-delay300 { 1605 | -webkit-animation-delay: .3s; 1606 | -moz-animation-delay: .3s; 1607 | animation-delay: .3s; 1608 | } 1609 | .pt-page-delay400 { 1610 | -webkit-animation-delay: .4s; 1611 | -moz-animation-delay: .4s; 1612 | animation-delay: .4s; 1613 | } 1614 | .pt-page-delay500 { 1615 | -webkit-animation-delay: .5s; 1616 | -moz-animation-delay: .5s; 1617 | animation-delay: .5s; 1618 | } 1619 | .pt-page-delay700 { 1620 | -webkit-animation-delay: .7s; 1621 | -moz-animation-delay: .7s; 1622 | animation-delay: .7s; 1623 | } 1624 | .pt-page-delay1000 { 1625 | -webkit-animation-delay: 1s; 1626 | -moz-animation-delay: 1s; 1627 | animation-delay: 1s; 1628 | } -------------------------------------------------------------------------------- /app/styles/main.less: -------------------------------------------------------------------------------- 1 | @import "../components/bootstrap/less/variables.less"; 2 | @import "../components/bootstrap/less/mixins.less"; 3 | @import "../components/bootstrap/less/utilities.less"; 4 | @import "includes/animations.less"; 5 | @import "includes/font-awesome.less"; 6 | @import "workouts.less"; 7 | 8 | body { 9 | color: #fff; 10 | background: #333; 11 | overflow: hidden; 12 | } 13 | 14 | .pagination-centered { 15 | .button { 16 | margin: 2em auto; 17 | } 18 | } 19 | 20 | @font-face { 21 | font-family: 'Satisfy'; 22 | src: url('./fonts/satisfy-webfont.woff?v=1.0.0') format('woff'), url('./fonts/satisfy-webfont.ttf?v=1.0.0') format('truetype'); 23 | font-weight: normal; 24 | font-style: normal; 25 | } 26 | 27 | 28 | h1 { 29 | font-weight: 300; 30 | font-size: 2em; 31 | line-height: 1; 32 | letter-spacing: 6px; 33 | margin: 0; 34 | top: 12%; 35 | width: 100%; 36 | text-align: center; 37 | text-transform: uppercase; 38 | word-spacing: -0.3em; 39 | 40 | 41 | @media all and (device-width: 768px) and (device-height: 1024px) and (orientation:portrait) { 42 | font-size: 3em; 43 | } 44 | @media all and (device-width: 768px) and (device-height: 1024px) and (orientation:landscape) { 45 | font-size: 4em; 46 | } 47 | 48 | > strong { 49 | color: rgba(255, 255, 255, 0.9); 50 | // color: rgba(0,0,0,0.1); 51 | } 52 | > span { 53 | font-family: 'Satisfy', serif; 54 | font-weight: 400; 55 | font-size: 80%; 56 | text-transform: none; 57 | word-spacing: 0; 58 | letter-spacing: 0; 59 | display: block; 60 | opacity: 0.4; 61 | } 62 | } 63 | 64 | 65 | // PAGES 66 | // ----- 67 | 68 | .content { 69 | position: relative; 70 | text-align: center; 71 | .content-title { 72 | -webkit-box-sizing: border-box; 73 | padding: 0 4em; 74 | width: 100%; 75 | margin-top: 10%; 76 | } 77 | .timer { 78 | position: absolute; 79 | top: 20%; 80 | width: 100%; 81 | // z-index: 3; 82 | text-align: center; 83 | font-weight: 600; 84 | font-size: 8em; 85 | color: #fff; 86 | margin-top: .5em; 87 | } 88 | .picture-holder { 89 | z-index:2; 90 | position: absolute; 91 | top: 25%; 92 | width: 100%; 93 | .picture { 94 | margin: auto; 95 | width: 50%; 96 | height: 0; 97 | padding-bottom: 50%; 98 | @media all and (orientation:landscape) { 99 | width: 39%; 100 | padding-bottom: 39%; 101 | } 102 | } 103 | } 104 | } 105 | 106 | .content-main { 107 | .config-menu { 108 | position: absolute; 109 | width: 100%; 110 | top: 0px; 111 | left: 0px; 112 | } 113 | .btn-minus { 114 | position: absolute; 115 | top: 0px; 116 | left: 0px; 117 | } 118 | .btn-plus { 119 | position: absolute; 120 | top: 0px; 121 | right: 0px; 122 | } 123 | } 124 | 125 | .content-step, .content-rest { 126 | i.icon-pause { 127 | position: absolute; 128 | bottom: 20px; 129 | left: 0; 130 | text-align: center; 131 | width: 100%; 132 | font-size: 50px; 133 | color: rgba(255, 255, 255, .8); 134 | } 135 | } 136 | 137 | .content-rest { 138 | .workout-next { 139 | -webkit-box-sizing: border-box; 140 | padding: 0 2em; 141 | position: absolute; 142 | bottom: 15%; 143 | width: 100%; 144 | @media all and (orientation:landscape) { 145 | bottom: 10%; 146 | } 147 | span { 148 | font-size: 1em; 149 | text-align: center; 150 | // word-spacing: -0.3em; 151 | } 152 | } 153 | } 154 | 155 | .content-done { 156 | h1 { 157 | span { 158 | font-size: 200%; 159 | } 160 | margin-bottom: 1em; 161 | } 162 | .icon-trophy { 163 | font-size: 12vw; 164 | } 165 | } 166 | 167 | header { 168 | height: .8em; 169 | position: absolute; 170 | top: 0px; 171 | left: 0px; 172 | right: 0px; 173 | } 174 | 175 | footer { 176 | z-index: 2; 177 | position: absolute; 178 | bottom: 0px; 179 | left: 0px; 180 | right: 0px; 181 | } 182 | 183 | header { 184 | .exit { 185 | z-index: 999; 186 | padding: .5em; 187 | font-size: 200%; 188 | color: rgba(255, 255, 255, .4); 189 | } 190 | } 191 | 192 | .progress-bar { 193 | position: absolute; 194 | bottom: 0px; 195 | background: rgba(255, 255, 255, .4); 196 | width: 100%; 197 | height: .8em; 198 | div { 199 | background: rgba(255, 255, 255, .8); 200 | height: 100%; 201 | } 202 | } 203 | 204 | // GLOBAL STYLES 205 | // ------------- 206 | 207 | .content-main, .content-rest { 208 | background: #a960d6; 209 | } 210 | .content-step-1, .content-step-7 { 211 | background: #0ac2d2; 212 | } 213 | .content-step-2, .content-step-8 { 214 | background: #7bb7fa; 215 | } 216 | .content-step-3, .content-step-9, .content-done { 217 | background: #60d7a9; 218 | } 219 | .content-step-4, .content-step-10 { 220 | background: #fdc162; 221 | } 222 | .content-step-5, .content-step-11 { 223 | background: #fd6a62; 224 | } 225 | .content-step-6, .content-step-12 { 226 | background: #f68dbb; 227 | } 228 | 229 | 230 | .container-perspective { 231 | position: relative; 232 | width: 100%; 233 | height: 100%; 234 | -webkit-perspective: 1200px; 235 | -moz-perspective: 1200px; 236 | perspective: 1200px; 237 | -webkit-transform-style: preserve-3d; 238 | -moz-transform-style: preserve-3d; 239 | transform-style: preserve-3d; 240 | } 241 | 242 | .content { 243 | width: 100%; 244 | height: 100%; 245 | // // visibility: hidden; 246 | // overflow: hidden; 247 | // -webkit-backface-visibility: hidden; 248 | // -moz-backface-visibility: hidden; 249 | // backface-visibility: hidden; 250 | // -webkit-transform: translate3d(0, 0, 0); 251 | // -moz-transform: translate3d(0, 0, 0); 252 | // transform: translate3d(0, 0, 0); 253 | } 254 | 255 | .btn-icon { 256 | padding: 10px 20px; 257 | background: rgba(255, 255, 255, .25); 258 | color: white; 259 | } 260 | 261 | .button { 262 | z-index: 2; 263 | border: none; 264 | font-size: 15px; 265 | font-weight: 700; 266 | text-transform: uppercase; 267 | 268 | margin: 10px 0 20px; 269 | padding: 0px 20px; 270 | line-height: 50px; 271 | height: 50px; 272 | letter-spacing: 1px; 273 | 274 | cursor: pointer; 275 | display: block; 276 | // font-family: 'Lato', Calibri, Arial, sans-serif; 277 | box-shadow: 0 3px 0 rgba(0,0,0,0.1); 278 | border-radius: 0px; 279 | } 280 | 281 | 282 | 283 | 284 | 285 | // TRANSITIONS 286 | // ----------- 287 | -------------------------------------------------------------------------------- /app/styles/workouts.less: -------------------------------------------------------------------------------- 1 | 2 | // WORKOUTS 3 | // -------- 4 | 5 | .workout-jumping-jacks { 6 | .picture { 7 | background: transparent url("./../images/workouts/jumping-jacks.png") no-repeat 0 0; 8 | background-size: 100%; 9 | } 10 | } 11 | .workout-wall-sit { 12 | .picture { 13 | background: transparent url("./../images/workouts/wall-sit.png") no-repeat 0 0; 14 | background-size: 100%; 15 | } 16 | } 17 | .workout-push-up { 18 | .picture { 19 | background: transparent url("./../images/workouts/push-up.png") no-repeat 0 0; 20 | background-size: 100%; 21 | } 22 | } 23 | .workout-abdominal-crunch { 24 | .picture { 25 | background: transparent url("./../images/workouts/abdominal-crunch.png") no-repeat 0 0; 26 | background-size: 100%; 27 | } 28 | } 29 | .workout-step-up-onto-chair { 30 | .picture { 31 | background: transparent url("./../images/workouts/step-up-onto-chair.png") no-repeat 0 0; 32 | background-size: 100%; 33 | } 34 | } 35 | .workout-squat { 36 | .picture { 37 | background: transparent url("./../images/workouts/squat.png") no-repeat 0 0; 38 | background-size: 100%; 39 | } 40 | } 41 | .workout-triceps-dip-on-chair { 42 | .picture { 43 | background: transparent url("./../images/workouts/triceps-dip-on-chair.png") no-repeat 0 0; 44 | background-size: 100%; 45 | } 46 | } 47 | .workout-plank { 48 | .picture { 49 | background: transparent url("./../images/workouts/plank.png") no-repeat 0 0; 50 | background-size: 100%; 51 | } 52 | } 53 | .workout-high-knees-running-in-place { 54 | .picture { 55 | background: transparent url("./../images/workouts/high-knees-running-in-place.png") no-repeat 0 0; 56 | background-size: 100%; 57 | } 58 | } 59 | .workout-lunge { 60 | .picture { 61 | background: transparent url("./../images/workouts/lunge.png") no-repeat 0 0; 62 | background-size: 100%; 63 | } 64 | } 65 | .workout-push-up-and-rotation { 66 | .picture { 67 | background: transparent url("./../images/workouts/push-up-and-rotation.png") no-repeat 0 0; 68 | background-size: 100%; 69 | } 70 | } 71 | .workout-side-plank { 72 | .picture { 73 | background: transparent url("./../images/workouts/side-plank.png") no-repeat 0 0; 74 | background-size: 100%; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/views/done.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | Finished! 6 | Well Done 7 |

8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 |
17 | 18 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /app/views/main.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | Workout timer 6 | {{workout.duration / 60 | numberAsText}} Minute 7 |

8 |
9 | 10 |
11 | 12 | 13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | {{timer}} 21 |
22 | 23 |
24 | -------------------------------------------------------------------------------- /app/views/rest.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 | 8 |
9 | 10 |
11 |

12 | {{rest.name | firstWord}} {{rest.name | followingWords}} 13 |

14 |
15 | 16 |
17 | {{timer}} 18 |
19 | 20 |
21 |

22 | Next... {{workout.name}}! 23 |

24 |
25 | 26 | 34 | 35 |
36 | -------------------------------------------------------------------------------- /app/views/step.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 |
14 | 15 |
16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |

24 | Step {{step}} 25 | {{workout.name | firstWord}} {{workout.name | followingWords}} 26 |

27 |
28 | 29 |
30 | {{timer}} 31 |
32 | 33 |
34 |
35 |
36 | 37 | 45 | 46 |
47 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "7-min-workout", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "angular": "~1.0.8", 6 | "cordova": "~2.7.0", 7 | "json3": "latest", 8 | "es5-shim": "latest", 9 | "angular-resource": "~1.0.8", 10 | "angular-cookies": "~1.0.8", 11 | "angular-sanitize": "~1.0.8", 12 | "ratchet": "git://github.com/maker/ratchet.git#~1.0.1", 13 | "bootstrap": "~2.3.2", 14 | "angular-mobile-nav": "latest", 15 | "fastclick": "~0.6.10" 16 | }, 17 | "devDependencies": { 18 | "angular-mocks": "~1.0.8", 19 | "angular-scenario": "~1.0.8" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 Olivier Louvignes - http://olouv.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "7-min-workout", 3 | "description": "beelink-mobile", 4 | "version": "1.0.0", 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "grunt": "~0.4.1", 8 | "grunt-contrib-copy": "~0.4.0", 9 | "grunt-contrib-concat": "~0.1.3", 10 | "grunt-contrib-coffee": "~0.6.4", 11 | "grunt-contrib-uglify": "~0.2.0", 12 | "grunt-contrib-compass": "~0.1.3", 13 | "grunt-contrib-jshint": "~0.3.0", 14 | "grunt-contrib-cssmin": "~0.5.0", 15 | "grunt-contrib-connect": "~0.2.0", 16 | "grunt-contrib-clean": "~0.4.0", 17 | "grunt-contrib-htmlmin": "~0.1.1", 18 | "grunt-contrib-imagemin": "~0.1.2", 19 | "grunt-contrib-less": "~0.5.0", 20 | "grunt-contrib-livereload": "~0.1.2", 21 | "grunt-bower-requirejs": "~0.4.1", 22 | "grunt-usemin": "~0.1.10", 23 | "grunt-regarde": "~0.1.1", 24 | "grunt-rev": "~0.1.0", 25 | "grunt-karma": "~0.3.0", 26 | "grunt-open": "~0.2.0", 27 | "matchdep": "~0.1.1", 28 | "grunt-google-cdn": "~0.1.1", 29 | "grunt-ngmin": "~0.0.2" 30 | }, 31 | "engines": { 32 | "node": ">=0.8.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # [angular-7min](http://mgcrea.github.com/angular-7min) [![Build Status](https://secure.travis-ci.org/mgcrea/angular-7min.png?branch=master)](http://travis-ci.org/#!/mgcrea/angular-7min) 2 | 3 | Todos are boring, aren't they? 4 | 5 | Angular-7min is fun & useful mobile application built with [AngularJS](https://github.com/angular) as a week-end project. 6 | 7 | > 8 | Don't have an hour or even twenty minutes to exercise each day? You might not need it. 9 | This routine of 12 exercises is a complete workout based on the latest fitness research—and it only takes 7 minutes. 10 | The routine was posted in the May-June issue of the American College of Sports Medicine's Health & Fitness Journal and highlighted by *** [TAKEDOWN - a famous journal from NY](https://github.com/mgcrea/angular-7min/blob/master/takedown/20130506-nytimes.jpg) ***. 11 | 12 | 13 | ## Takedown notice 14 | 15 | + I have received the following [takedown notice](https://github.com/mgcrea/angular-7min/blob/master/takedown/20130506-nytimes.jpg) regarding the illustrations used in the app. 16 | 17 | 18 | ## Documentation and examples 19 | 20 | [![Build Status](http://mgcrea.github.io/angular-7min/images/tour.gif)](http://mgcrea.github.com/angular-7min) 21 | 22 | 23 | + Check the [documentation](http://mgcrea.github.com/angular-7min) and [changelog](https://github.com/mgcrea/angular-7min/wiki/Changelog). 24 | 25 | 26 | ## Todo 27 | 28 | + Write unit&e2e tests 29 | + Add a build script for `cordova-ios` 30 | + Migrate to `angular-unstable` with `$animate` 31 | 32 | 33 | ## Quick start 34 | 35 | > 36 | ``` bash 37 | $ grunt server 38 | ``` 39 | 40 | 41 | ## Developers 42 | 43 | Clone the repo, `git clone git://github.com/mgcrea/angular-7min.git`, [download the latest release](https://github.com/mgcrea/angular-7min/zipball/master) or install with bower `bower install angular-7min`. 44 | 45 | AngularStrap is tested with `karma`. 46 | 47 | ``` bash 48 | $ sudo npm install bower grunt-cli --global 49 | $ npm install --dev; bower install 50 | $ grunt test 51 | ``` 52 | 53 | Tests require 'PhantomJS' to be installed. 54 | 55 | ``` bash 56 | $ brew update && brew install phantomjs 57 | ``` 58 | 59 | You can build the latest version using `grunt`. 60 | 61 | ``` bash 62 | $ grunt build 63 | ``` 64 | 65 | If you run into any permissions issues running the 'npm install' command on OSX, try running one of these two commands. 66 | 67 | ``` bash 68 | $ sudo chown -R $USER /usr/local 69 | $ sudo chown -R $USER /Users/[yourusername]/.npm 70 | ``` 71 | 72 | ## Contributing 73 | 74 | Please submit all pull requests the against master branch. If your unit test contains JavaScript patches or features, you should include relevant unit tests. Thanks! 75 | 76 | 77 | ## Authors 78 | 79 | **Olivier Louvignes** 80 | 81 | + http://olouv.com 82 | + http://github.com/mgcrea 83 | 84 | 85 | ## Credits 86 | 87 | + [AngularJS mobile-nav](https://github.com/ajoslin/angular-mobile-nav) by [@ajoslin](https://github.com/ajoslin) 88 | + [Codrops's PageTransitions](https://github.com/codrops/PageTransitions) by [@botelho](https://github.com/botelho) 89 | 90 | 91 | ## Copyright and license 92 | 93 | The MIT License 94 | 95 | Copyright (c) 2013 Olivier Louvignes - http://olouv.com 96 | 97 | Permission is hereby granted, free of charge, to any person obtaining a copy 98 | of this software and associated documentation files (the "Software"), to deal 99 | in the Software without restriction, including without limitation the rights 100 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 101 | copies of the Software, and to permit persons to whom the Software is 102 | furnished to do so, subject to the following conditions: 103 | 104 | The above copyright notice and this permission notice shall be included in 105 | all copies or substantial portions of the Software. 106 | 107 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 108 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 109 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 110 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 111 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 112 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 113 | THE SOFTWARE. 114 | -------------------------------------------------------------------------------- /takedown/20130506-nytimes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgcrea/angular-7min/0f242fd731671369c0a9c852067f46a981ec3045/takedown/20130506-nytimes.jpg -------------------------------------------------------------------------------- /test/karma-e2e.conf.js: -------------------------------------------------------------------------------- 1 | // Karma E2E configuration 2 | 3 | // base path, that will be used to resolve files and exclude 4 | basePath = ''; 5 | 6 | // list of files / patterns to load in the browser 7 | files = [ 8 | ANGULAR_SCENARIO, 9 | ANGULAR_SCENARIO_ADAPTER, 10 | 'test/e2e/**/*.js' 11 | ]; 12 | 13 | // list of files to exclude 14 | exclude = []; 15 | 16 | // test results reporter to use 17 | // possible values: dots || progress || growl 18 | reporters = ['progress']; 19 | 20 | // web server port 21 | port = 8080; 22 | 23 | // cli runner port 24 | runnerPort = 9100; 25 | 26 | // enable / disable colors in the output (reporters and logs) 27 | colors = true; 28 | 29 | // level of logging 30 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 31 | logLevel = LOG_INFO; 32 | 33 | // enable / disable watching file and executing tests whenever any file changes 34 | autoWatch = false; 35 | 36 | // Start these browsers, currently available: 37 | // - Chrome 38 | // - ChromeCanary 39 | // - Firefox 40 | // - Opera 41 | // - Safari (only Mac) 42 | // - PhantomJS 43 | // - IE (only Windows) 44 | browsers = ['Chrome']; 45 | 46 | // If browser does not capture in given timeout [ms], kill it 47 | captureTimeout = 5000; 48 | 49 | // Continuous Integration mode 50 | // if true, it capture browsers, run tests and exit 51 | singleRun = false; 52 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | 3 | // base path, that will be used to resolve files and exclude 4 | basePath = ''; 5 | 6 | // list of files / patterns to load in the browser 7 | files = [ 8 | JASMINE, 9 | JASMINE_ADAPTER, 10 | 'app/components/angular/angular.js', 11 | 'app/components/angular-mocks/angular-mocks.js', 12 | 'app/scripts/*.js', 13 | 'app/scripts/**/*.js', 14 | 'test/mock/**/*.js', 15 | 'test/spec/**/*.js' 16 | ]; 17 | 18 | // list of files to exclude 19 | exclude = []; 20 | 21 | // test results reporter to use 22 | // possible values: dots || progress || growl 23 | reporters = ['progress']; 24 | 25 | // web server port 26 | port = 8080; 27 | 28 | // cli runner port 29 | runnerPort = 9100; 30 | 31 | // enable / disable colors in the output (reporters and logs) 32 | colors = true; 33 | 34 | // level of logging 35 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 36 | logLevel = LOG_INFO; 37 | 38 | // enable / disable watching file and executing tests whenever any file changes 39 | autoWatch = false; 40 | 41 | // Start these browsers, currently available: 42 | // - Chrome 43 | // - ChromeCanary 44 | // - Firefox 45 | // - Opera 46 | // - Safari (only Mac) 47 | // - PhantomJS 48 | // - IE (only Windows) 49 | browsers = ['Chrome']; 50 | 51 | // If browser does not capture in given timeout [ms], kill it 52 | captureTimeout = 5000; 53 | 54 | // Continuous Integration mode 55 | // if true, it capture browsers, run tests and exit 56 | singleRun = false; 57 | -------------------------------------------------------------------------------- /test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | End2end Test Runner 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/spec/controllers/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: MainCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('beelinkMobileApp')); 7 | 8 | var MainCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | MainCtrl = $controller('MainCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | --------------------------------------------------------------------------------