├── .eslintrc ├── .gitignore ├── Gruntfile.js ├── README.md ├── bower.json ├── bower_components ├── JSColor │ ├── .bower.json │ ├── arrow.gif │ ├── bower.json │ ├── cross.gif │ ├── demo.html │ ├── hs.png │ ├── hv.png │ └── jscolor.js ├── backbone │ ├── .bower.json │ ├── .gitignore │ ├── .npmignore │ ├── CNAME │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── backbone.js │ ├── bower.json │ ├── component.json │ ├── index.html │ ├── index.js │ └── package.json ├── es6-module-loader │ ├── .bower.json │ ├── .gitignore │ ├── .jshintrc │ ├── Gruntfile.js │ ├── LICENSE-MIT │ ├── README.md │ ├── bower.json │ └── dist │ │ ├── es6-module-loader.js │ │ ├── traceur-runtime.js │ │ └── traceur.js ├── jquery │ ├── .bower.json │ ├── MIT-LICENSE.txt │ ├── bower.json │ ├── dist │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ └── jquery.min.map │ └── src │ │ ├── ajax.js │ │ ├── ajax │ │ ├── jsonp.js │ │ ├── load.js │ │ ├── parseJSON.js │ │ ├── parseXML.js │ │ ├── script.js │ │ ├── var │ │ │ ├── nonce.js │ │ │ └── rquery.js │ │ └── xhr.js │ │ ├── attributes.js │ │ ├── attributes │ │ ├── attr.js │ │ ├── classes.js │ │ ├── prop.js │ │ ├── support.js │ │ └── val.js │ │ ├── callbacks.js │ │ ├── core.js │ │ ├── core │ │ ├── access.js │ │ ├── init.js │ │ ├── parseHTML.js │ │ ├── ready.js │ │ └── var │ │ │ └── rsingleTag.js │ │ ├── css.js │ │ ├── css │ │ ├── addGetHookIf.js │ │ ├── curCSS.js │ │ ├── defaultDisplay.js │ │ ├── hiddenVisibleSelectors.js │ │ ├── support.js │ │ ├── swap.js │ │ └── var │ │ │ ├── cssExpand.js │ │ │ ├── getStyles.js │ │ │ ├── isHidden.js │ │ │ ├── rmargin.js │ │ │ └── rnumnonpx.js │ │ ├── data.js │ │ ├── data │ │ ├── Data.js │ │ ├── accepts.js │ │ └── var │ │ │ ├── data_priv.js │ │ │ └── data_user.js │ │ ├── deferred.js │ │ ├── deprecated.js │ │ ├── dimensions.js │ │ ├── effects.js │ │ ├── effects │ │ ├── Tween.js │ │ └── animatedSelector.js │ │ ├── event.js │ │ ├── event │ │ ├── ajax.js │ │ ├── alias.js │ │ └── support.js │ │ ├── exports │ │ ├── amd.js │ │ └── global.js │ │ ├── intro.js │ │ ├── jquery.js │ │ ├── manipulation.js │ │ ├── manipulation │ │ ├── _evalUrl.js │ │ ├── support.js │ │ └── var │ │ │ └── rcheckableType.js │ │ ├── offset.js │ │ ├── outro.js │ │ ├── queue.js │ │ ├── queue │ │ └── delay.js │ │ ├── selector-native.js │ │ ├── selector-sizzle.js │ │ ├── selector.js │ │ ├── serialize.js │ │ ├── sizzle │ │ └── dist │ │ │ ├── sizzle.js │ │ │ ├── sizzle.min.js │ │ │ └── sizzle.min.map │ │ ├── traversing.js │ │ ├── traversing │ │ ├── findFilter.js │ │ └── var │ │ │ └── rneedsContext.js │ │ ├── var │ │ ├── arr.js │ │ ├── class2type.js │ │ ├── concat.js │ │ ├── hasOwn.js │ │ ├── indexOf.js │ │ ├── pnum.js │ │ ├── push.js │ │ ├── rnotwhite.js │ │ ├── slice.js │ │ ├── strundefined.js │ │ ├── support.js │ │ └── toString.js │ │ └── wrap.js └── underscore │ ├── .bower.json │ ├── LICENSE │ ├── README.md │ ├── bower.json │ ├── underscore-min.js │ ├── underscore-min.map │ └── underscore.js ├── dist ├── app.js └── app.min.js ├── gif.worker.js ├── gobblefile.js ├── index.html ├── lib ├── gif.js ├── gif.js.map ├── gif.worker.js ├── gif.worker.js.map └── share.js ├── package.json └── src ├── css └── app.css ├── img ├── down_arrow.png ├── down_arrow.svg └── favicon.png └── js ├── app.js ├── models └── slate.js ├── modules ├── constants.js ├── fonts.js └── slate.js └── views ├── share.js ├── slate.js └── slateConfig.js /.gitignore: -------------------------------------------------------------------------------- 1 | .gobble* 2 | .DS_Store 3 | node_modules 4 | 5 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | 4 | require("load-grunt-tasks")(grunt); // npm install --save-dev load-grunt-tasks 5 | 6 | grunt.initConfig({ 7 | babel: { 8 | options: { 9 | sourceMap: false, 10 | modules: 'umd' 11 | }, 12 | dist: { 13 | files: [{ 14 | expand: true, 15 | cwd: 'src/', 16 | src: ['**/*.js'], 17 | dest: 'dist' 18 | }] 19 | } 20 | }, 21 | uglify: { 22 | dist: { 23 | files: { 24 | 'dest/slate.min.js': ['dist/js/*.js'] 25 | } 26 | } 27 | }, 28 | esperanto: { 29 | options: { 30 | type: 'umd', 31 | bundleOpts: { 32 | name: 'slate' 33 | } 34 | }, 35 | files: { 36 | expand: true, 37 | cwd: 'src/js', 38 | src : ['**/*.js'], 39 | dest: 'dist/out.min.js' 40 | } 41 | } 42 | }); 43 | 44 | grunt.registerTask("default", [/*"babel"/*, 'uglify'*/,'esperanto']); 45 | // grunt.registerTask('default', ['umd']); 46 | }; 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slate 2 | *Simple and cool text meme generator* 3 | 4 | ![alt tag](http://i.imgur.com/Aj0IWPM.gif) ![alt tag](http://i.imgur.com/XcpDwZG.gif) 5 | ![alt tag](http://i.imgur.com/sUAu2Bw.gif) ![alt tag](http://imgur.com/BqF3fUK.gif) 6 | 7 | 8 | ## [See it in Action](http://bitshadow.github.io/slate) 9 | 10 | ## Contributing 11 | Want to add some extra features. Pull requests are welcome :). 12 | 13 | ``` 14 | $ git clone https://github.com/bitshadow/slate.git 15 | 16 | $ cd slate 17 | ``` 18 | 19 | As some of the browsers don't allow you load web workers when running script. You will need to start the local server. 20 | 21 | ``` 22 | $ python -m SimpleHTTPServer 23 | ``` 24 | 25 | Browser Support 26 | --------------- 27 | 28 | Works best on latest versions of Google Chrome, Firefox and Safari. 29 | 30 | License 31 | ------- 32 | 33 | Copyright (c) 2015 Jignesh Kakadiya, http://bitshadow.github.io 34 | Licensed under the [MIT license](http://opensource.org/licenses/MIT). 35 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todomvc-backbone-es6", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "jquery": "~2.1.0", 6 | "backbone": "~1.1.0", 7 | "es6-module-loader": "~0.4.2", 8 | "JSColor": "~1.4.2" 9 | }, 10 | "resolutions": { 11 | "backbone": "~1.1.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bower_components/JSColor/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSColor", 3 | "main": "jscolor.js", 4 | "version": "1.4.2", 5 | "authors": [ 6 | "Jan Odvárko" 7 | ], 8 | "description": "JavaScript / HTML Color Picker", 9 | "license": "LGPL", 10 | "homepage": "http://jscolor.com/", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "_release": "1.4.2", 19 | "_resolution": { 20 | "type": "version", 21 | "tag": "v1.4.2", 22 | "commit": "48a3c0789704d47275d88e484af2e771b5766ba8" 23 | }, 24 | "_source": "git://github.com/callumacrae/JSColor.git", 25 | "_target": "~1.4.2", 26 | "_originalSource": "JSColor", 27 | "_direct": true 28 | } -------------------------------------------------------------------------------- /bower_components/JSColor/arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/bower_components/JSColor/arrow.gif -------------------------------------------------------------------------------- /bower_components/JSColor/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSColor", 3 | "main": "jscolor.js", 4 | "version": "1.4.2", 5 | "authors": [ 6 | "Jan Odvárko" 7 | ], 8 | "description": "JavaScript / HTML Color Picker", 9 | "license": "LGPL", 10 | "homepage": "http://jscolor.com/", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /bower_components/JSColor/cross.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/bower_components/JSColor/cross.gif -------------------------------------------------------------------------------- /bower_components/JSColor/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | jscolor demo 4 | 5 | 6 | 7 | 8 | 9 | Click here: 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /bower_components/JSColor/hs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/bower_components/JSColor/hs.png -------------------------------------------------------------------------------- /bower_components/JSColor/hv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/bower_components/JSColor/hv.png -------------------------------------------------------------------------------- /bower_components/backbone/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backbone", 3 | "version": "1.1.2", 4 | "main": "backbone.js", 5 | "dependencies": { 6 | "underscore": ">=1.5.0" 7 | }, 8 | "ignore": [ 9 | "backbone-min.js", 10 | "docs", 11 | "examples", 12 | "test", 13 | "*.yml", 14 | "*.map", 15 | ".html", 16 | "*.ico" 17 | ], 18 | "homepage": "https://github.com/jashkenas/backbone", 19 | "_release": "1.1.2", 20 | "_resolution": { 21 | "type": "version", 22 | "tag": "1.1.2", 23 | "commit": "53f77901a4ea9c7cf75d3db93ddddf491998d90f" 24 | }, 25 | "_source": "git://github.com/jashkenas/backbone.git", 26 | "_target": "~1.1.0", 27 | "_originalSource": "backbone" 28 | } -------------------------------------------------------------------------------- /bower_components/backbone/.gitignore: -------------------------------------------------------------------------------- 1 | raw 2 | *.sw? 3 | .DS_Store 4 | node_modules 5 | bower_components 6 | -------------------------------------------------------------------------------- /bower_components/backbone/.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | Rakefile 3 | docs/ 4 | raw/ 5 | examples/ 6 | index.html 7 | .jshintrc 8 | -------------------------------------------------------------------------------- /bower_components/backbone/CNAME: -------------------------------------------------------------------------------- 1 | backbonejs.org 2 | 3 | -------------------------------------------------------------------------------- /bower_components/backbone/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to Open a Backbone.js Ticket 2 | 3 | * Do not use tickets to ask for help with (debugging) your application. Ask on 4 | the [mailing list](https://groups.google.com/forum/#!forum/backbonejs), 5 | in the IRC channel (`#documentcloud` on Freenode), or if you understand your 6 | specific problem, on [StackOverflow](http://stackoverflow.com/questions/tagged/backbone.js). 7 | 8 | * Before you open a ticket or send a pull request, 9 | [search](https://github.com/jashkenas/backbone/issues) for previous 10 | discussions about the same feature or issue. Add to the earlier ticket if you 11 | find one. 12 | 13 | * Before sending a pull request for a feature or bug fix, be sure to have 14 | [tests](http://backbonejs.org/test/). 15 | 16 | * Use the same coding style as the rest of the 17 | [codebase](https://github.com/jashkenas/backbone/blob/master/backbone.js). 18 | 19 | * In your pull request, do not add documentation or rebuild the minified 20 | `backbone-min.js` file. We'll do that before cutting a new release. 21 | 22 | * All pull requests should be made to the `master` branch. 23 | -------------------------------------------------------------------------------- /bower_components/backbone/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2014 Jeremy Ashkenas, DocumentCloud 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /bower_components/backbone/README.md: -------------------------------------------------------------------------------- 1 | ____ __ __ 2 | /\ _`\ /\ \ /\ \ __ 3 | \ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____ 4 | \ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\ 5 | \ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\ 6 | \ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/ 7 | \/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/ 8 | \ \____/ 9 | \/___/ 10 | (_'_______________________________________________________________________________'_) 11 | (_.———————————————————————————————————————————————————————————————————————————————._) 12 | 13 | 14 | Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface. 15 | 16 | For Docs, License, Tests, pre-packed downloads, and everything else, really, see: 17 | http://backbonejs.org 18 | 19 | To suggest a feature, report a bug, or general discussion: 20 | http://github.com/jashkenas/backbone/issues 21 | 22 | Backbone is an open-sourced component of DocumentCloud: 23 | https://github.com/documentcloud 24 | 25 | Many thanks to our contributors: 26 | http://github.com/jashkenas/backbone/contributors 27 | 28 | Special thanks to Robert Kieffer for the original philosophy behind Backbone. 29 | http://github.com/broofa 30 | -------------------------------------------------------------------------------- /bower_components/backbone/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "backbone", 3 | "version" : "1.1.2", 4 | "main" : "backbone.js", 5 | "dependencies" : { 6 | "underscore" : ">=1.5.0" 7 | }, 8 | "ignore" : ["backbone-min.js", "docs", "examples", "test", "*.yml", "*.map", ".html", "*.ico"] 9 | } 10 | -------------------------------------------------------------------------------- /bower_components/backbone/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "backbone", 3 | "version" : "1.1.2", 4 | "description" : "Give your JS App some Backbone with Models, Views, Collections, and Events.", 5 | "keywords" : ["model", "view", "controller", "router", "server", "client", "browser"], 6 | "repo" : "jashkenas/backbone", 7 | "dependencies" : { 8 | "jashkenas/underscore" : "*" 9 | }, 10 | "main" : "backbone.js", 11 | "scripts" : ["backbone.js"], 12 | "license" : "MIT" 13 | } 14 | -------------------------------------------------------------------------------- /bower_components/backbone/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./backbone'); 2 | -------------------------------------------------------------------------------- /bower_components/backbone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "backbone", 3 | "description" : "Give your JS App some Backbone with Models, Views, Collections, and Events.", 4 | "url" : "http://backbonejs.org", 5 | "keywords" : ["model", "view", "controller", "router", "server", "client", "browser"], 6 | "author" : "Jeremy Ashkenas ", 7 | "dependencies" : { 8 | "underscore" : ">=1.5.0" 9 | }, 10 | "devDependencies": { 11 | "phantomjs": "1.9.0-1", 12 | "docco": "0.6.1", 13 | "coffee-script": "1.6.1" 14 | }, 15 | "scripts": { 16 | "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true && coffee test/model.coffee", 17 | "build": "uglifyjs backbone.js --mangle --source-map backbone-min.map -o backbone-min.js", 18 | "doc": "docco backbone.js && docco examples/todos/todos.js examples/backbone.localstorage.js", 19 | "lint": "jsl -nofilelisting -nologo -conf docs/jsl.conf -process backbone.js" 20 | }, 21 | "main" : "backbone.js", 22 | "version" : "1.1.2", 23 | "license" : "MIT", 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/jashkenas/backbone.git" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es6-module-loader", 3 | "version": "0.4.3", 4 | "description": "An ES6 Module Loader polyfill based on the latest spec.", 5 | "homepage": "https://github.com/ModuleLoader/es6-module-loader", 6 | "main": "dist/es6-module-loader.js", 7 | "keywords": [ 8 | "es6", 9 | "harmony", 10 | "polyfill", 11 | "modules" 12 | ], 13 | "ignore": [ 14 | "demo", 15 | "lib", 16 | "test", 17 | "grunt.js", 18 | "package.json" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/ModuleLoader/es6-module-loader.git" 23 | }, 24 | "licenses": [ 25 | { 26 | "type": "MIT" 27 | } 28 | ], 29 | "_release": "0.4.3", 30 | "_resolution": { 31 | "type": "version", 32 | "tag": "v0.4.3", 33 | "commit": "52b67e3afa5a26568ac2e9d15c8d742bdd50c78c" 34 | }, 35 | "_source": "git://github.com/ModuleLoader/es6-module-loader.git", 36 | "_target": "~0.4.2", 37 | "_originalSource": "es6-module-loader" 38 | } -------------------------------------------------------------------------------- /bower_components/es6-module-loader/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "immed": true, 5 | "latedef": true, 6 | "newcap": true, 7 | "noarg": true, 8 | "sub": true, 9 | "undef": true, 10 | "boss": true, 11 | "eqnull": true 12 | } 13 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function (grunt) { 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | meta: { 6 | banner: '/*\n * <%= pkg.name %> v<%= pkg.version %>\n' + 7 | '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' + 8 | ' * Implemented to the 2013-12-02 ES6 module specification draft\n' + 9 | ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 10 | ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n' 11 | }, 12 | uglify: { 13 | options: { 14 | banner: '<%= meta.banner %>' 15 | }, 16 | dist: { 17 | src: 'lib/<%= pkg.name %>.js', 18 | dest: 'dist/<%= pkg.name %>.js' 19 | }, 20 | traceur: { 21 | options: { 22 | banner: '/*\n Traceur Compiler 0.0.9 - https://github.com/google/traceur-compiler \n*/\n' 23 | }, 24 | src: 'lib/traceur.js', 25 | dest: 'dist/traceur.js' 26 | } 27 | }, 28 | jshint: { 29 | options: { 30 | jshintrc: '.jshintrc' 31 | }, 32 | dist: [ 33 | 'lib/es6-module-loader.js', 34 | 'test/es6-module-loader_test.js' 35 | ] 36 | } 37 | }); 38 | 39 | grunt.loadNpmTasks('grunt-contrib-jshint'); 40 | grunt.loadNpmTasks('grunt-contrib-uglify'); 41 | 42 | grunt.registerTask('default', [/*'jshint', */'uglify']); 43 | }; 44 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Guy Bedford, Luke Hoban, Addy Osmani 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es6-module-loader", 3 | "version": "0.4.3", 4 | "description": "An ES6 Module Loader polyfill based on the latest spec.", 5 | "homepage": "https://github.com/ModuleLoader/es6-module-loader", 6 | "main": "dist/es6-module-loader.js", 7 | "keywords": [ 8 | "es6", 9 | "harmony", 10 | "polyfill", 11 | "modules" 12 | ], 13 | "ignore": [ 14 | "demo", 15 | "lib", 16 | "test", 17 | "grunt.js", 18 | "package.json" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/ModuleLoader/es6-module-loader.git" 23 | }, 24 | "licenses": [ 25 | { 26 | "type": "MIT" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /bower_components/es6-module-loader/dist/traceur-runtime.js: -------------------------------------------------------------------------------- 1 | !function(e){"use strict";function t(e){return{configurable:!0,enumerable:!1,value:e,writable:!0}}function r(){return"__$"+Math.floor(1e9*Math.random())+"$"+ ++k+"$__"}function n(e){return"object"==typeof e&&e instanceof i}function o(e){return n(e)?"symbol":typeof e}function u(e){var t=new i(e);if(!(this instanceof u))return t;throw new TypeError("Symbol cannot be new'ed")}function i(e){var t=r();H(this,W,{value:this}),H(this,Q,{value:t}),H(this,Y,{value:e}),N(this),q[t]=this}function a(e){return n(e)?e[Q]:e}function c(e){for(var t=[],r=z(e),n=0;nr;r++)e[n[r]]=t[n[r]];return e}function n(e,t){var r,n,o=z(t),u=o.length;for(r=0;u>r;r++)n=U(t,o[r]),H(e,o[r],n);return e}H(e,"defineProperty",{value:h}),H(e,"getOwnPropertyNames",{value:c}),H(e,"getOwnPropertyDescriptor",{value:l}),H(e.prototype,"hasOwnProperty",{value:s}),e.getOwnPropertySymbols=f,H(e,"is",F(t)),H(e,"assign",F(r)),H(e,"mixin",F(n))}function m(e){for(var t=1;t3?("function"==typeof n&&(e.__proto__=n),e.prototype=C(M(n),P(t))):e.prototype=t,H(e,"prototype",{configurable:!1,writable:!1}),G(e,P(r))}function M(e){if("function"==typeof e){var t=e.prototype;if(A(t)===t||null===t)return e.prototype}if(null===e)return null;throw new TypeError}function _(e,t,r){null!==D(t)&&S(e,t,"constructor",r)}function j(e){return h(e,u.iterator,t(function(){return this}))}function T(e){return j({next:function(t){switch(e.GState){case J:throw new Error('"next" on executing generator');case L:throw new Error('"next" on closed generator');case B:if(void 0!==t)throw x("Sent value to newborn generator");case K:return e.GState=J,e.moveNext(t,V)?(e.GState=K,{value:e.current,done:!1}):(e.GState=L,{value:e.yieldReturn,done:!0})}},"throw":function(t){switch(e.GState){case J:throw new Error('"throw" on executing generator');case L:throw new Error('"throw" on closed generator');case B:throw e.GState=L,t;case K:return e.GState=J,e.moveNext(t,X)?(e.GState=K,{value:e.current,done:!1}):(e.GState=L,{value:e.yieldReturn,done:!0})}}})}function $(e){e.Symbol=u,g(e.Object)}if(!e.$traceurRuntime){var A=Object,x=TypeError,C=A.create,G=A.defineProperties,H=A.defineProperty,N=A.freeze,U=A.getOwnPropertyDescriptor,z=A.getOwnPropertyNames,D=A.getPrototypeOf,I=A.prototype.hasOwnProperty,F=(A.prototype.toString,t),k=0,Q=r(),Y=r(),W=r(),q=C(null);H(u.prototype,"constructor",t(u)),H(u.prototype,"toString",F(function(){var e=this[W];if(!p("symbols"))return e[Q];if(!e)throw TypeError("Conversion from symbol to string");var t=e[Y];return void 0===t&&(t=""),"Symbol("+t+")"})),H(u.prototype,"valueOf",F(function(){var e=this[W];if(!e)throw TypeError("Conversion from symbol to string");return p("symbols")?e:e[Q]})),H(i.prototype,"constructor",t(u)),H(i.prototype,"toString",{value:u.prototype.toString,enumerable:!1}),H(i.prototype,"valueOf",{value:u.prototype.valueOf,enumerable:!1}),N(i.prototype),u.iterator=u();var B=0,J=1,K=2,L=3,V=0,X=1;$(e),e.$traceurRuntime={createClass:R,defaultSuperCall:_,exportStar:m,generatorWrap:T,setProperty:v,setupGlobals:$,spread:b,superCall:S,superGet:O,superSet:E,toObject:y,toProperty:a,"typeof":o}}}("undefined"!=typeof global?global:this),function(){function e(e,t,r,n,o,u,i){var a=[];return e&&a.push(e,":"),r&&(a.push("//"),t&&a.push(t,"@"),a.push(r),n&&a.push(":",n)),o&&a.push(o),u&&a.push("?",u),i&&a.push("#",i),a.join("")}function t(e){return e.match(a)}function r(e){if("/"===e)return"/";for(var t="/"===e[0]?"/":"",r="/"===e.slice(-1)?"/":"",n=e.split("/"),o=[],u=0,i=0;i0;)o.unshift("..");0===o.length&&o.push(".")}return t+o.join("/")+r}function n(t){var n=t[c.PATH];return n=r(n.replace(/\/\//.g,"/")),t[c.PATH]=n,e(t[c.SCHEME],t[c.USER_INFO],t[c.DOMAIN],t[c.PORT],t[c.PATH],t[c.QUERY_DATA],t[c.FRAGMENT])}function o(e){var r=t(e);return n(r)}function u(e,r){var o=t(r),u=t(e);if(o[c.SCHEME])return n(o);o[c.SCHEME]=u[c.SCHEME];for(var i=c.SCHEME;i<=c.PORT;i++)o[i]||(o[i]=u[i]);if("/"==o[c.PATH][0])return n(o);var a=u[c.PATH],l=a.lastIndexOf("/");return a=a.slice(0,l+1)+o[c.PATH],o[c.PATH]=a,n(o)}function i(e){if(!e)return!1;if("/"===e[0])return!0;var r=t(e);return r[c.SCHEME]?!0:!1}var a=new RegExp("^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([\\w\\d\\-\\u0100-\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$"),c={SCHEME:1,USER_INFO:2,DOMAIN:3,PORT:4,PATH:5,QUERY_DATA:6,FRAGMENT:7};$traceurRuntime.canonicalizeUrl=o,$traceurRuntime.isAbsolute=i,$traceurRuntime.removeDotSegments=r,$traceurRuntime.resolveUrl=u}(),function(e){"use strict";function t(e){if(e){var t=h.normalize(e);return c[t]}}function r(e){var t=arguments[1],r=Object.create(null);return Object.getOwnPropertyNames(e).forEach(function(n){var o,u;if(t===v){var i=Object.getOwnPropertyDescriptor(e,n);i.get&&(o=i.get)}o||(u=e[n],o=function(){return u}),Object.defineProperty(r,n,{get:o,enumerable:!0})}),Object.preventExtensions(r),r}var n,o=$traceurRuntime,u=o.canonicalizeUrl,i=o.resolveUrl,a=o.isAbsolute,c=Object.create(null);n=e.location&&e.location.href?i(e.location.href,"./"):"";var l=function(e,t){this.url=e,this.value_=t};l=$traceurRuntime.createClass(l,{},{});var f=function(e,t){$traceurRuntime.superCall(this,s.prototype,"constructor",[e,null]),this.func=t},s=$traceurRuntime.createClass(f,{getUncoatedModule:function(){return this.value_?this.value_:this.value_=this.func.call(e)}},{},l),p=Object.create(null),v={},h={normalize:function(e,t){if("string"!=typeof e)throw new TypeError("module name must be a string, not "+typeof e);if(a(e))return u(e);if(/[^\.]\/\.\.\//.test(e))throw new Error("module name embeds /../: "+e);return"."===e[0]&&t?i(t,e):u(e)},get:function(e){var n=t(e);if(!n)return void 0;var o=p[n.url];return o?o:(o=r(n.getUncoatedModule(),v),p[n.url]=o)},set:function(e,t){e=String(e),c[e]=new f(e,function(){return t}),p[e]=t},get baseURL(){return n},set baseURL(e){n=String(e)},registerModule:function(e,t){var r=h.normalize(e);c[r]=new f(r,t)},getForTesting:function(e){var t=this;return this.testingPrefix_||Object.keys(p).some(function(e){var r=/(traceur@[^\/]*\/)/.exec(e);return r?(t.testingPrefix_=r[1],!0):void 0}),this.get(this.testingPrefix_+e)},set rootReferrer(e){this.rootReferrer_=e},get rootReferrer(){return this.rootReferrer_}};h.set("@traceur/src/runtime/ModuleStore",new r({ModuleStore:h}));var g=$traceurRuntime.setupGlobals;$traceurRuntime.setupGlobals=function(e){g(e)},$traceurRuntime.ModuleStore=h,e.System={registerModule:h.registerModule,get:h.get,set:h.set,normalize:h.normalize},$traceurRuntime.getModuleImpl=function(e){var r=t(e);return r&&r.getUncoatedModule()}}("undefined"!=typeof global?global:this);var $__4=$traceurRuntime.getModuleImpl("traceur@0.0.12/src/runtime/polyfills/polyfills"); -------------------------------------------------------------------------------- /bower_components/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.1.4", 4 | "main": "dist/jquery.js", 5 | "license": "MIT", 6 | "ignore": [ 7 | "**/.*", 8 | "build", 9 | "dist/cdn", 10 | "speed", 11 | "test", 12 | "*.md", 13 | "AUTHORS.txt", 14 | "Gruntfile.js", 15 | "package.json" 16 | ], 17 | "devDependencies": { 18 | "sizzle": "2.1.1-jquery.2.1.2", 19 | "requirejs": "2.1.10", 20 | "qunit": "1.14.0", 21 | "sinon": "1.8.1" 22 | }, 23 | "keywords": [ 24 | "jquery", 25 | "javascript", 26 | "library" 27 | ], 28 | "homepage": "https://github.com/jquery/jquery", 29 | "_release": "2.1.4", 30 | "_resolution": { 31 | "type": "version", 32 | "tag": "2.1.4", 33 | "commit": "7751e69b615c6eca6f783a81e292a55725af6b85" 34 | }, 35 | "_source": "git://github.com/jquery/jquery.git", 36 | "_target": "~2.1.0", 37 | "_originalSource": "jquery" 38 | } -------------------------------------------------------------------------------- /bower_components/jquery/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 jQuery Foundation and other contributors 2 | http://jquery.com/ 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bower_components/jquery/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.1.4", 4 | "main": "dist/jquery.js", 5 | "license": "MIT", 6 | "ignore": [ 7 | "**/.*", 8 | "build", 9 | "dist/cdn", 10 | "speed", 11 | "test", 12 | "*.md", 13 | "AUTHORS.txt", 14 | "Gruntfile.js", 15 | "package.json" 16 | ], 17 | "devDependencies": { 18 | "sizzle": "2.1.1-jquery.2.1.2", 19 | "requirejs": "2.1.10", 20 | "qunit": "1.14.0", 21 | "sinon": "1.8.1" 22 | }, 23 | "keywords": [ 24 | "jquery", 25 | "javascript", 26 | "library" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /bower_components/jquery/src/ajax/jsonp.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "./var/nonce", 4 | "./var/rquery", 5 | "../ajax" 6 | ], function( jQuery, nonce, rquery ) { 7 | 8 | var oldCallbacks = [], 9 | rjsonp = /(=)\?(?=&|$)|\?\?/; 10 | 11 | // Default jsonp settings 12 | jQuery.ajaxSetup({ 13 | jsonp: "callback", 14 | jsonpCallback: function() { 15 | var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 16 | this[ callback ] = true; 17 | return callback; 18 | } 19 | }); 20 | 21 | // Detect, normalize options and install callbacks for jsonp requests 22 | jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 23 | 24 | var callbackName, overwritten, responseContainer, 25 | jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 26 | "url" : 27 | typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 28 | ); 29 | 30 | // Handle iff the expected data type is "jsonp" or we have a parameter to set 31 | if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 32 | 33 | // Get callback name, remembering preexisting value associated with it 34 | callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 35 | s.jsonpCallback() : 36 | s.jsonpCallback; 37 | 38 | // Insert callback into url or form data 39 | if ( jsonProp ) { 40 | s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 41 | } else if ( s.jsonp !== false ) { 42 | s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 43 | } 44 | 45 | // Use data converter to retrieve json after script execution 46 | s.converters["script json"] = function() { 47 | if ( !responseContainer ) { 48 | jQuery.error( callbackName + " was not called" ); 49 | } 50 | return responseContainer[ 0 ]; 51 | }; 52 | 53 | // force json dataType 54 | s.dataTypes[ 0 ] = "json"; 55 | 56 | // Install callback 57 | overwritten = window[ callbackName ]; 58 | window[ callbackName ] = function() { 59 | responseContainer = arguments; 60 | }; 61 | 62 | // Clean-up function (fires after converters) 63 | jqXHR.always(function() { 64 | // Restore preexisting value 65 | window[ callbackName ] = overwritten; 66 | 67 | // Save back as free 68 | if ( s[ callbackName ] ) { 69 | // make sure that re-using the options doesn't screw things around 70 | s.jsonpCallback = originalSettings.jsonpCallback; 71 | 72 | // save the callback name for future use 73 | oldCallbacks.push( callbackName ); 74 | } 75 | 76 | // Call if it was a function and we have a response 77 | if ( responseContainer && jQuery.isFunction( overwritten ) ) { 78 | overwritten( responseContainer[ 0 ] ); 79 | } 80 | 81 | responseContainer = overwritten = undefined; 82 | }); 83 | 84 | // Delegate to script 85 | return "script"; 86 | } 87 | }); 88 | 89 | }); 90 | -------------------------------------------------------------------------------- /bower_components/jquery/src/ajax/load.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "../core/parseHTML", 4 | "../ajax", 5 | "../traversing", 6 | "../manipulation", 7 | "../selector", 8 | // Optional event/alias dependency 9 | "../event/alias" 10 | ], function( jQuery ) { 11 | 12 | // Keep a copy of the old load method 13 | var _load = jQuery.fn.load; 14 | 15 | /** 16 | * Load a url into a page 17 | */ 18 | jQuery.fn.load = function( url, params, callback ) { 19 | if ( typeof url !== "string" && _load ) { 20 | return _load.apply( this, arguments ); 21 | } 22 | 23 | var selector, type, response, 24 | self = this, 25 | off = url.indexOf(" "); 26 | 27 | if ( off >= 0 ) { 28 | selector = jQuery.trim( url.slice( off ) ); 29 | url = url.slice( 0, off ); 30 | } 31 | 32 | // If it's a function 33 | if ( jQuery.isFunction( params ) ) { 34 | 35 | // We assume that it's the callback 36 | callback = params; 37 | params = undefined; 38 | 39 | // Otherwise, build a param string 40 | } else if ( params && typeof params === "object" ) { 41 | type = "POST"; 42 | } 43 | 44 | // If we have elements to modify, make the request 45 | if ( self.length > 0 ) { 46 | jQuery.ajax({ 47 | url: url, 48 | 49 | // if "type" variable is undefined, then "GET" method will be used 50 | type: type, 51 | dataType: "html", 52 | data: params 53 | }).done(function( responseText ) { 54 | 55 | // Save response for use in complete callback 56 | response = arguments; 57 | 58 | self.html( selector ? 59 | 60 | // If a selector was specified, locate the right elements in a dummy div 61 | // Exclude scripts to avoid IE 'Permission Denied' errors 62 | jQuery("
").append( jQuery.parseHTML( responseText ) ).find( selector ) : 63 | 64 | // Otherwise use the full result 65 | responseText ); 66 | 67 | }).complete( callback && function( jqXHR, status ) { 68 | self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 69 | }); 70 | } 71 | 72 | return this; 73 | }; 74 | 75 | }); 76 | -------------------------------------------------------------------------------- /bower_components/jquery/src/ajax/parseJSON.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core" 3 | ], function( jQuery ) { 4 | 5 | // Support: Android 2.3 6 | // Workaround failure to string-cast null input 7 | jQuery.parseJSON = function( data ) { 8 | return JSON.parse( data + "" ); 9 | }; 10 | 11 | return jQuery.parseJSON; 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /bower_components/jquery/src/ajax/parseXML.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core" 3 | ], function( jQuery ) { 4 | 5 | // Cross-browser xml parsing 6 | jQuery.parseXML = function( data ) { 7 | var xml, tmp; 8 | if ( !data || typeof data !== "string" ) { 9 | return null; 10 | } 11 | 12 | // Support: IE9 13 | try { 14 | tmp = new DOMParser(); 15 | xml = tmp.parseFromString( data, "text/xml" ); 16 | } catch ( e ) { 17 | xml = undefined; 18 | } 19 | 20 | if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 21 | jQuery.error( "Invalid XML: " + data ); 22 | } 23 | return xml; 24 | }; 25 | 26 | return jQuery.parseXML; 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /bower_components/jquery/src/ajax/script.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "../ajax" 4 | ], function( jQuery ) { 5 | 6 | // Install script dataType 7 | jQuery.ajaxSetup({ 8 | accepts: { 9 | script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 10 | }, 11 | contents: { 12 | script: /(?:java|ecma)script/ 13 | }, 14 | converters: { 15 | "text script": function( text ) { 16 | jQuery.globalEval( text ); 17 | return text; 18 | } 19 | } 20 | }); 21 | 22 | // Handle cache's special case and crossDomain 23 | jQuery.ajaxPrefilter( "script", function( s ) { 24 | if ( s.cache === undefined ) { 25 | s.cache = false; 26 | } 27 | if ( s.crossDomain ) { 28 | s.type = "GET"; 29 | } 30 | }); 31 | 32 | // Bind script tag hack transport 33 | jQuery.ajaxTransport( "script", function( s ) { 34 | // This transport only deals with cross domain requests 35 | if ( s.crossDomain ) { 36 | var script, callback; 37 | return { 38 | send: function( _, complete ) { 39 | script = jQuery(" 34 | 35 | 65 | 66 |
67 |
68 |
69 | 70 |
71 | 72 |
73 | 83 |
84 |
85 | 86 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /lib/gif.js: -------------------------------------------------------------------------------- 1 | (function(c){function a(b,d){if({}.hasOwnProperty.call(a.cache,b))return a.cache[b];var e=a.resolve(b);if(!e)throw new Error('Failed to resolve module '+b);var c={id:b,require:a,filename:b,exports:{},loaded:!1,parent:d,children:[]};d&&d.children.push(c);var f=b.slice(0,b.lastIndexOf('/')+1);return a.cache[b]=c.exports,e.call(c.exports,c,c.exports,f,b),c.loaded=!0,a.cache[b]=c.exports}a.modules={},a.cache={},a.resolve=function(b){return{}.hasOwnProperty.call(a.modules,b)?a.modules[b]:void 0},a.define=function(b,c){a.modules[b]=c};var b=function(a){return a='/',{title:'browser',version:'v0.10.26',browser:!0,env:{},argv:[],nextTick:c.setImmediate||function(a){setTimeout(a,0)},cwd:function(){return a},chdir:function(b){a=b}}}();a.define('/gif.coffee',function(d,m,l,k){function g(a,b){return{}.hasOwnProperty.call(a,b)}function j(d,b){for(var a=0,c=b.length;athis.frames.length;0<=this.frames.length?++a:--a)b.push(a);return b}.apply(this,arguments),a=0,e=b.length;aa;0<=a?++b:--b)c.push(b);return c}.apply(this,arguments),b=0,e=c.length;ba;this.freeWorkers.length<=a?++b:--b)c.push(b);return c}.apply(this,arguments).forEach(function(a){return function(c){var b;return console.log('spawning worker '+c),b=new Worker(a.options.workerScript),b.onmessage=function(a){return function(c){return a.activeWorkers.splice(a.activeWorkers.indexOf(b),1),a.freeWorkers.push(b),a.frameFinished(c.data)}}(a),a.freeWorkers.push(b)}}(this)),a},a.prototype.frameFinished=function(a){return console.log('frame '+a.index+' finished - '+this.activeWorkers.length+' active'),this.finishedFrames++,this.emit('progress',this.finishedFrames/this.frames.length),this.imageParts[a.index]=a,j(null,this.imageParts)?this.renderNextFrame():this.finishRendering()},a.prototype.finishRendering=function(){var e,a,k,m,b,d,h;b=0;for(var f=0,j=this.imageParts.length;f=this.frames.length?void 0:(c=this.frames[this.nextFrame++],b=this.freeWorkers.shift(),a=this.getTask(c),console.log('starting frame '+(a.index+1)+' of '+this.frames.length),this.activeWorkers.push(b),b.postMessage(a))},a.prototype.getContextData=function(a){return a.getImageData(0,0,this.options.width,this.options.height).data},a.prototype.getImageData=function(b){var a;return null!=this._canvas||(this._canvas=document.createElement('canvas'),this._canvas.width=this.options.width,this._canvas.height=this.options.height),a=this._canvas.getContext('2d'),a.setFill=this.options.background,a.fillRect(0,0,this.options.width,this.options.height),a.drawImage(b,0,0),this.getContextData(a)},a.prototype.getTask=function(a){var c,b;if(c=this.frames.indexOf(a),b={index:c,last:c===this.frames.length-1,delay:a.delay,transparent:a.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,repeat:this.options.repeat,canTransfer:h.name==='chrome'},null!=a.data)b.data=a.data;else if(null!=a.context)b.data=this.getContextData(a.context);else if(null!=a.image)b.data=this.getImageData(a.image);else throw new Error('Invalid frame');return b},a}(f),d.exports=e}),a.define('/browser.coffee',function(f,g,h,i){var a,d,e,c,b;c=navigator.userAgent.toLowerCase(),e=navigator.platform.toLowerCase(),b=c.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,'unknown',0],d=b[1]==='ie'&&document.documentMode,a={name:b[1]==='version'?b[3]:b[1],version:d||parseFloat(b[1]==='opera'&&b[4]?b[4]:b[2]),platform:{name:c.match(/ip(?:ad|od|hone)/)?'ios':(c.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||['other'])[0]}},a[a.name]=!0,a[a.name+parseInt(a.version,10)]=!0,a.platform[a.platform.name]=!0,f.exports=a}),a.define('events',function(f,e,g,h){b.EventEmitter||(b.EventEmitter=function(){});var a=e.EventEmitter=b.EventEmitter,c=typeof Array.isArray==='function'?Array.isArray:function(a){return Object.prototype.toString.call(a)==='[object Array]'},d=10;a.prototype.setMaxListeners=function(a){this._events||(this._events={}),this._events.maxListeners=a},a.prototype.emit=function(f){if(f==='error'&&(!(this._events&&this._events.error)||c(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var a=this._events[f];if(!a)return!1;if(!(typeof a=='function'))if(c(a)){var b=Array.prototype.slice.call(arguments,1),e=a.slice();for(var d=0,g=e.length;d0&&this._events[a].length>e&&(this._events[a].warned=!0,console.error('(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.',this._events[a].length),console.trace())}this._events[a].push(b)}else this._events[a]=[this._events[a],b];return this},a.prototype.on=a.prototype.addListener,a.prototype.once=function(b,c){var a=this;return a.on(b,function d(){a.removeListener(b,d),c.apply(this,arguments)}),this},a.prototype.removeListener=function(a,d){if('function'!==typeof d)throw new Error('removeListener only takes instances of Function');if(!(this._events&&this._events[a]))return this;var b=this._events[a];if(c(b)){var e=b.indexOf(d);if(e<0)return this;b.splice(e,1),b.length==0&&delete this._events[a]}else this._events[a]===d&&delete this._events[a];return this},a.prototype.removeAllListeners=function(a){return a&&this._events&&this._events[a]&&(this._events[a]=null),this},a.prototype.listeners=function(a){return this._events||(this._events={}),this._events[a]||(this._events[a]=[]),c(this._events[a])||(this._events[a]=[this._events[a]]),this._events[a]}}),c.GIF=a('/gif.coffee')}.call(this,this)) 2 | //# sourceMappingURL=gif.js.map 3 | // gif.js 0.1.6 - https://github.com/jnordberg/gif.js 4 | -------------------------------------------------------------------------------- /lib/gif.worker.js: -------------------------------------------------------------------------------- 1 | (function(b){function a(b,d){if({}.hasOwnProperty.call(a.cache,b))return a.cache[b];var e=a.resolve(b);if(!e)throw new Error('Failed to resolve module '+b);var c={id:b,require:a,filename:b,exports:{},loaded:!1,parent:d,children:[]};d&&d.children.push(c);var f=b.slice(0,b.lastIndexOf('/')+1);return a.cache[b]=c.exports,e.call(c.exports,c,c.exports,f,b),c.loaded=!0,a.cache[b]=c.exports}a.modules={},a.cache={},a.resolve=function(b){return{}.hasOwnProperty.call(a.modules,b)?a.modules[b]:void 0},a.define=function(b,c){a.modules[b]=c},a.define('/gif.worker.coffee',function(d,e,f,g){var b,c;b=a('/GIFEncoder.js',d),c=function(a){var c,e,d,f;return c=new b(a.width,a.height),a.index===0?c.writeHeader():c.firstFrame=!1,c.setTransparent(a.transparent),c.setRepeat(a.repeat),c.setDelay(a.delay),c.setQuality(a.quality),c.addFrame(a.data),a.last&&c.finish(),d=c.stream(),a.data=d.pages,a.cursor=d.cursor,a.pageSize=d.constructor.pageSize,a.canTransfer?(f=function(c){for(var b=0,d=a.data.length;b=c.pageSize&&this.newPage(),this.pages[this.page][this.cursor++]=a},c.prototype.writeUTFBytes=function(b){for(var c=b.length,a=0;a=0&&(this.dispose=a)},b.prototype.setRepeat=function(a){this.repeat=a},b.prototype.setTransparent=function(a){this.transparent=a},b.prototype.addFrame=function(a){this.image=a,this.getImagePixels(),this.analyzePixels(),this.firstFrame&&(this.writeLSD(),this.writePalette(),this.repeat>=0&&this.writeNetscapeExt()),this.writeGraphicCtrlExt(),this.writeImageDesc(),this.firstFrame||this.writePalette(),this.writePixels(),this.firstFrame=!1},b.prototype.finish=function(){this.out.writeByte(59)},b.prototype.setQuality=function(a){a<1&&(a=1),this.sample=a},b.prototype.writeHeader=function(){this.out.writeUTFBytes('GIF89a')},b.prototype.analyzePixels=function(){var g=this.pixels.length,d=g/3;this.indexedPixels=new Uint8Array(d);var a=new f(this.pixels,this.sample);a.buildColormap(),this.colorTab=a.getColormap();var b=0;for(var c=0;c>16,l=(e&65280)>>8,m=e&255,c=0,d=16777216,j=this.colorTab.length;for(var a=0;a=0&&(a=dispose&7),a<<=2,this.out.writeByte(0|a|0|b),this.writeShort(this.delay),this.out.writeByte(this.transIndex),this.out.writeByte(0)},b.prototype.writeImageDesc=function(){this.out.writeByte(44),this.writeShort(0),this.writeShort(0),this.writeShort(this.width),this.writeShort(this.height),this.firstFrame?this.out.writeByte(0):this.out.writeByte(128|this.palSize)},b.prototype.writeLSD=function(){this.writeShort(this.width),this.writeShort(this.height),this.out.writeByte(240|this.palSize),this.out.writeByte(0),this.out.writeByte(0)},b.prototype.writeNetscapeExt=function(){this.out.writeByte(33),this.out.writeByte(255),this.out.writeByte(11),this.out.writeUTFBytes('NETSCAPE2.0'),this.out.writeByte(3),this.out.writeByte(1),this.writeShort(this.repeat),this.out.writeByte(0)},b.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);var b=768-this.colorTab.length;for(var a=0;a>8&255)},b.prototype.writePixels=function(){var a=new g(this.width,this.height,this.indexedPixels,this.colorDepth);a.encode(this.out)},b.prototype.stream=function(){return this.out},e.exports=b}),a.define('/LZWEncoder.js',function(e,g,h,i){function f(y,D,C,B){function w(a,b){r[f++]=a,f>=254&&t(b)}function x(b){u(a),k=i+2,j=!0,l(i,b)}function u(b){for(var a=0;a=0){y=w-d,d===0&&(y=1);do if((d-=y)<0&&(d+=w),h[d]===g){e=n[d];continue a}while(h[d]>=0)}l(e,r),e=t,k<1<0&&(a.writeByte(f),a.writeBytes(r,0,f),f=0)}function p(a){return(1<0?g|=a<=8)w(g&255,c),g>>=8,e-=8;if((k>m||j)&&(j?(m=p(n_bits=q),j=!1):(++n_bits,n_bits==b?m=1<0)w(g&255,c),g>>=8,e-=8;t(c)}}var s=Math.max(2,B),r=new Uint8Array(256),h=new Int32Array(a),n=new Int32Array(a),g,e=0,f,k=0,m,j=!1,q,i,o;this.encode=z}var c=-1,b=12,a=5003,d=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];e.exports=f}),a.define('/TypedNeuQuant.js',function(A,F,E,D){function C(A,B){function I(){o=[],q=new Int32Array(256),t=new Int32Array(a),y=new Int32Array(a),z=new Int32Array(a>>3);var c,d;for(c=0;c>=b,o[c][1]>>=b,o[c][2]>>=b,o[c][3]=c}function K(b,a,c,e,f){o[a][0]-=b*(o[a][0]-c)/d,o[a][1]-=b*(o[a][1]-e)/d,o[a][2]-=b*(o[a][2]-f)/d}function L(j,e,n,l,k){var h=Math.abs(e-j),i=Math.min(e+j,a),g=e+1,f=e-1,m=1,b,d;while(gh)d=z[m++],gh&&(b=o[f--],b[0]-=d*(b[0]-n)/c,b[1]-=d*(b[1]-l)/c,b[2]-=d*(b[2]-k)/c)}function C(p,s,q){var h=2147483647,k=h,d=-1,m=d,c,j,e,n,l;for(c=0;c>i-b),n>g,y[c]-=l,t[c]+=l<>1,b=f+1;b>1,b=f+1;b<256;b++)q[b]=n}function E(j,i,k){var b,d,c,e=1e3,h=-1,f=q[i],g=f-1;while(f=0)f=e?f=a:(f++,c<0&&(c=-c),b=d[0]-j,b<0&&(b=-b),c+=b,c=0&&(d=o[g],c=i-d[1],c>=e?g=-1:(g--,c<0&&(c=-c),b=d[0]-j,b<0&&(b=-b),c+=b,c>h;for(a<=1&&(a=0),c=0;c=f&&(g-=f),c++,q===0&&(q=1),c%q===0)for(n-=n/D,o-=o/v,a=o>>h,a<=1&&(a=0),e=0;e>g,r=e<>3,h=6,t=1< div { 279 | background-color: #666666; 280 | height: 100%; 281 | width: 6px; 282 | display: inline-block; 283 | -webkit-animation: stretchdelay 1.2s infinite ease-in-out; 284 | animation: stretchdelay 1.2s infinite ease-in-out; 285 | } 286 | 287 | .spinner .rect2 { 288 | -webkit-animation-delay: -1.1s; 289 | animation-delay: -1.1s; 290 | } 291 | 292 | .spinner .rect3 { 293 | -webkit-animation-delay: -1.0s; 294 | animation-delay: -1.0s; 295 | } 296 | 297 | .spinner .rect4 { 298 | -webkit-animation-delay: -0.9s; 299 | animation-delay: -0.9s; 300 | } 301 | 302 | .spinner .rect5 { 303 | -webkit-animation-delay: -0.8s; 304 | animation-delay: -0.8s; 305 | } 306 | 307 | #carbonads { 308 | position: fixed; 309 | display: block; 310 | left: 0; 311 | bottom: 0; 312 | width: 320px; 313 | background: #fff; 314 | border: 1px solid #e7e7e7; 315 | border-bottom: none; 316 | font-size: 13.5px; 317 | line-height: 17.5px; 318 | padding: 0.9375rem 0.9375rem 0.5rem; 319 | } 320 | 321 | #carbonads a { 322 | text-decoration: none; 323 | color: #000; 324 | } 325 | 326 | .carbon-img, 327 | .carbon-text { 328 | float: left; 329 | } 330 | 331 | .carbon-text { 332 | display: block; 333 | max-width: 50%; 334 | text-align: left; 335 | padding-bottom: 0.5rem; 336 | padding-left: 0.9375rem; 337 | } 338 | 339 | .carbon-poweredby { 340 | display: block; 341 | color: #b1b1b1; 342 | float: right; 343 | font-size: .8em; 344 | } 345 | 346 | @-webkit-keyframes stretchdelay { 347 | 0%, 40%, 100% { 348 | -webkit-transform: scaleY(0.4) 349 | } 350 | 20% { 351 | -webkit-transform: scaleY(1.0) 352 | } 353 | } 354 | 355 | @keyframes stretchdelay { 356 | 0%, 40%, 100% { 357 | transform: scaleY(0.4); 358 | -webkit-transform: scaleY(0.4); 359 | } 360 | 20% { 361 | transform: scaleY(1.0); 362 | -webkit-transform: scaleY(1.0); 363 | } 364 | } 365 | 366 | 367 | @media (max-width: 760px) { 368 | .site__content { 369 | max-width: 360px; 370 | height: 840px; 371 | } 372 | 373 | .slate__config ul { 374 | margin: 0 25px; 375 | } 376 | 377 | .slate__config { 378 | float: none; 379 | } 380 | 381 | .slate__preview { 382 | float: none; 383 | } 384 | 385 | #result { 386 | width: 340px; 387 | margin: 9px; 388 | } 389 | .github-ribbon { 390 | display: none; 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/img/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/src/img/down_arrow.png -------------------------------------------------------------------------------- /src/img/down_arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitshadow/slate/c82e7df98d41f1e4e72dc5fe4b2f9da766b741a3/src/img/favicon.png -------------------------------------------------------------------------------- /src/js/app.js: -------------------------------------------------------------------------------- 1 | import SlateModel from './models/slate.js'; 2 | import SlateConfigView from './views/slateConfig.js'; 3 | import SlateView from './views/slate.js'; 4 | import ShareView from './views/share.js'; 5 | 6 | let { View } = Backbone; 7 | 8 | class SlateApp extends View { 9 | constructor(options) { 10 | super(options); 11 | 12 | let model = new SlateModel(); 13 | 14 | this.slateConfigView = new SlateConfigView({ 15 | model: model, 16 | el: $('.slate__config') 17 | }); 18 | 19 | this.slateView = new SlateView({ 20 | model: model, 21 | el: $('.slate__preview') 22 | }); 23 | 24 | this.shareView = new ShareView({ 25 | model: model, 26 | el: $('.share-box') 27 | }); 28 | } 29 | 30 | render() { 31 | this.slateConfigView.render(); 32 | this.slateView.render(); 33 | } 34 | } 35 | 36 | (new SlateApp()).render() 37 | -------------------------------------------------------------------------------- /src/js/models/slate.js: -------------------------------------------------------------------------------- 1 | import { colors, quotes } from '../modules/constants'; 2 | 3 | let { Model } = Backbone; 4 | export default class extends Model{ 5 | defaults() { 6 | let bgColor = colors[Math.floor(Math.random() * colors.length)]; 7 | let quote = quotes[Math.floor(Math.random() * quotes.length)] 8 | return { 9 | bgColor: bgColor, 10 | textColor: '#fff', 11 | family: 'Georgia', 12 | text: quote, 13 | width: 360, 14 | height: 400, 15 | fontHeight: 35, 16 | delay: 300 17 | } 18 | } 19 | }; -------------------------------------------------------------------------------- /src/js/modules/constants.js: -------------------------------------------------------------------------------- 1 | const colors = [ 2 | '#B7D438', 3 | '#1C747F', 4 | '#4B687C', 5 | '#5CB932', 6 | '#EF7409', 7 | '#F3D063', 8 | '#31B98E', 9 | '#6AA398', 10 | '#D55A29', 11 | '#B32B54', 12 | '#FBB30D', 13 | '#621239', 14 | '#315873', 15 | '#C12E01', 16 | '#671C41', 17 | '#22A1FF', 18 | '#621239', 19 | '#6CC08E', 20 | '#3B8187', 21 | '#D3192F', 22 | '#80A000', 23 | '#F48200', 24 | '#000C3B', 25 | '#3B8187', 26 | '#BE1E2D', 27 | '#1A2728', 28 | '#5F8964', 29 | '#EA5F61', 30 | '#BA4938', 31 | '#185546', 32 | '#4667B2', 33 | '#74A187', 34 | '#F10043', 35 | '#EEA623', 36 | '#3B5C79' 37 | ]; 38 | 39 | const quotes = [ 40 | 'The Shortest Answer Is Doing The Thing.', 41 | "Don't Just Be Good To Others. Be Good To Yourself To.", 42 | 'Its Ok To Be Happy With A Calm Life', 43 | 'Stay True In Dark And Humble In Spotlight.', 44 | 'I DONT WANT PERFECT I WANT HONEST', 45 | "Hard Days Are The Best Because That's When Champions Are Made", 46 | 'KEEP KALM AND LET IT GO', 47 | "Whether You Think You Can Our You Can't You're Right", 48 | "You know What's One Wrong Thing We Do When We Fall In Love? WE EXPECT ☹ ", 49 | 'NOT TO SPOIL THE ENDING FOR YOU, BUT EVERYTHING IS GOING TO BE OK ', 50 | 'TRUST ME YOU CAN DANCE -VODKA' 51 | ]; 52 | 53 | export { colors, quotes }; -------------------------------------------------------------------------------- /src/js/modules/fonts.js: -------------------------------------------------------------------------------- 1 | let fonts = [ 2 | 'Andale Mono', 3 | 'Arial Black', 4 | 'Arial Narrow', 5 | 'Arial Rounded MT Bold', 6 | 'Arial', 7 | 'Avant Garde', 8 | 'Baskerville', 9 | 'Big Caslon', 10 | 'Bodoni MT', 11 | 'Book Antiqua', 12 | 'Brush Script MT', 13 | 'Calibri', 14 | 'Calisto MT', 15 | 'Cambria', 16 | 'Candara', 17 | 'Century Gothic', 18 | 'Consolas', 19 | 'Copperplate', 20 | 'Courier New', 21 | 'Didot', 22 | 'Franklin Gothic Medium', 23 | 'Futura', 24 | 'Garamond', 25 | 'Geneva', 26 | 'Georgia', 27 | 'Gill Sans', 28 | 'Goudy Old Style', 29 | 'Helvetica', 30 | 'Hoefler Text', 31 | 'Impact', 32 | 'Lucida Bright', 33 | 'Lucida Console', 34 | 'Lucida Grande', 35 | 'Lucida Sans Typewriter', 36 | 'Monaco', 37 | 'Optima', 38 | 'Palatino', 39 | 'Papyrus', 40 | 'Perpetua', 41 | 'Rockwell Extra Bold', 42 | 'Rockwell', 43 | 'Segoe UI', 44 | 'Tahoma', 45 | 'Times New Roman', 46 | 'Trebuchet MS', 47 | 'Verdana' 48 | ]; 49 | 50 | 51 | function Detector() { 52 | // a font will be compared against all the three default fonts. 53 | // and if it doesn't match all 3 then that font is not available. 54 | let baseFonts = ['monospace', 'sans-serif', 'serif']; 55 | 56 | //we use m or w because these two characters take up the maximum width. 57 | // And we use a LLi so that the same matching fonts can get separated 58 | let testString = "mmmmmmmmmmlli"; 59 | 60 | //we test using 72px font size, we may use any size. I guess larger the better. 61 | let testSize = '72px'; 62 | 63 | let h = document.getElementsByTagName("body")[0]; 64 | 65 | // create a SPAN in the document to get the width of the text we use to test 66 | let s = document.createElement("span"); 67 | s.style.fontSize = testSize; 68 | s.innerHTML = testString; 69 | let defaultWidth = {}; 70 | let defaultHeight = {}; 71 | for (let index in baseFonts) { 72 | //get the default width for the three base fonts 73 | s.style.fontFamily = baseFonts[index]; 74 | h.appendChild(s); 75 | //width for the default font 76 | defaultWidth[baseFonts[index]] = s.offsetWidth; 77 | //height for the defualt font 78 | defaultHeight[baseFonts[index]] = s.offsetHeight; 79 | h.removeChild(s); 80 | } 81 | 82 | let detect = (font) => { 83 | let detected = false; 84 | for (let index in baseFonts) { 85 | // name of the font along with the base font for fallback. 86 | s.style.fontFamily = font + ',' + baseFonts[index]; 87 | h.appendChild(s); 88 | let matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]); 89 | h.removeChild(s); 90 | detected = detected || matched; 91 | } 92 | return detected; 93 | } 94 | 95 | this.detect = detect; 96 | }; 97 | 98 | let d = new Detector(); 99 | let supportedFonts = []; 100 | fonts.forEach((font) => { 101 | if (d.detect(font)) { 102 | supportedFonts.push(font); 103 | } 104 | }); 105 | 106 | export default supportedFonts; 107 | -------------------------------------------------------------------------------- /src/js/modules/slate.js: -------------------------------------------------------------------------------- 1 | export default { 2 | setFont(ctx) { 3 | let fontSize = (this.fontHeight * this.scale) + 'px'; 4 | ctx.font = fontSize + '/' + fontSize + ' ' + this.family; 5 | }, 6 | 7 | createDummy() { 8 | let dummy = document.createElement('canvas'); 9 | dummy.width = this.width * this.scale; 10 | dummy.height = this.height * this.scale; 11 | 12 | return dummy.getContext('2d'); 13 | }, 14 | 15 | drawBackground(ctx) { 16 | let w = ctx.canvas.width; 17 | let h = ctx.canvas.height; 18 | 19 | ctx.fillStyle = this.bgColor; 20 | ctx.fillRect(0, 0, w, h); 21 | }, 22 | 23 | drawText(ctx, text) { 24 | let mw = ctx.canvas.width / 2; 25 | let mh = ctx.canvas.height / 2; 26 | 27 | ctx.textAlign = 'center'; 28 | ctx.textBaseline = 'middle'; 29 | ctx.fillStyle = this.textColor; 30 | ctx.fillText(text, mw, mh); 31 | }, 32 | 33 | drawDummy(ctx, dummy) { 34 | let w = ctx.canvas.width; 35 | let h = ctx.canvas.height; 36 | 37 | ctx.drawImage(dummy.canvas, 0, 0, w, h); 38 | }, 39 | 40 | getCanvas(options) { 41 | let canvas = document.createElement('canvas'); 42 | canvas.width = this.width; 43 | canvas.height = this.height; 44 | 45 | return canvas; 46 | }, 47 | 48 | setProperties(options) { 49 | this.bgColor = options.bgColor; 50 | this.height = options.height; 51 | this.width = options.width; 52 | this.text = options.text || ''; 53 | this.textColor = options.textColor; 54 | this.delay = options.delay || 0; 55 | this.fontHeight = options.fontHeight || 0; 56 | this.family = options.family || 'Georgia, serif'; 57 | this.scale = 2; 58 | }, 59 | 60 | renderGif(element) { 61 | let _this = this; 62 | let ctx = _this.getCanvas().getContext('2d'); 63 | let dummy = _this.createDummy(); 64 | let gif = _this.getGifCreator(element); 65 | 66 | _this.setFont(dummy); 67 | 68 | let words = this.text.split(' '); 69 | for (let i = 0, l = words.length; i < l; i++) { 70 | _this.drawBackground(dummy); 71 | _this.drawText(dummy, words[i]); 72 | 73 | _this.drawDummy(ctx, dummy); 74 | gif.addFrame(ctx, { 75 | copy: true, 76 | delay: _this.delay 77 | }); 78 | } 79 | 80 | _this.drawBackground(dummy); 81 | _this.drawDummy(ctx, dummy); 82 | gif.addFrame(ctx, { 83 | delay: 2 * _this.delay 84 | }); 85 | 86 | gif.render(); 87 | }, 88 | 89 | getStyles(obj) { 90 | let str = ''; 91 | 92 | for (let prop in obj) { 93 | if(obj.hasOwnProperty(prop)) { 94 | str += prop + ':' + obj[prop] + ';'; 95 | } 96 | } 97 | 98 | return str; 99 | }, 100 | 101 | getSVG(dummy) { 102 | let outer = { 103 | display: 'table-cell', 104 | width: dummy.canvas.width + 'px', 105 | height: dummy.canvas.height + 'px', 106 | color: this.textColor, 107 | 'font-size': (this.fontHeight * this.scale) + 'px', 108 | 'font-family': this.family, 109 | 'vertical-align': 'middle' 110 | }; 111 | 112 | let width = (dummy.canvas.width) - 20; 113 | let inner = { 114 | margin: '0 auto', 115 | width: width + 'px', 116 | 'word-wrap': 'break-word' 117 | }; 118 | 119 | let data = "data:image/svg+xml," + 120 | "" + 121 | "" + 122 | "
" + 123 | "
" + this.text.trim() +"
" + 124 | "
" + 125 | "
" + 126 | "
"; 127 | 128 | return data; 129 | }, 130 | 131 | renderImage(element) { 132 | let _this = this; 133 | let ctx = _this.getCanvas().getContext('2d'); 134 | let dummy = _this.createDummy(); 135 | let gif = _this.getGifCreator(element); 136 | 137 | let DOMURL = window.URL || window.webkitURL || window; 138 | let img = new Image(); 139 | // let svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'}); 140 | // let url = DOMURL.createObjectURL(svg); 141 | 142 | img.onload = function() { 143 | _this.drawBackground(dummy); 144 | // _this.drawText(dummy, 'Hello world there is awesome thing to be learned'); 145 | dummy.drawImage(img, 0, 0); 146 | _this.drawDummy(ctx, dummy); 147 | gif.addFrame(ctx, { 148 | delay: 0 149 | }); 150 | 151 | gif.render(); 152 | } 153 | 154 | img.src = this.getSVG(dummy); 155 | }, 156 | 157 | render(element) { 158 | if (this.delay > 0) { 159 | this.renderGif(element); 160 | } else { 161 | this.renderImage(element); 162 | } 163 | 164 | }, 165 | 166 | getGifCreator(callback) { 167 | let _this = this; 168 | let gif = new GIF({ 169 | workers: 2, 170 | quality: 10, 171 | width: _this.width, 172 | height: _this.height 173 | }); 174 | 175 | gif.on('finished', (blob, data) => { 176 | let obj = btoa(String.fromCharCode.apply(null, data)); 177 | callback(null, obj); 178 | }); 179 | 180 | return gif; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/js/views/share.js: -------------------------------------------------------------------------------- 1 | import slate from '../modules/slate'; 2 | import config from '../config/share'; 3 | 4 | let { View } = Backbone; 5 | 6 | export default class extends View { 7 | constructor(options) { 8 | _.defaults(options, { 9 | events: { 10 | 'click .get-url': 'upload' 11 | } 12 | }); 13 | 14 | super(options); 15 | 16 | let _this = this; 17 | _this.listenTo(_this.model, 'change', () => { 18 | if (_this.model.hasChanged('url')) { 19 | _this.render(); 20 | } else { 21 | _this.render(); 22 | _this.hideLoading(); 23 | _this.model.unset('url'); 24 | } 25 | }); 26 | 27 | _this.template = _.template($('script.share-template').html()); 28 | } 29 | 30 | postRender() { 31 | let url = this.model.get('url'); 32 | if (url) { 33 | this.$('.url').get(0).select(); 34 | this.$('.url-btn').addClass('hide'); 35 | this.showShare(url) 36 | } 37 | 38 | this.hideLoading(); 39 | } 40 | 41 | render() { 42 | let $sharer = this.$('.sharer'); 43 | let obj = { 44 | model: this.model.attributes 45 | }; 46 | 47 | $sharer.html(''); 48 | $sharer.html(this.template(obj)); 49 | this.postRender(); 50 | } 51 | 52 | showShare(url) { 53 | this.$('.share-btn').hideshare({ 54 | link: url, 55 | media: url + '.gif', 56 | position: 'right', 57 | linkedin: false, 58 | title: 'Created with Slate. http://bitshadow.github.io/slate' 59 | }); 60 | } 61 | 62 | showLoading() { 63 | $('.spinner').removeClass('hide'); 64 | this.$('.url-btn').addClass('hide'); 65 | } 66 | 67 | hideLoading() { 68 | $('.spinner').addClass('hide'); 69 | } 70 | 71 | upload() { 72 | this.showLoading(); 73 | let _this = this; 74 | let auth = 'Client-ID ' + 'f0972432933fc36'; 75 | $.ajax({ 76 | url: 'https://api.imgur.com/3/image', 77 | type: 'POST', 78 | headers: { 79 | Authorization: auth, 80 | Accept: 'application/json' 81 | }, 82 | data: { 83 | image: localStorage.dataBase64, 84 | type: 'base64' 85 | }, 86 | success(result) { 87 | let id = result.data.id; 88 | _this.model.set('url', 'http://imgur.com/' + id); 89 | console.log('image upload with this id', id); 90 | }, 91 | error(e) { 92 | console.log(e); 93 | } 94 | }); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/js/views/slate.js: -------------------------------------------------------------------------------- 1 | let { View } = Backbone; 2 | import slate from '../modules/slate'; 3 | 4 | export default class extends View { 5 | constructor(options) { 6 | super(options); 7 | 8 | this.listenTo(this.model, 'change', this.render); 9 | } 10 | 11 | render() { 12 | slate.setProperties(this.model.toJSON()); 13 | slate.render((err, data) => { 14 | let element = $('#result'); 15 | element.removeClass('hide'); 16 | element.attr('src', 'data:image/gif;base64,' + data); 17 | localStorage.dataBase64 = data; 18 | }); 19 | } 20 | } -------------------------------------------------------------------------------- /src/js/views/slateConfig.js: -------------------------------------------------------------------------------- 1 | import fonts from '../modules/fonts'; 2 | 3 | let { 4 | View 5 | } = Backbone; 6 | 7 | export default class extends View { 8 | constructor(options) { 9 | _.defaults(options, { 10 | events: { 11 | 'change .text-color': '_updateModel', 12 | 'change .bg-color': '_updateModel', 13 | 'keyup .text': 'setText', 14 | 'change .family': '_updateModel', 15 | 'keyup .delay': '_updateModel', 16 | 'keyup .font-height': '_updateModel', 17 | 'keydown .delay': '_updateInput', 18 | 'keydown .font-height': '_updateInput', 19 | } 20 | }); 21 | 22 | super(options); 23 | this.fonts = fonts; 24 | this.template = _.template($('script.slate-config').html()); 25 | } 26 | 27 | initialize() { 28 | this._setDebouncedText = _.debounce(_.bind(this.setDebouncedText, this), 300); 29 | } 30 | 31 | render() { 32 | this.$el.append(this.template({ 33 | model: this.model.attributes 34 | })); 35 | this.postRender(); 36 | } 37 | 38 | postRender() { 39 | let select = this.$('.family'); 40 | 41 | let str = '' 42 | this.fonts.forEach((font) => { 43 | let selected = font.name === this.model.get('family') ? 'selected' : ''; 44 | str += ''; 45 | }); 46 | 47 | select.append(str); 48 | 49 | let keys = ['bgColor', 'textColor', 'text']; 50 | keys.forEach((key) => { 51 | this.$('[name="' + key + '"]').val(this.model.get(key)); 52 | }); 53 | } 54 | 55 | setDebouncedText(text) { 56 | this.model.set({ 57 | text: text 58 | }); 59 | } 60 | 61 | setText(e) { 62 | let text = $(e.target).val(); 63 | this._setDebouncedText(text); 64 | } 65 | 66 | _updateInput(ev) { 67 | if (ev.keyCode != 38 && ev.keyCode != 40) return; 68 | 69 | let target = $(ev.currentTarget), 70 | val = parseInt(target.val()), 71 | increment = ev.keyCode == 38 ? 1 : -1, 72 | multiply = ev.shiftKey ? 10 : 1, 73 | newVal = val + increment * multiply; 74 | 75 | if (newVal < 0) newVal = 0; 76 | 77 | target.val(newVal); 78 | } 79 | 80 | _updateModel(ev) { 81 | let target = $(ev.currentTarget), 82 | val = target.val(), 83 | attr; 84 | 85 | attr = target.attr('name'); 86 | 87 | if (attr === 'fontHeight' || attr === 'delay') val = parseInt(val, 10); 88 | if (attr === 'textColor' || attr === 'bgColor') val = '#' + val; 89 | 90 | this.model.set(attr, val); 91 | } 92 | 93 | setAttributes(e) { 94 | let text = $('[name="text"]').val(); 95 | this.model.set({ 96 | text: text 97 | }); 98 | } 99 | } 100 | --------------------------------------------------------------------------------