├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .jshintrc ├── .travis.yml ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── demo ├── README-logo.png ├── index.html ├── index_annyang.html ├── sample_sites │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ └── 4.jpg └── speechkitt-demo.gif ├── dist ├── speechkitt.min.js └── themes │ ├── basic.css │ ├── basic.css.map │ ├── flat-amethyst.css │ ├── flat-amethyst.css.map │ ├── flat-clouds.css │ ├── flat-clouds.css.map │ ├── flat-concrete.css │ ├── flat-concrete.css.map │ ├── flat-emerald.css │ ├── flat-emerald.css.map │ ├── flat-midnight-blue.css │ ├── flat-midnight-blue.css.map │ ├── flat-orange.css │ ├── flat-orange.css.map │ ├── flat-pomegranate.css │ ├── flat-pomegranate.css.map │ ├── flat-pumpkin.css │ ├── flat-pumpkin.css.map │ ├── flat-turquoise.css │ ├── flat-turquoise.css.map │ ├── flat.css │ └── flat.css.map ├── docs └── README.md ├── package-lock.json ├── package.json ├── src └── speechkitt.js ├── test ├── SpecRunner.html ├── helper_functions.js ├── init_corti.js ├── spec │ ├── .jshintrc │ ├── 1_BasicSpec.js │ ├── 2_UISpec.js │ └── 3_FunctionalSpec.js └── vendor │ ├── annyang.min.js │ ├── corti.js │ ├── jasmine-jquery.js │ └── jquery-2.1.4.min.js ├── themes ├── basic.scss ├── flat-amethyst │ └── flat-amethyst.scss ├── flat-clouds │ └── flat-clouds.scss ├── flat-concrete │ └── flat-concrete.scss ├── flat-emerald │ └── flat-emerald.scss ├── flat-midnight-blue │ └── flat-midnight-blue.scss ├── flat-orange │ └── flat-orange.scss ├── flat-pomegranate │ └── flat-pomegranate.scss ├── flat-pumpkin │ └── flat-pumpkin.scss ├── flat-turquoise │ └── flat-turquoise.scss └── flat │ └── flat.scss └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended" 8 | ], 9 | "parserOptions": { 10 | "sourceType": "module" 11 | }, 12 | "rules": { 13 | "no-console": 0, 14 | "indent": [ 15 | "error", 16 | 2 17 | ], 18 | "linebreak-style": [ 19 | "error", 20 | "unix" 21 | ], 22 | "quotes": [ 23 | "error", 24 | "single" 25 | ], 26 | "semi": [ 27 | "error", 28 | "always" 29 | ] 30 | }, 31 | "globals": { 32 | "annyang": false 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | demo/* linguist-documentation 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Expected Behavior 4 | 5 | 6 | 7 | ## Current Behavior 8 | 9 | 10 | 11 | ## Possible Solution 12 | 13 | 14 | 15 | ## Steps to Reproduce (for bugs) 16 | 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 4. 22 | 23 | ## Context 24 | 25 | 26 | 27 | ## Your Environment 28 | 29 | * Version used: 30 | * Browser Name and version: 31 | * Operating System and version (desktop or mobile): 32 | * Link to your project: 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | ## Screenshots (if appropriate): 16 | 17 | ## Types of changes 18 | 19 | - [ ] Bug fix (non-breaking change which fixes an issue) 20 | - [ ] New feature (non-breaking change which adds functionality) 21 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 22 | 23 | ## Checklist: 24 | 25 | 26 | - [ ] My code follows the code style of this project. 27 | - [ ] My change requires a change to the documentation. 28 | - [ ] I have updated the documentation accordingly. 29 | - [ ] I have read the **CONTRIBUTING** document. 30 | - [ ] I have added tests to cover my changes. 31 | - [ ] All new and existing tests passed. 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .grunt 3 | .idea 4 | test/coverage 5 | .sass-cache 6 | .DS_Store 7 | npm-debug.log 8 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node" : true, 3 | "browser" : true, 4 | "devel" : false, 5 | "camelcase" : true, 6 | "curly" : true, 7 | "latedef" : true, 8 | "unused" : true, 9 | "trailing" : true, 10 | "eqeqeq" : true, 11 | "eqnull" : true, 12 | "evil" : false, 13 | "forin" : true, 14 | "immed" : true, 15 | "laxbreak" : false, 16 | "newcap" : true, 17 | "noarg" : true, 18 | "noempty" : false, 19 | "nonew" : true, 20 | "onevar" : false, 21 | "plusplus" : false, 22 | "undef" : true, 23 | "sub" : true, 24 | "strict" : true, 25 | "white" : false, 26 | "indent" : 2, 27 | "globals": { 28 | "annyang": false 29 | } 30 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - '8' 5 | - '6' 6 | - 'node' 7 | before_script: 8 | - gem update --system 9 | - gem install sass 10 | - 'npm install -g grunt-cli' 11 | - 'grunt' 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Speech KITT 2 | 3 | Thank you for taking the time to get involved with Speech KITT! :+1: 4 | 5 | There are several ways you can help the project out: 6 | 7 | * [Contributing code](#contributing-code) 8 | * [Reporting Bugs](#reporting-bugs) 9 | * [Feature Requests and Ideas](#feature-requests-and-ideas) 10 | 11 | ## How Can I Contribute? 12 | 13 | ### Contributing Code 14 | 15 | - [x] Fork the repository from the [Speech KITT GitHub page](https://github.com/TalAter/SpeechKITT). 16 | - [x] Clone a copy to your local machine with `$ git clone git@github.com:YOUR-GITHUB-USER-NAME/SpeechKITT.git` 17 | - [x] Make sure you have *node.js* and *npm* installed on your machine. You can use this [guide](https://docs.npmjs.com/getting-started/installing-node) for help. 18 | - [x] Install all of Speech KITT's development dependencies with npm. `$ cd SpeechKITT; npm install` 19 | - [x] Run grunt to make sure everything runs smoothly `$ grunt` 20 | - [x] Add tests for your code. [See details below](#automated-testing). 21 | - [x] Code, code, code. 22 | - [x] Run `$ grunt` after making changes to verify that everything still works and run the build process. Alternatively, you can just run `$ grunt watch` once, and leave that process running. It will continuously run all the tests and build the files every time you make a change to one of Speech KITT's files. It will even *beep* if you make an error, and help you debug it.:+1: 23 | - [x] Before committing your changes, the last step must always be running `$ grunt`. This makes sure everything works, and all files are kept up to date with your changes. 24 | - [x] Once you've made sure all your changes work correctly and have been committed, push your local changes back to github with `$ git push -u origin master` 25 | - [x] Visit your fork on GitHub.com ([https://github.com/YOUR-USER-NAME/SpeechKITT](https://github.com/YOUR-USER-NAME/SpeechKITT)) and create a pull request for your changes. 26 | - [x] Makes sure your pull request describes exactly what you changed and if it relates to an open issue references that issue (just include the issue number in the title like this: #49) 27 | 28 | #### Important: 29 | 30 | * Make sure to run `npm install` and `grunt` and make sure all tasks completed successfully before committing. 31 | * Do not change the [API docs](https://github.com/TalAter/SpeechKITT/blob/master/docs/README.md) in `/docs/README.md` directly. This file is generated automatically, and your changes will be overwritten. Instead, update the relevant comments in speechkitt.js 32 | * If you make any changes, please make sure to test your changes thoroughly to make sure no backward functionality was broken, and that your changes work as intended. 33 | * Do not update the version number yourself. 34 | * Please stick to the project's existing coding style. Coding styles don't need to have a consensus, they just need to be consistent :smile:. 35 | * Push your changes to a topic branch in your fork of the repository. Your branch should be based on the `master` branch. 36 | * When submitting [pull request](https://help.github.com/articles/using-pull-requests/), please elaborate as much as possible about the change, your motivation for the change, etc. 37 | 38 | #### Automated Testing 39 | 40 | Speech KITT is tested using [Jasmine](http://jasmine.github.io/2.0/introduction.html). 41 | 42 | Please include tests for any changes you make: 43 | * If you found a bug, please write a test that fails because of that bug, then fix the bug so that the test passes. 44 | * If you are adding a new feature, write tests that thoroughly test every possible use of your code. 45 | * If you are changing existing functionality, make sure to update existing tests so they pass. (This is a last resort. Whenever possible try to maintain backwards compatibility) 46 | 47 | The tests reside in *BasicSpec.js* and *UISpec.js*. These file contains a series of spec groups (e.g. `describe('a spec group', function() {});`) which each contain 1 or more specs (e.g. `it('should do stuff', function() {});`). Some of the spec groups also contain some code which runs before each spec (`beforeEach(function() {});`). When adding a test you can usually find the appropriate file to add your tests to by looking at existing tests for similar functionality. 48 | 49 | To simulate Speech Recognition in the testing environment, Speech KITT uses a mock object called [Corti](https://github.com/TalAter/Corti) which mocks the browser's SpeechRecognition object. Corti also adds a number of utility functions to the SpeechRecognition object which simulate user actions (e.g. `say('Hello there')`), and allow checking the SpeechRecognition's status (e.g. `isListening() === true`). 50 | 51 | ### Reporting Bugs 52 | 53 | Bugs are tracked as [GitHub issues](https://github.com/TalAter/SpeechKITT/issues). If you found a bug with Speech KITT, the quickest way to get help would be to look through existing open and closed [GitHub issues](https://github.com/TalAter/SpeechKITT/issues?q=is%3Aissue). If the issue is already being discussed and hasn't been resolved yet, you can join the discussion and provide details about the problem you are having. If this is a new bug, please open a [new issue](https://github.com/TalAter/SpeechKITT/issues/new). 54 | 55 | When you are creating a bug report, please include as many details as possible. 56 | 57 | Explain the problem and include additional details to help maintainers reproduce the problem. 58 | 59 | * Use a clear and descriptive title for the issue to identify the problem. 60 | * Describe the exact steps which reproduce the problem. Share the relevant code to reproduce the issue if possible. 61 | * Try to isolate the issue as much as possible, reducing unrelated code until you get to the minimal amount of code in which the bug still reproduces. This is the most important step to help the community solve the issue. 62 | 63 | ### Feature Requests and Ideas 64 | 65 | We track discussions of new features, proposed changes and other ideas as [GitHub issues](https://github.com/TalAter/SpeechKITT/issues). If you would like to discuss one of those, please first look through existing open and closed [GitHub issues](https://github.com/TalAter/SpeechKITT/issues?q=is%3Aissue) and see if there is already a discussion on this topic which you can join. If there isn't, please open a [new issue](https://github.com/TalAter/SpeechKITT/issues/new). 66 | 67 | When discussing new ideas or proposing changes, please take the time to be as descriptive as possible about the topic at hand. Please take the time to explain the issue you are facing, or the problem you propose to solve in as much detail as possible. 68 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | "use strict"; 3 | 4 | // Project configuration. 5 | grunt.initConfig({ 6 | pkg: grunt.file.readJSON('package.json'), 7 | jshint: { 8 | all: [ 9 | 'src/speechkitt.js', 10 | 'Gruntfile.js', 11 | 'test/corti.js', 12 | 'test/spec/*Spec.js' 13 | ], 14 | options: { 15 | jshintrc: true 16 | } 17 | }, 18 | uglify: { 19 | dist: { 20 | options: { 21 | output: { 22 | comments: /^\! / 23 | } 24 | }, 25 | files: { 26 | 'dist/speechkitt.min.js': ['src/speechkitt.js'] 27 | } 28 | } 29 | }, 30 | watch: { 31 | files: ['src/speechkitt.js', 'test/*.js', 'test/spec/**.js', 'themes/**/*', '!**/node_modules/**'], 32 | tasks: ['default'] 33 | }, 34 | sass: { 35 | dist: { 36 | options: { 37 | style: 'compressed' 38 | }, 39 | files: { 40 | 'dist/themes/flat.css': 'themes/flat/flat.scss', 41 | 'dist/themes/flat-amethyst.css': 'themes/flat-amethyst/flat-amethyst.scss', 42 | 'dist/themes/flat-clouds.css': 'themes/flat-clouds/flat-clouds.scss', 43 | 'dist/themes/flat-concrete.css': 'themes/flat-concrete/flat-concrete.scss', 44 | 'dist/themes/flat-emerald.css': 'themes/flat-emerald/flat-emerald.scss', 45 | 'dist/themes/flat-midnight-blue.css': 'themes/flat-midnight-blue/flat-midnight-blue.scss', 46 | 'dist/themes/flat-orange.css': 'themes/flat-orange/flat-orange.scss', 47 | 'dist/themes/flat-pomegranate.css': 'themes/flat-pomegranate/flat-pomegranate.scss', 48 | 'dist/themes/flat-pumpkin.css': 'themes/flat-pumpkin/flat-pumpkin.scss', 49 | 'dist/themes/flat-turquoise.css': 'themes/flat-turquoise/flat-turquoise.scss', 50 | 'dist/themes/basic.css': 'themes/basic.scss' 51 | } 52 | } 53 | }, 54 | markdox: { 55 | target: { 56 | files: [ 57 | {src: 'src/speechkitt.js', dest: 'docs/README.md'} 58 | ] 59 | } 60 | }, 61 | jasmine: { 62 | testAndCoverage: { 63 | src: ['src/speechkitt.js'], 64 | options: { 65 | specs: ['test/spec/*Spec.js'], 66 | outfile: 'test/SpecRunner.html', 67 | polyfills: ['test/vendor/corti.js', 'test/init_corti.js', 'test/vendor/annyang.min.js', 'test/helper_functions.js'], 68 | vendor: ['test/vendor/jquery-2.1.4.min.js', 'test/vendor/jasmine-jquery.js'], 69 | styles: ['dist/themes/basic.css'], 70 | keepRunner: true, 71 | template: require('grunt-template-jasmine-istanbul'), 72 | templateOptions: { 73 | coverage: 'test/coverage/coverage.json', 74 | report: [ 75 | { 76 | type: 'html', 77 | options: { 78 | dir: 'test/coverage' 79 | } 80 | }, 81 | { 82 | type: 'text' 83 | } 84 | ], 85 | thresholds: { 86 | lines: 50, 87 | statements: 50, 88 | branches: 50, 89 | functions: 50 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }); 96 | 97 | // Load NPM Tasks 98 | grunt.loadNpmTasks('grunt-contrib-uglify'); 99 | grunt.loadNpmTasks('grunt-contrib-jshint'); 100 | grunt.loadNpmTasks('grunt-contrib-jasmine'); 101 | grunt.loadNpmTasks('grunt-contrib-watch'); 102 | grunt.loadNpmTasks('grunt-contrib-sass'); 103 | grunt.loadNpmTasks('grunt-markdox'); 104 | 105 | // Default task(s). 106 | grunt.registerTask('default', ['jshint', 'uglify', 'sass', 'jasmine', 'markdox']); 107 | 108 | // Test task 109 | grunt.registerTask('test', ['jshint', 'jasmine']); 110 | 111 | }; 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tal Ater 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Speech KITT 2 | 3 | 4 | > A flexible GUI for interacting with Speech Recognition 5 | 6 | Speech KITT makes it easy to add a GUI to sites using Speech Recognition. Whether you are using [annyang](https://github.com/TalAter/annyang), a different library or webkitSpeechRecognition directly, KITT will take care of the GUI. 7 | 8 | Speech KITT provides a graphical interface for the user to start or stop Speech Recognition and see its current status. It can also help guide the user on how to interact with your site using their voice, providing instructions and sample commands. It can even be used to carry a natural conversation with the user, asking questions the user can answer with his voice, and then asking follow up questions. 9 | 10 | Speech KITT is fully customizable, and comes with many different themes (and instructions on how to create your own designs). 11 | 12 | [![Speech Recognition GUI with Speech KITT](https://raw.githubusercontent.com/TalAter/SpeechKITT/master/demo/speechkitt-demo.gif)](https://github.com/TalAter/SpeechKITT) 13 | 14 | 15 | ## Hello World 16 | 17 | The most basic implementation requires 6 commands. 18 | 19 | 1. Let KITT know how to start and stop the SpeechRecognition engine you use with `SpeechKITT.setStartCommand()` and `SpeechKITT.setAbortCommand`. 20 | 2. Add events to your SpeechRecognition engine so it calls `SpeechKITT.onStart()` when it starts, and `SpeechKITT.onEnd()` when it stops. 21 | 3. Tell KITT which stylesheet to use for its GUI with `SpeechKITT.setStylesheet()` (KITT comes with a number of pre-made [styles](https://github.com/TalAter/SpeechKITT/tree/master/dist/themes)). 22 | 4. Start your engines with `SpeechKITT.vroom()` 23 | 24 | ````html 25 | 26 | 48 | ```` 49 | 50 | ## Hello World - With annyang 51 | 52 | If you're doing [Speech Recognition with annyang](https://www.talater.com/annyang/), you can skip most of the configuration above. Just calling `SpeechKITT.annyang()` will take care of the configuration explained in steps 1 & 2 above. 53 | 54 | ````html 55 | 56 | 57 | 74 | ```` 75 | 76 | ## API Docs 77 | 78 | For details on all available methods, options and more details, check out the [API documentation](https://github.com/TalAter/SpeechKITT/blob/master/docs/README.md). 79 | 80 | ## Pretty Badges 81 | 82 | [![Build Status](https://travis-ci.org/TalAter/SpeechKITT.svg?branch=master)](https://travis-ci.org/TalAter/SpeechKITT) 83 | 84 | ### Author 85 | 86 | Tal Ater: [@TalAter](https://twitter.com/TalAter) 87 | 88 | ### License 89 | 90 | Licensed under [MIT](https://github.com/TalAter/SpeechKITT/blob/master/LICENSE). 91 | -------------------------------------------------------------------------------- /demo/README-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/README-logo.png -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Speech KITT 5 | 14 | 15 | 16 | 28 | 29 | 30 | 56 | 57 | -------------------------------------------------------------------------------- /demo/index_annyang.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Speech KITT 5 | 14 | 15 | 16 | 28 | 29 | 30 | 31 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /demo/sample_sites/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/sample_sites/1.jpg -------------------------------------------------------------------------------- /demo/sample_sites/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/sample_sites/2.jpg -------------------------------------------------------------------------------- /demo/sample_sites/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/sample_sites/3.jpg -------------------------------------------------------------------------------- /demo/sample_sites/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/sample_sites/4.jpg -------------------------------------------------------------------------------- /demo/speechkitt-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalAter/SpeechKITT/082dc7323074e581c1937dfb042a5511030c0b44/demo/speechkitt-demo.gif -------------------------------------------------------------------------------- /dist/speechkitt.min.js: -------------------------------------------------------------------------------- 1 | //! Speech KITT 2 | //! version : 1.0.0 3 | //! author : Tal Ater @TalAter 4 | //! license : MIT 5 | //! https://github.com/TalAter/SpeechKITT 6 | (function(t){"use strict";var e,n,i,o,s,c,a=this,r=0,l=!1,d="Activate Voice Control",u="What can I help you with?",g=[],m=[],f=!1,h=function(){return c!==t},p=function(){o&&h()&&(s?s.href=o:((s=document.createElement("link")).rel="stylesheet",s.href=o,s.id="skitt-style-sheet",document.body.appendChild(s)))},k=function(){if(h()){var t=document.getElementById("skitt-listening-text__samples");if(g.length){if(!t){var e=document.getElementById("skitt-listening-text__instructions");(t=document.createElement("span")).id="skitt-listening-text__samples",e.parentNode.insertBefore(t,e.nextSibling)}t.innerText=g.join(". ")+".",c.classList.add("skitt-ui--sample-commands-shown")}else t&&t.parentNode.removeChild(t),c.classList.remove("skitt-ui--sample-commands-shown")}},b=function(){if(h()){var t=document.getElementById("skitt-listening-text__recognized-sentence"),e=a.SpeechKITT.getLastRecognizedSentence();if(e&&f){if(!t){var n=document.getElementById("skitt-listening-text__samples")||document.getElementById("skitt-listening-text__instructions");(t=document.createElement("span")).id="skitt-listening-text__recognized-sentence",n.parentNode.insertBefore(t,n.nextSibling)}t.innerText=e,c.classList.add("skitt-ui--recognized-sentence-shown")}else t&&t.parentNode.removeChild(t),c.classList.remove("skitt-ui--recognized-sentence-shown")}},y=function(){h()&&(c.classList.remove("skitt-ui--not-listening"),c.classList.add("skitt-ui--listening"))},T=function(){h()&&(c.classList.add("skitt-ui--not-listening"),c.classList.remove("skitt-ui--listening"))},v=function(){l||(l=!0,y())},x=function(){l&&(l=!1,T())},_=function(t,e){h()&&(document.getElementById(e).innerHTML=t)},S=function(t){Array.isArray(t)&&(t=t[0]),a.SpeechKITT.setRecognizedSentence(t)},w=function(t,e){if("function"!=typeof t)throw new TypeError(e)};a.SpeechKITT={setStartCommand:function(t,e){t=a[t]||t,w(t,"invalid callback function"),n={callback:t,context:e=e||this}},setAbortCommand:function(t,e){t=a[t]||t,w(t,"invalid callback function"),i={callback:t,context:e=e||this}},startRecognition:function(){if(!n)throw new TypeError("cannot start recognition. Start command not defined");var t;r&&((t=new Date).setTime(t.getTime()+6e4*r),document.cookie="skittremember=1; expires="+t.toUTCString()+"; path=/"),n.callback.apply(n.context),v()},abortRecognition:function(){if(!i)throw new TypeError("cannot abort recognition. Abort command not defined");document.cookie="skittremember=1; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",i.callback.apply(i.context),x()},toggleRecognition:function(){l?this.abortRecognition():this.startRecognition()},onStart:function(){a.clearTimeout(e),v()},onEnd:function(){e=setTimeout(x,100)},setStylesheet:function(t){o=t,p()},render:function(){h()||((c=document.createElement("div")).id="skitt-ui",c.innerHTML=' 
'+u+"
",c.style.display="none",document.body.appendChild(c),k(),p(),document.getElementById("skitt-toggle-button").addEventListener("click",function(){a.SpeechKITT.toggleRecognition()})),-1===document.cookie.indexOf("skittremember")||this.isListening()||this.startRecognition(),this.isListening()?y():T()},vroom:function(){this.render()},hide:function(){if(!h())throw new TypeError("cannot hide interface. Must be rendered first");c.classList.add("skitt-ui--hidden")},show:function(){if(!h())throw new TypeError("cannot show interface. Must be rendered first");c.classList.remove("skitt-ui--hidden")},isListening:function(){return l},setToggleLabelText:function(t){d=t,_(t,"skitt-toggle-button__label")},setInstructionsText:function(t){"string"==typeof t&&(u=t,_(t,"skitt-listening-text__instructions"))},setSampleCommands:function(t){Array.isArray(t)||(t=[]),g=t,k()},rememberStatus:function(t){if("number"!=typeof t||t<0)throw new TypeError("rememberStatus() only accepts positive integers");r=t},getLastRecognizedSentence:function(){return 0===m.length?t:m[m.length-1]},setRecognizedSentence:function(t){"string"==typeof t&&(m.push(t),b())},displayRecognizedSentence:function(t){f=!(arguments.length>0)||!!t,b()},annyang:function(){this.setStartCommand(annyang.start),this.setAbortCommand(annyang.abort),annyang.addCallback("start",this.onStart),annyang.addCallback("end",this.onEnd),annyang.addCallback("resultMatch",S),annyang.addCallback("resultNoMatch",S)}}}).call(this); -------------------------------------------------------------------------------- /dist/themes/basic.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important} 2 | /*# sourceMappingURL=basic.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/basic.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe", 4 | "sources": ["../../themes/basic.scss"], 5 | "names": [], 6 | "file": "basic.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-amethyst.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#8E44AD;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#8E44AD}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#8E44AD}50%{background-color:#9B59B6}100%{background-color:#8E44AD}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#9B59B6}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#9B59B6}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-amethyst.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-amethyst.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-amethyst/flat-amethyst.scss"], 5 | "names": [], 6 | "file": "flat-amethyst.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-clouds.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#ECF0F1;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#BDC3C7}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#BDC3C7}50%{background-color:#ECF0F1}100%{background-color:#BDC3C7}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#ECF0F1}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#ECF0F1}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#333}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-clouds.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-clouds.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CC1EY,IAAI,CD6EvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-clouds/flat-clouds.scss"], 5 | "names": [], 6 | "file": "flat-clouds.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-concrete.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#7F8C8D;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#95A5A6}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#95A5A6}50%{background-color:#7F8C8D}100%{background-color:#95A5A6}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#7F8C8D}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#7F8C8D}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-concrete.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-concrete.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-concrete/flat-concrete.scss"], 5 | "names": [], 6 | "file": "flat-concrete.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-emerald.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#27AE60;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#27AE60}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#27AE60}50%{background-color:#2ECC71}100%{background-color:#27AE60}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#2ECC71}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#2ECC71}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-emerald.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-emerald.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-emerald/flat-emerald.scss"], 5 | "names": [], 6 | "file": "flat-emerald.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-midnight-blue.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#2C3E50;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#2C3E50}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#2C3E50}50%{background-color:#34495E}100%{background-color:#2C3E50}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#34495E}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#34495E}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-midnight-blue.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-midnight-blue.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-midnight-blue/flat-midnight-blue.scss"], 5 | "names": [], 6 | "file": "flat-midnight-blue.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-orange.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#F39C12;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#F39C12}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#F39C12}50%{background-color:#F1C40F}100%{background-color:#F39C12}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#F1C40F}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#F1C40F}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-orange.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-orange.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-orange/flat-orange.scss"], 5 | "names": [], 6 | "file": "flat-orange.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-pomegranate.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#C0392B;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#C0392B}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#C0392B}50%{background-color:#E74C3C}100%{background-color:#C0392B}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#E74C3C}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#E74C3C}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-pomegranate.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-pomegranate.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-pomegranate/flat-pomegranate.scss"], 5 | "names": [], 6 | "file": "flat-pomegranate.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-pumpkin.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#D35400;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#D35400}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#D35400}50%{background-color:#E67E22}100%{background-color:#D35400}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#E67E22}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#E67E22}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-pumpkin.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-pumpkin.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-pumpkin/flat-pumpkin.scss"], 5 | "names": [], 6 | "file": "flat-pumpkin.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat-turquoise.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#16A085;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#16A085}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#16A085}50%{background-color:#1ABC9C}100%{background-color:#16A085}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#1ABC9C}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#1ABC9C}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat-turquoise.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat-turquoise.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CCZE,OAAO,CDazB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CC/CH,OAAO,CDkDtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CCxDL,OAAO,CD0DpB,GAAI,CACF,gBAAgB,CC1DL,OAAO,CD4DpB,IAAK,CACH,gBAAgB,CC9DL,OAAO,EDkEtB,mDAAoD,CAClD,gBAAgB,CClEH,OAAO,CDoEtB,+CAAgD,CAC9C,gBAAgB,CCrEH,OAAO,CDwEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss","../../themes/flat-turquoise/flat-turquoise.scss"], 5 | "names": [], 6 | "file": "flat-turquoise.css" 7 | } 8 | -------------------------------------------------------------------------------- /dist/themes/flat.css: -------------------------------------------------------------------------------- 1 | #skitt-ui{display:block !important}#skitt-ui.skitt-ui--hidden{display:none !important}#skitt-ui{height:50px;display:inline-block;background-color:#2980B9;z-index:200;border-radius:25px;position:fixed;bottom:20px;left:20px;outline:none;border:none;box-shadow:rgba(0,0,0,0.2) 0px 4px 8px;cursor:default;font-family:Lato,Helvetica,Arial,sans-serif;font-size:16px}#skitt-toggle-button{width:50px;height:50px;border-radius:50%;cursor:pointer;display:inline-block;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+");background-size:72% 72%;background-position:7px 6px;background-repeat:no-repeat;-webkit-transition:background-color 400ms ease;float:left}label#skitt-toggle-button__label{display:none}.skitt-ui--not-listening #skitt-toggle-button{background-color:#2980B9}.skitt-ui--listening #skitt-toggle-button{-webkit-animation:listen_pulse 2s ease-out infinite}@-webkit-keyframes "listen_pulse"{0%{background-color:#2980B9}50%{background-color:#3498DB}100%{background-color:#2980B9}}.skitt-ui--not-listening #skitt-toggle-button:hover{background-color:#3498DB}.skitt-ui--listening #skitt-toggle-button:hover{background-color:#3498DB}#skitt-listening-box{float:left;display:inline-block;line-height:50px;color:#fff}#skitt-listening-text{display:inline-block;overflow:hidden}.skitt-ui--not-listening #skitt-listening-text{width:0}.skitt-ui--listening #skitt-listening-text{width:100%;-webkit-transition:width 1s ease-in-out;margin:0 25px 0 15px}#skitt-listening-text__samples{font-weight:bold;margin-left:10px}#skitt-listening-text__recognized-sentence{display:none}@media (max-width: 1200px) and (orientation: portrait){#skitt-ui{border-radius:62.5px;font-size:35px;height:125px}#skitt-toggle-button{width:125px;height:125px;background-position:17.5px 15px}#skitt-listening-box{line-height:125px}}@media (max-width: 1200px) and (orientation: landscape){#skitt-ui{border-radius:40px;font-size:25px;height:80px}#skitt-toggle-button{width:80px;height:80px;background-position:11.2px 9.6px}#skitt-listening-box{line-height:80px}} 2 | /*# sourceMappingURL=flat.css.map */ 3 | -------------------------------------------------------------------------------- /dist/themes/flat.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,SAAU,CACR,OAAO,CAAE,gBAAe,CAE1B,0BAA2B,CACzB,OAAO,CAAE,eAAe,CCS1B,SAAU,CACR,MAAM,CATa,IAAI,CAUvB,OAAO,CAAE,YAAY,CACrB,gBAAgB,CARE,OAAO,CASzB,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAsB,CACrC,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,2BAA8B,CAC1C,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,+BAA+B,CAC5C,SAAS,CAAE,IAAI,CAGjB,oBAAqB,CACnB,KAAK,CA3Ba,IAAI,CA4BtB,MAAM,CA3Ba,IAAI,CA4BvB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,6gCAA6gC,CACzhC,eAAe,CAAE,OAAO,CACxB,mBAAmB,CAAE,OAAoD,CACzE,iBAAiB,CAAE,SAAS,CAC5B,kBAAkB,CAAE,2BAA2B,CAC/C,KAAK,CAAE,IAAI,CAGb,gCAAiC,CAC/B,OAAO,CAAE,IAAI,CAGf,6CAA8C,CAC5C,gBAAgB,CA3CH,OAAO,CA8CtB,yCAA0C,CACxC,iBAAiB,CAAE,iCAAiC,CAGtD,iCAUC,CATC,EAAG,CACD,gBAAgB,CApDL,OAAO,CAsDpB,GAAI,CACF,gBAAgB,CAtDL,OAAO,CAwDpB,IAAK,CACH,gBAAgB,CA1DL,OAAO,EA8DtB,mDAAoD,CAClD,gBAAgB,CA9DH,OAAO,CAgEtB,+CAAgD,CAC9C,gBAAgB,CAjEH,OAAO,CAoEtB,oBAAqB,CACnB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACrB,WAAW,CAzEQ,IAAI,CA0EvB,KAAK,CAtEY,IAAI,CAyEvB,qBAAsB,CACpB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAElB,8CAA+C,CAC7C,KAAK,CAAE,CAAC,CAEV,0CAA2C,CACzC,KAAK,CAAE,IAAI,CACX,kBAAkB,CAAE,oBAAoB,CACxC,MAAM,CAAE,aAA6B,CAGvC,8BAA+B,CAC7B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,IAAI,CAGnB,0CAA2C,CACzC,OAAO,CAAE,IAAI,CAEf,sDAAwD,CAEtD,SAAU,CACR,aAAa,CAAE,MAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,KAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,KAAqC,CAC5C,MAAM,CAAE,KAAsC,CAC9C,mBAAmB,CAAE,WAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,KAAsC,EAIvD,uDAAyD,CAEvD,SAAU,CACR,aAAa,CAAE,IAAyC,CACxD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAsC,CAEhD,oBAAqB,CACnB,KAAK,CAAE,IAAqC,CAC5C,MAAM,CAAE,IAAsC,CAC9C,mBAAmB,CAAE,YAA0F,CAEjH,oBAAqB,CACnB,WAAW,CAAE,IAAsC", 4 | "sources": ["../../themes/basic.scss","../../themes/flat/flat.scss"], 5 | "names": [], 6 | "file": "flat.css" 7 | } 8 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # Getting Started 6 | 7 | The quickest way to get started is described in the project's [README](https://github.com/TalAter/SpeechKITT/blob/master/README.md). 8 | 9 | Additional details and methods to interact with KITT are described below. 10 | 11 | # API Reference 12 | 13 | ## setStartCommand(callback, [context]) 14 | 15 | Define the function that should be called in order to start speech recognition. 16 | 17 | #### Examples: 18 | ````javascript 19 | // Will call annyang's start method 20 | SpeechKITT.setStartCommand(annyang.start); 21 | // Will call a global function called listen with a local context. 22 | SpeechKITT.setStartCommand(listen, this); 23 | // Functions can also be stated by name (string) 24 | SpeechKITT.setStartCommand('listen', this); 25 | // Using the browser's native start function 26 | SpeechKITT.setStartCommand(webkitSpeechRecognition.start); 27 | ```` 28 | 29 | ### Params: 30 | 31 | * **Function|String** *callback* - The function to call to start speech recognition 32 | * **Object** *[context]* - Optional context for the callback function 33 | 34 | ## setAbortCommand(callback, [context]) 35 | 36 | Define the function that should be called in order to abort (stop) speech recognition. 37 | 38 | #### Examples: 39 | ````javascript 40 | // Will call annyang's abort method 41 | SpeechKITT.setAbortCommand(annyang.abort); 42 | // Using the browser's native abort function 43 | SpeechKITT.setAbortCommand(webkitSpeechRecognition.abort); 44 | ```` 45 | 46 | ### Params: 47 | 48 | * **Function|String** *callback* - The function to call to abort speech recognition 49 | * **Object** *[context]* - Optional context for the callback function 50 | 51 | ## startRecognition() 52 | 53 | Starts the speech recognition. This is equivalent to the user pushing KITT's buttons. 54 | 55 | Make sure to define the speech recognition start command first using setStartCommand() 56 | 57 | ## abortRecognition() 58 | 59 | Aborts the speech recognition. This is equivalent to the user pushing KITT's buttons. 60 | 61 | Make sure to define the speech recognition abort command first using setAbortCommand() 62 | 63 | ## toggleRecognition() 64 | 65 | Toggles speech recognition. This is equivalent to the user pushing KITT's buttons. 66 | 67 | Make sure to define the speech recognition abort and start commands first 68 | 69 | ## onStart() 70 | 71 | This function should be called when the browser's SpeechRecognition start event fires. 72 | 73 | Attach this function to the Speech Recognition instance's start event. 74 | 75 | #### Examples: 76 | ````javascript 77 | var recognition = new webkitSpeechRecognition(); 78 | recognition.addEventListener('start', SpeechKITT.onStart); 79 | ```` 80 | 81 | ## onEnd() 82 | 83 | This function should be called when the browser's SpeechRecognition end event fires. 84 | 85 | Attach this function to the Speech Recognition instance's end event. 86 | 87 | *Note: KITT's interface will only change to 'stopped' 100ms after this method is called.* 88 | *If Speech Recognition restarts before 100ms have passed, the interface will just remain* 89 | *in 'started' mode (this is to prevent the interface from flickering when Speech* 90 | *Recognition is stopped and immediately restarted programmatically)* 91 | 92 | #### Examples: 93 | ````javascript 94 | var recognition = new webkitSpeechRecognition(); 95 | recognition.addEventListener('end', SpeechKITT.onEnd); 96 | ```` 97 | 98 | ## setStylesheet(string) 99 | 100 | Set the URL for the stylesheet for the UI 101 | 102 | If a stylesheet was previously set, calling this again will update the 103 | interface with a new stylesheet (if the interface was already rendered, 104 | it will be updated) 105 | 106 | ### Params: 107 | 108 | * *string* css relative or absolute url to the stylesheet 109 | 110 | ## render() 111 | 112 | Call after configuring KITT, to render its interface. 113 | 114 | ## vroom() 115 | 116 | Call after configuring KITT, to render its interface. 117 | 118 | Identical to calling SpeechKITT.render(); 119 | 120 | See: [render()](#render) 121 | 122 | ## hide() 123 | 124 | Call to hide the GUI. 125 | 126 | Interface must have been previously rendered with render() 127 | 128 | ## show() 129 | 130 | Call to show the GUI if it has been hidden with hide() 131 | 132 | Interface must have been previously rendered with render() 133 | 134 | ## isListening() 135 | 136 | Returns true if Speech Recognition is currently on. 137 | 138 | This can be wrong if KITT wasn't completely configured correctly, or was 139 | started while Speech Recognition was already running. 140 | 141 | ### Return: 142 | 143 | * **boolean** true = listening or false = not listening 144 | 145 | ## setToggleLabelText(string) 146 | 147 | Set the text for the toggle button's label. 148 | 149 | Defaults to: 'Activate Voice Control' 150 | 151 | ### Params: 152 | 153 | * *string* text The text to show next to toggle button 154 | 155 | ## setInstructionsText(string) 156 | 157 | Set the instructional text which will be shown next to toggle button when listening. 158 | 159 | Accepts simple text or HTML. 160 | 161 | Defaults to: 'What can I help you with?' 162 | 163 | ### Params: 164 | 165 | * *string* text The text to show next to toggle button when listening 166 | 167 | ## setSampleCommands(array) 168 | 169 | Pass this an array of sample textual commands which your application responds to. 170 | 171 | These will then be shown to the user to help him understand what commands he can use. 172 | 173 | ### Params: 174 | 175 | * *array* commands An array of strings, each a sample command. 176 | 177 | ## rememberStatus(minutes) 178 | 179 | Set this and KITT will remember when the user clicks the button to turn on Speech Recognition, and next time 180 | they visit the site, Speech Recognition will be turned on again (unless user turned it off, or a certain number 181 | of minutes has passed since it was last on). 182 | 183 | Disabled by default. Enable by passing an integer which is the number of minutes to remember. 184 | To disable manually after you enabled, pass 0 to it. 185 | 186 | Example: 187 | ````javascript 188 | SpeechKITT.rememberStatus(120); // Automatically start Speech Recognition for any consecutive 189 | // visit to this page in the next 120 minutes, or until the user 190 | // has clicked the button to stop listening. 191 | ```` 192 | 193 | ### Params: 194 | 195 | * *minutes* integer Number of minutes to remember choice to turn on Speech Recognition 196 | 197 | ## getLastRecognizedSentence() 198 | 199 | Returns the last sentenced recognized by speech recognition. 200 | 201 | *Note: You need to set sentences as they are recognized with setRecognizedSentence().* 202 | *If you are using annyang, this happens automatically.* 203 | 204 | See: [setRecognizedSentence()](#setrecognizedsentencesentence) 205 | 206 | ### Return: 207 | 208 | * undefined|string 209 | 210 | ## setRecognizedSentence(sentence) 211 | 212 | Add a sentence that was recognized. 213 | You will usually want to call this from the SpeechRecognition's result event. 214 | 215 | Example: 216 | ````javascript 217 | var recognition = new webkitSpeechRecognition(); 218 | recognition.addEventListener('result', function(ev) { 219 | SpeechKITT.setRecognizedSentence( 220 | ev.results[ev.resultIndex][0].transcript // This is where the browser hides the text the user said 221 | ); 222 | }); 223 | ```` 224 | 225 | *Note: If you're using annyang, this gets called automatically for you.* 226 | 227 | See: [annyang()](#annyang) 228 | 229 | ### Params: 230 | 231 | * *sentence* string 232 | 233 | ## displayRecognizedSentence([newState=true]) 234 | 235 | Speech KITT can display the last sentence the user said in the GUI. 236 | Set this to true to display the last sentence. Set it to false to remove it from the DOM. 237 | 238 | For more details on how to track the sentences said, see the documentation for setRecognizedSentence() 239 | 240 | See: [setRecognizedSentence()](#setrecognizedsentencesentence) 241 | 242 | ### Params: 243 | 244 | * **boolean** *[newState=true]* - Turn on/off display of recognized sentences 245 | 246 | ## annyang() 247 | 248 | Call this if you're using annyang to automatically configure Speech KITT to interact with it. 249 | 250 | Automatically does the following: 251 | - Set Speech KITT's start command to annyang.start 252 | - Set Speech KITT's abort command to annyang.abort 253 | - Adds a callback to annyang's start event to call SpeechKITT.onStart 254 | - Adds a callback to annyang's end event to call SpeechKITT.onEnd 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "speechkitt", 3 | "version": "1.0.0", 4 | "description": "A flexible GUI for interacting with Speech Recognition", 5 | "keywords": [ 6 | "controls", 7 | "gui", 8 | "interface", 9 | "recognition", 10 | "speech", 11 | "speechrecognition", 12 | "ui", 13 | "voice", 14 | "webkitspeechrecognition" 15 | ], 16 | "homepage": "https://github.com/TalAter/SpeechKITT", 17 | "bugs": { 18 | "url": "https://github.com/TalAter/SpeechKITT/issues" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/TalAter/SpeechKITT.git" 23 | }, 24 | "license": "MIT", 25 | "author": "Tal Ater (https://www.talater.com/)", 26 | "main": "speechkitt.js", 27 | "scripts": { 28 | "test": "grunt test" 29 | }, 30 | "devDependencies": { 31 | "async": "^2.6.2", 32 | "grunt": "^1.0.4", 33 | "grunt-cli": "^1.3.2", 34 | "grunt-contrib-jasmine": "^1.2.0", 35 | "grunt-contrib-jshint": "^2.1.0", 36 | "grunt-contrib-sass": "^1.0.0", 37 | "grunt-contrib-uglify": "^4.0.1", 38 | "grunt-contrib-watch": "^1.1.0", 39 | "grunt-markdox": "^1.2.1", 40 | "grunt-template-jasmine-istanbul": "^0.5.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/speechkitt.js: -------------------------------------------------------------------------------- 1 | //! Speech KITT 2 | //! version : 1.0.0 3 | //! author : Tal Ater @TalAter 4 | //! license : MIT 5 | //! https://github.com/TalAter/SpeechKITT 6 | 7 | /** 8 | * # Getting Started 9 | * 10 | * The quickest way to get started is described in the project's [README](https://github.com/TalAter/SpeechKITT/blob/master/README.md). 11 | * 12 | * Additional details and methods to interact with KITT are described below. 13 | * 14 | * # API Reference 15 | */ 16 | 17 | (function (undefined) { 18 | 'use strict'; 19 | 20 | // Save a reference to the global object (window in the browser) 21 | var _root = this; 22 | 23 | // Internal variable pointing to the timeout used to make sure KITT isn't stopped and immediately started (See `onEnd()`) 24 | var _listeningStoppedTimeout; 25 | 26 | // Set by SpeechKITT.rememberStatus() - Number of minutes after KITT has been activated by user to remember his choice 27 | var _minutesToRememberStatus = 0; 28 | 29 | // Reference to functions used to start and abort speech recognition 30 | var _startCommand; 31 | var _abortCommand; 32 | 33 | // Is speech recognition currently on? 34 | var _statusListening = false; 35 | 36 | // URL to the stylesheet to use 37 | var _stylesheet; 38 | var _stylesheetNode; 39 | 40 | // Texts used in UI 41 | var _toggleLabelText = 'Activate Voice Control'; 42 | var _listeningInstructionsText = 'What can I help you with?'; 43 | var _sampleCommands = []; 44 | 45 | // A list of sentences recognized 46 | var _recognizedSentences = []; 47 | 48 | // Should sentences recognized be rendered to DOM? 49 | var _displayRecognizedSentence = false; 50 | 51 | // DOM elements 52 | var _guiNodes; 53 | 54 | // Checks if GUI was already created 55 | var _guiCreated = function () { 56 | return _guiNodes !== undefined; 57 | }; 58 | 59 | // Attach a style sheet if GUI already attached, if already attached, update it's href 60 | var _updateStylesheet = function() { 61 | if (_stylesheet && _guiCreated()) { 62 | if (_stylesheetNode) { 63 | _stylesheetNode.href = _stylesheet; 64 | } else { 65 | _stylesheetNode = document.createElement('link'); 66 | _stylesheetNode.rel = 'stylesheet'; 67 | _stylesheetNode.href = _stylesheet; 68 | _stylesheetNode.id = 'skitt-style-sheet'; 69 | document.body.appendChild(_stylesheetNode); 70 | } 71 | } 72 | }; 73 | 74 | // Update texts shown while listening 75 | var _updateListeningText = function() { 76 | if (!_guiCreated()) { 77 | return; 78 | } 79 | var samplesNode = document.getElementById('skitt-listening-text__samples'); 80 | if (_sampleCommands.length) { 81 | if (!samplesNode) { 82 | var nodeToInsertAfter = document.getElementById('skitt-listening-text__instructions'); 83 | samplesNode = document.createElement('span'); 84 | samplesNode.id = 'skitt-listening-text__samples'; 85 | nodeToInsertAfter.parentNode.insertBefore(samplesNode, nodeToInsertAfter.nextSibling); 86 | } 87 | samplesNode.innerText = _sampleCommands.join('. ')+'.'; 88 | _guiNodes.classList.add('skitt-ui--sample-commands-shown'); 89 | } else { 90 | if (samplesNode) { 91 | samplesNode.parentNode.removeChild(samplesNode); 92 | } 93 | _guiNodes.classList.remove('skitt-ui--sample-commands-shown'); 94 | } 95 | }; 96 | 97 | var _updateRecognizedSentenceText = function() { 98 | if (!_guiCreated()) { 99 | return; 100 | } 101 | var recognizedSentenceNode = document.getElementById('skitt-listening-text__recognized-sentence'); 102 | var lastRecognizedSentenceText = _root.SpeechKITT.getLastRecognizedSentence(); 103 | if (lastRecognizedSentenceText && _displayRecognizedSentence) { 104 | if (!recognizedSentenceNode) { 105 | var nodeToInsertAfter = document.getElementById('skitt-listening-text__samples') || document.getElementById('skitt-listening-text__instructions'); 106 | recognizedSentenceNode = document.createElement('span'); 107 | recognizedSentenceNode.id = 'skitt-listening-text__recognized-sentence'; 108 | nodeToInsertAfter.parentNode.insertBefore(recognizedSentenceNode, nodeToInsertAfter.nextSibling); 109 | } 110 | recognizedSentenceNode.innerText = lastRecognizedSentenceText; 111 | _guiNodes.classList.add('skitt-ui--recognized-sentence-shown'); 112 | } else { 113 | if (recognizedSentenceNode) { 114 | recognizedSentenceNode.parentNode.removeChild(recognizedSentenceNode); 115 | } 116 | _guiNodes.classList.remove('skitt-ui--recognized-sentence-shown'); 117 | } 118 | }; 119 | 120 | // Called once to generate the GUI nodes 121 | var _createGUI = function() { 122 | // create GUI 123 | _guiNodes = document.createElement('div'); 124 | _guiNodes.id = 'skitt-ui'; 125 | _guiNodes.innerHTML = ' 
'+_listeningInstructionsText+'
'; 126 | _guiNodes.style.display = 'none'; 127 | document.body.appendChild(_guiNodes); 128 | 129 | _updateListeningText(); 130 | 131 | _updateStylesheet(); 132 | 133 | // Attach events 134 | document.getElementById('skitt-toggle-button').addEventListener('click', function(){ 135 | _root.SpeechKITT.toggleRecognition(); 136 | }); 137 | }; 138 | 139 | // Called to change GUI look to listening 140 | var _setGUIListening = function() { 141 | if (!_guiCreated()) { 142 | return; 143 | } 144 | _guiNodes.classList.remove('skitt-ui--not-listening'); 145 | _guiNodes.classList.add('skitt-ui--listening'); 146 | }; 147 | 148 | // Called to change GUI look to not listening 149 | var _setGUINotListening = function() { 150 | if (!_guiCreated()) { 151 | return; 152 | } 153 | _guiNodes.classList.add('skitt-ui--not-listening'); 154 | _guiNodes.classList.remove('skitt-ui--listening'); 155 | }; 156 | 157 | // Called internally to set listening status to on, and update interface if needed 158 | var _setStatusOn = function() { 159 | if (!_statusListening) { 160 | _statusListening = true; 161 | _setGUIListening(); 162 | } 163 | }; 164 | 165 | // Called internally to set listening status to off, and update interface if needed 166 | var _setStatusOff = function() { 167 | if (_statusListening) { 168 | _statusListening = false; 169 | _setGUINotListening(); 170 | } 171 | }; 172 | 173 | // Helper function used by various public methods which change texts 174 | var _setText = function(text, id) { 175 | if (_guiCreated()) { 176 | document.getElementById(id).innerHTML = text; 177 | } 178 | }; 179 | 180 | var _annyangSetRecognizedSentence = function(sentences) { 181 | if (Array.isArray(sentences)) { 182 | sentences = sentences[0]; 183 | } 184 | _root.SpeechKITT.setRecognizedSentence(sentences); 185 | }; 186 | 187 | // Saves a cookie called skittremember which signifies that the user has chosen to turn on Speech Recognition 188 | var _saveListeningStatusCookie = function() { 189 | var dtExpiration = new Date(); 190 | dtExpiration.setTime(dtExpiration.getTime() + 60000 * _minutesToRememberStatus); 191 | document.cookie='skittremember=1; expires='+dtExpiration.toUTCString()+'; path=/'; 192 | }; 193 | 194 | // Deletes the skittremember cookie because the user has chosen to stop Speech Recognition 195 | var _deleteListeningStatusCookie = function() { 196 | document.cookie='skittremember=1; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; 197 | }; 198 | 199 | // Checks for existence of the skittremember cookie which signifies that Speech Recognition should be turned on 200 | var _listeningStatusCookieExists = function() { 201 | return document.cookie.indexOf('skittremember') !== -1; 202 | }; 203 | 204 | var _ifNotFunctionThrowError = function(func, errorText) { 205 | if (typeof func !== 'function') { 206 | throw new TypeError(errorText); 207 | } 208 | }; 209 | 210 | // Expose functionality 211 | _root.SpeechKITT = { 212 | 213 | /** 214 | * Define the function that should be called in order to start speech recognition. 215 | * 216 | * #### Examples: 217 | * ````javascript 218 | * // Will call annyang's start method 219 | * SpeechKITT.setStartCommand(annyang.start); 220 | * // Will call a global function called listen with a local context. 221 | * SpeechKITT.setStartCommand(listen, this); 222 | * // Functions can also be stated by name (string) 223 | * SpeechKITT.setStartCommand('listen', this); 224 | * // Using the browser's native start function 225 | * SpeechKITT.setStartCommand(webkitSpeechRecognition.start); 226 | * ```` 227 | * 228 | * @param {Function|String} callback - The function to call to start speech recognition 229 | * @param {Object} [context] - Optional context for the callback function 230 | * @method setStartCommand 231 | */ 232 | setStartCommand: function(callback, context) { 233 | // This should work both when passed a function, or a name of a function 234 | callback = _root[callback] || callback; 235 | _ifNotFunctionThrowError(callback, 'invalid callback function'); 236 | context = context || this; 237 | 238 | _startCommand = {callback: callback, context: context}; 239 | }, 240 | 241 | /** 242 | * Define the function that should be called in order to abort (stop) speech recognition. 243 | * 244 | * #### Examples: 245 | * ````javascript 246 | * // Will call annyang's abort method 247 | * SpeechKITT.setAbortCommand(annyang.abort); 248 | * // Using the browser's native abort function 249 | * SpeechKITT.setAbortCommand(webkitSpeechRecognition.abort); 250 | * ```` 251 | * 252 | * @param {Function|String} callback - The function to call to abort speech recognition 253 | * @param {Object} [context] - Optional context for the callback function 254 | * @method setAbortCommand 255 | */ 256 | setAbortCommand: function(callback, context) { 257 | // This should work both when passed a function, or a name of a function 258 | callback = _root[callback] || callback; 259 | _ifNotFunctionThrowError(callback, 'invalid callback function'); 260 | context = context || this; 261 | 262 | _abortCommand = {callback: callback, context: context}; 263 | }, 264 | 265 | /** 266 | * Starts the speech recognition. This is equivalent to the user pushing KITT's buttons. 267 | * 268 | * Make sure to define the speech recognition start command first using setStartCommand() 269 | * 270 | * @method startRecognition 271 | */ 272 | startRecognition: function() { 273 | if (!_startCommand) { 274 | throw new TypeError('cannot start recognition. Start command not defined'); 275 | } 276 | // If need to remember status, save a cookie now 277 | if (_minutesToRememberStatus) { 278 | _saveListeningStatusCookie(); 279 | } 280 | _startCommand.callback.apply(_startCommand.context); 281 | _setStatusOn(); 282 | }, 283 | 284 | /** 285 | * Aborts the speech recognition. This is equivalent to the user pushing KITT's buttons. 286 | * 287 | * Make sure to define the speech recognition abort command first using setAbortCommand() 288 | * 289 | * @method abortRecognition 290 | */ 291 | abortRecognition: function() { 292 | if (!_abortCommand) { 293 | throw new TypeError('cannot abort recognition. Abort command not defined'); 294 | } 295 | // Clear status cookie 296 | _deleteListeningStatusCookie(); 297 | _abortCommand.callback.apply(_abortCommand.context); 298 | _setStatusOff(); 299 | }, 300 | 301 | /** 302 | * Toggles speech recognition. This is equivalent to the user pushing KITT's buttons. 303 | * 304 | * Make sure to define the speech recognition abort and start commands first 305 | * 306 | * @method toggleRecognition 307 | */ 308 | toggleRecognition: function() { 309 | if (_statusListening) { 310 | this.abortRecognition(); 311 | } else { 312 | this.startRecognition(); 313 | } 314 | }, 315 | 316 | /** 317 | * This function should be called when the browser's SpeechRecognition start event fires. 318 | * 319 | * Attach this function to the Speech Recognition instance's start event. 320 | * 321 | * #### Examples: 322 | * ````javascript 323 | * var recognition = new webkitSpeechRecognition(); 324 | * recognition.addEventListener('start', SpeechKITT.onStart); 325 | * ```` 326 | * 327 | * @method onStart 328 | */ 329 | onStart: function() { 330 | _root.clearTimeout(_listeningStoppedTimeout); 331 | _setStatusOn(); 332 | }, 333 | 334 | /** 335 | * This function should be called when the browser's SpeechRecognition end event fires. 336 | * 337 | * Attach this function to the Speech Recognition instance's end event. 338 | * 339 | * *Note: KITT's interface will only change to 'stopped' 100ms after this method is called.* 340 | * *If Speech Recognition restarts before 100ms have passed, the interface will just remain* 341 | * *in 'started' mode (this is to prevent the interface from flickering when Speech* 342 | * *Recognition is stopped and immediately restarted programmatically)* 343 | * 344 | * #### Examples: 345 | * ````javascript 346 | * var recognition = new webkitSpeechRecognition(); 347 | * recognition.addEventListener('end', SpeechKITT.onEnd); 348 | * ```` 349 | * 350 | * @method onEnd 351 | */ 352 | onEnd: function() { 353 | _listeningStoppedTimeout = setTimeout(_setStatusOff, 100); 354 | }, 355 | 356 | /** 357 | * Set the URL for the stylesheet for the UI 358 | * 359 | * If a stylesheet was previously set, calling this again will update the 360 | * interface with a new stylesheet (if the interface was already rendered, 361 | * it will be updated) 362 | * 363 | * @param string css relative or absolute url to the stylesheet 364 | * @method setStylesheet 365 | */ 366 | setStylesheet: function(css) { 367 | _stylesheet = css; 368 | _updateStylesheet(); 369 | }, 370 | 371 | /** 372 | * Call after configuring KITT, to render its interface. 373 | * 374 | * @method render 375 | */ 376 | render: function() { 377 | if (!_guiCreated()) { 378 | _createGUI(); 379 | } 380 | // If cookie for on status exists, start listening immediately 381 | if (_listeningStatusCookieExists() && !this.isListening()) { 382 | this.startRecognition(); 383 | } 384 | //set GUI status 385 | if (this.isListening()) { 386 | _setGUIListening(); 387 | } else { 388 | _setGUINotListening(); 389 | } 390 | }, 391 | 392 | /** 393 | * Call after configuring KITT, to render its interface. 394 | * 395 | * Identical to calling SpeechKITT.render(); 396 | * 397 | * @method vroom 398 | * @see [render()](#render) 399 | */ 400 | vroom: function() { 401 | this.render(); 402 | }, 403 | 404 | /** 405 | * Call to hide the GUI. 406 | * 407 | * Interface must have been previously rendered with render() 408 | * 409 | * @method hide 410 | */ 411 | hide: function() { 412 | if (!_guiCreated()) { 413 | throw new TypeError('cannot hide interface. Must be rendered first'); 414 | } 415 | _guiNodes.classList.add('skitt-ui--hidden'); 416 | }, 417 | 418 | /** 419 | * Call to show the GUI if it has been hidden with hide() 420 | * 421 | * Interface must have been previously rendered with render() 422 | * 423 | * @method show 424 | */ 425 | show: function() { 426 | if (!_guiCreated()) { 427 | throw new TypeError('cannot show interface. Must be rendered first'); 428 | } 429 | _guiNodes.classList.remove('skitt-ui--hidden'); 430 | }, 431 | 432 | /** 433 | * Returns true if Speech Recognition is currently on. 434 | * 435 | * This can be wrong if KITT wasn't completely configured correctly, or was 436 | * started while Speech Recognition was already running. 437 | * 438 | * @returns {boolean} true = listening or false = not listening 439 | * @method isListening 440 | */ 441 | isListening: function() { 442 | return _statusListening; 443 | }, 444 | 445 | /** 446 | * Set the text for the toggle button's label. 447 | * 448 | * Defaults to: 'Activate Voice Control' 449 | * 450 | * @param string text The text to show next to toggle button 451 | * @method setToggleLabelText 452 | */ 453 | setToggleLabelText: function(text) { 454 | _toggleLabelText = text; 455 | _setText(text, 'skitt-toggle-button__label'); 456 | }, 457 | 458 | /** 459 | * Set the instructional text which will be shown next to toggle button when listening. 460 | * 461 | * Accepts simple text or HTML. 462 | * 463 | * Defaults to: 'What can I help you with?' 464 | * 465 | * @param string text The text to show next to toggle button when listening 466 | * @method setInstructionsText 467 | */ 468 | setInstructionsText: function(text) { 469 | if (typeof text === 'string') { 470 | _listeningInstructionsText = text; 471 | _setText(text, 'skitt-listening-text__instructions'); 472 | } 473 | }, 474 | 475 | /** 476 | * Pass this an array of sample textual commands which your application responds to. 477 | * 478 | * These will then be shown to the user to help him understand what commands he can use. 479 | * 480 | * @param array commands An array of strings, each a sample command. 481 | * @method setSampleCommands 482 | */ 483 | setSampleCommands: function(commands) { 484 | if (!Array.isArray(commands)) { 485 | commands = []; 486 | } 487 | _sampleCommands = commands; 488 | _updateListeningText(); 489 | }, 490 | 491 | /** 492 | * Set this and KITT will remember when the user clicks the button to turn on Speech Recognition, and next time 493 | * they visit the site, Speech Recognition will be turned on again (unless user turned it off, or a certain number 494 | * of minutes has passed since it was last on). 495 | * 496 | * Disabled by default. Enable by passing an integer which is the number of minutes to remember. 497 | * To disable manually after you enabled, pass 0 to it. 498 | * 499 | * Example: 500 | * ````javascript 501 | * SpeechKITT.rememberStatus(120); // Automatically start Speech Recognition for any consecutive 502 | * // visit to this page in the next 120 minutes, or until the user 503 | * // has clicked the button to stop listening. 504 | * ```` 505 | * 506 | * @param minutes integer Number of minutes to remember choice to turn on Speech Recognition 507 | */ 508 | rememberStatus: function(minutes) { 509 | if (typeof minutes !== 'number' || minutes < 0) { 510 | throw new TypeError('rememberStatus() only accepts positive integers'); 511 | } 512 | _minutesToRememberStatus = minutes; 513 | }, 514 | 515 | /** 516 | * Returns the last sentenced recognized by speech recognition. 517 | * 518 | * *Note: You need to set sentences as they are recognized with setRecognizedSentence().* 519 | * *If you are using annyang, this happens automatically.* 520 | * 521 | * @returns undefined|string 522 | * @see [setRecognizedSentence()](#setrecognizedsentencesentence) 523 | */ 524 | getLastRecognizedSentence: function() { 525 | if (_recognizedSentences.length === 0) { 526 | return undefined; 527 | } else { 528 | return _recognizedSentences[_recognizedSentences.length-1]; 529 | } 530 | }, 531 | 532 | /** 533 | * Add a sentence that was recognized. 534 | * You will usually want to call this from the SpeechRecognition's result event. 535 | * 536 | * Example: 537 | * ````javascript 538 | * var recognition = new webkitSpeechRecognition(); 539 | * recognition.addEventListener('result', function(ev) { 540 | * SpeechKITT.setRecognizedSentence( 541 | * ev.results[ev.resultIndex][0].transcript // This is where the browser hides the text the user said 542 | * ); 543 | * }); 544 | * ```` 545 | * 546 | * *Note: If you're using annyang, this gets called automatically for you.* 547 | * 548 | * @param sentence string 549 | * @method setRecognizedSentence 550 | * @see [annyang()](#annyang) 551 | */ 552 | setRecognizedSentence : function(sentence) { 553 | if (typeof sentence === 'string') { 554 | _recognizedSentences.push(sentence); 555 | _updateRecognizedSentenceText(); 556 | } 557 | }, 558 | 559 | /** 560 | * Speech KITT can display the last sentence the user said in the GUI. 561 | * Set this to true to display the last sentence. Set it to false to remove it from the DOM. 562 | * 563 | * For more details on how to track the sentences said, see the documentation for setRecognizedSentence() 564 | * 565 | * @param {boolean} [newState=true] - Turn on/off display of recognized sentences 566 | * @method displayRecognizedSentence 567 | * @see [setRecognizedSentence()](#setrecognizedsentencesentence) 568 | */ 569 | displayRecognizedSentence: function(newState) { 570 | if (arguments.length > 0) { 571 | _displayRecognizedSentence = !!newState; 572 | } else { 573 | _displayRecognizedSentence = true; 574 | } 575 | _updateRecognizedSentenceText(); 576 | }, 577 | 578 | /** 579 | * Call this if you're using annyang to automatically configure Speech KITT to interact with it. 580 | * 581 | * Automatically does the following: 582 | * - Set Speech KITT's start command to annyang.start 583 | * - Set Speech KITT's abort command to annyang.abort 584 | * - Adds a callback to annyang's start event to call SpeechKITT.onStart 585 | * - Adds a callback to annyang's end event to call SpeechKITT.onEnd 586 | * 587 | * @method annyang 588 | */ 589 | annyang: function() { 590 | this.setStartCommand(annyang.start); 591 | this.setAbortCommand(annyang.abort); 592 | annyang.addCallback('start', this.onStart); 593 | annyang.addCallback('end', this.onEnd); 594 | annyang.addCallback('resultMatch', _annyangSetRecognizedSentence); 595 | annyang.addCallback('resultNoMatch', _annyangSetRecognizedSentence); 596 | } 597 | 598 | }; 599 | 600 | }).call(this); 601 | -------------------------------------------------------------------------------- /test/SpecRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Spec Runner 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /test/helper_functions.js: -------------------------------------------------------------------------------- 1 | var getWrappers = function() { 2 | return $('div#skitt-ui'); 3 | }; 4 | 5 | var getWrapper = function() { 6 | return getWrappers()[0]; 7 | }; 8 | 9 | var getToggleButtons = function() { 10 | return $('a#skitt-toggle-button', getWrapper()); 11 | }; 12 | 13 | var getToggleButton = function() { 14 | return getToggleButtons()[0]; 15 | }; 16 | 17 | var getToggleButtonLabels = function() { 18 | return $('label#skitt-toggle-button__label', getWrapper()); 19 | }; 20 | 21 | var getToggleButtonLabel = function() { 22 | return getToggleButtonLabels()[0]; 23 | }; 24 | 25 | var getStyleSheets = function() { 26 | return $('#skitt-style-sheet'); 27 | }; 28 | 29 | var getStyleSheet = function() { 30 | return getStyleSheets()[0]; 31 | }; 32 | 33 | var getListeningTexts = function() { 34 | return $('#skitt-listening-text'); 35 | }; 36 | 37 | var getListeningText = function() { 38 | return getListeningTexts()[0]; 39 | }; 40 | 41 | var getInstructionsTexts = function() { 42 | return $('#skitt-listening-text__instructions', getListeningTexts()[0]); 43 | }; 44 | 45 | var getInstructionsText = function() { 46 | return getInstructionsTexts()[0]; 47 | }; 48 | 49 | var getSamplesTexts = function() { 50 | return $('#skitt-listening-text__samples', getListeningTexts()[0]); 51 | }; 52 | 53 | var getSamplesText = function() { 54 | return getSamplesTexts()[0]; 55 | }; 56 | 57 | var getLastSentenceTexts = function () { 58 | return $('#skitt-listening-text__recognized-sentence', getWrapper()); 59 | }; 60 | 61 | var getLastSentenceText = function () { 62 | return getLastSentenceTexts()[0]; 63 | }; 64 | 65 | var simulateClick = function(element) { 66 | var event = document.createEvent("MouseEvents"); 67 | event.initEvent("click", true, false); 68 | return element.dispatchEvent(event); 69 | }; -------------------------------------------------------------------------------- /test/init_corti.js: -------------------------------------------------------------------------------- 1 | Corti.patch(); -------------------------------------------------------------------------------- /test/spec/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node" : true, 3 | "browser" : true, 4 | "devel" : false, 5 | "camelcase" : true, 6 | "curly" : true, 7 | "latedef" : true, 8 | "unused" : true, 9 | "trailing" : true, 10 | "eqeqeq" : true, 11 | "eqnull" : true, 12 | "evil" : false, 13 | "forin" : true, 14 | "immed" : true, 15 | "laxbreak" : false, 16 | "newcap" : true, 17 | "noarg" : true, 18 | "noempty" : false, 19 | "nonew" : true, 20 | "onevar" : false, 21 | "plusplus" : false, 22 | "undef" : true, 23 | "sub" : true, 24 | "strict" : true, 25 | "white" : false, 26 | "indent" : 2, 27 | "globals": { 28 | "afterEach": false, 29 | "beforeEach": false, 30 | "describe": false, 31 | "expect": false, 32 | "jasmine": false, 33 | "it": false, 34 | "xit": false, 35 | "SpeechKITT": false, 36 | "Corti": false, 37 | "SpeechRecognition": false, 38 | "annyang": false, 39 | "$": false, 40 | "getWrappers": false, 41 | "getWrapper": false, 42 | "getToggleButtons": false, 43 | "getToggleButton": false, 44 | "getToggleButtonLabels": false, 45 | "getToggleButtonLabel": false, 46 | "getStyleSheets": false, 47 | "getStyleSheet": false, 48 | "getListeningTexts": false, 49 | "getListeningText": false, 50 | "getInstructionsTexts": false, 51 | "getInstructionsText": false, 52 | "getSamplesTexts": false, 53 | "getSamplesText": false, 54 | "getLastSentenceTexts": false, 55 | "getLastSentenceText": false, 56 | "simulateClick": false 57 | } 58 | } -------------------------------------------------------------------------------- /test/spec/1_BasicSpec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | 4 | describe('SpeechKITT', function() { 5 | 6 | it('should exist in global namespace', function () { 7 | expect(SpeechKITT).toEqual(jasmine.any(Object)); 8 | }); 9 | 10 | it('should contain setStartCommand method', function () { 11 | expect(SpeechKITT.setStartCommand).toEqual(jasmine.any(Function)); 12 | }); 13 | 14 | it('should contain setAbortCommand method', function () { 15 | expect(SpeechKITT.setAbortCommand).toEqual(jasmine.any(Function)); 16 | }); 17 | 18 | it('should contain startRecognition method', function () { 19 | expect(SpeechKITT.startRecognition).toEqual(jasmine.any(Function)); 20 | }); 21 | 22 | it('should contain abortRecognition method', function () { 23 | expect(SpeechKITT.abortRecognition).toEqual(jasmine.any(Function)); 24 | }); 25 | 26 | it('should contain toggleRecognition method', function () { 27 | expect(SpeechKITT.toggleRecognition).toEqual(jasmine.any(Function)); 28 | }); 29 | 30 | it('should contain onStart method', function () { 31 | expect(SpeechKITT.onStart).toEqual(jasmine.any(Function)); 32 | }); 33 | 34 | it('should contain onEnd method', function () { 35 | expect(SpeechKITT.onEnd).toEqual(jasmine.any(Function)); 36 | }); 37 | 38 | it('should contain render method', function () { 39 | expect(SpeechKITT.render).toEqual(jasmine.any(Function)); 40 | }); 41 | 42 | it('should contain vroom method', function () { 43 | expect(SpeechKITT.vroom).toEqual(jasmine.any(Function)); 44 | }); 45 | 46 | it('should contain hide method', function () { 47 | expect(SpeechKITT.hide).toEqual(jasmine.any(Function)); 48 | }); 49 | 50 | it('should contain show method', function () { 51 | expect(SpeechKITT.show).toEqual(jasmine.any(Function)); 52 | }); 53 | 54 | it('should contain isListening method', function () { 55 | expect(SpeechKITT.isListening).toEqual(jasmine.any(Function)); 56 | }); 57 | 58 | it('should contain setStylesheet method', function () { 59 | expect(SpeechKITT.setStylesheet).toEqual(jasmine.any(Function)); 60 | }); 61 | 62 | it('should contain setToggleLabelText method', function () { 63 | expect(SpeechKITT.setToggleLabelText).toEqual(jasmine.any(Function)); 64 | }); 65 | 66 | it('should contain getInstructionsText method', function () { 67 | expect(SpeechKITT.setInstructionsText).toEqual(jasmine.any(Function)); 68 | }); 69 | 70 | it('should contain setSampleCommands method', function () { 71 | expect(SpeechKITT.setSampleCommands).toEqual(jasmine.any(Function)); 72 | }); 73 | 74 | it('should contain annyang method', function () { 75 | expect(SpeechKITT.annyang).toEqual(jasmine.any(Function)); 76 | }); 77 | 78 | it('should contain rememberStatus method', function () { 79 | expect(SpeechKITT.rememberStatus).toEqual(jasmine.any(Function)); 80 | }); 81 | 82 | it('should contain setRecognizedSentence method', function () { 83 | expect(SpeechKITT.setRecognizedSentence).toEqual(jasmine.any(Function)); 84 | }); 85 | 86 | it('should contain getLastRecognizedSentence method', function () { 87 | expect(SpeechKITT.getLastRecognizedSentence).toEqual(jasmine.any(Function)); 88 | }); 89 | 90 | it('should contain displayRecognizedSentence method', function () { 91 | expect(SpeechKITT.displayRecognizedSentence).toEqual(jasmine.any(Function)); 92 | }); 93 | 94 | }); 95 | 96 | describe('Initial state', function() { 97 | 98 | describe('SpeechKITT.getLastRecognizedSentence', function() { 99 | 100 | it('should return undefined if called before anything said', function () { 101 | expect(SpeechKITT.getLastRecognizedSentence()).toBe(undefined); 102 | }); 103 | 104 | }); 105 | 106 | }); 107 | 108 | describe('SpeechKITT.setStartCommand', function() { 109 | 110 | it('should throw an error when called without a callback function', function () { 111 | expect(function() { 112 | SpeechKITT.setStartCommand(); 113 | }).toThrowError(); 114 | }); 115 | 116 | it('should throw an error when called with an invalid callback function', function () { 117 | expect(function() { 118 | SpeechKITT.setStartCommand('blerg'); 119 | }).toThrowError(); 120 | }); 121 | 122 | it('should throw an error when called with an undefined callback function', function () { 123 | expect(function() { 124 | SpeechKITT.setStartCommand(undefined); 125 | }).toThrowError(); 126 | }); 127 | 128 | //@TODO: define a test for different contexts 129 | 130 | }); 131 | 132 | describe('SpeechKITT.setAbortCommand', function() { 133 | 134 | it('should throw an error when called without a callback function', function () { 135 | expect(function() { 136 | SpeechKITT.setAbortCommand(); 137 | }).toThrowError(); 138 | }); 139 | 140 | it('should throw an error when called with an invalid callback function', function () { 141 | expect(function() { 142 | SpeechKITT.setAbortCommand('blerg'); 143 | }).toThrowError(); 144 | }); 145 | 146 | it('should throw an error when called with an undefined callback function', function () { 147 | expect(function() { 148 | SpeechKITT.setAbortCommand(undefined); 149 | }).toThrowError(); 150 | }); 151 | 152 | }); 153 | 154 | describe('SpeechKITT.startRecognition', function() { 155 | 156 | var recognition; 157 | 158 | beforeEach(function() { 159 | Corti.patch(); 160 | recognition = new SpeechRecognition(); 161 | }); 162 | 163 | afterEach(function() { 164 | Corti.unpatch(); 165 | }); 166 | 167 | it('should throw an error when called before setting a start command', function () { 168 | expect(function() { 169 | SpeechKITT.startRecognition(); 170 | }).toThrowError(); 171 | }); 172 | 173 | it('should start SpeechRecognition', function () { 174 | SpeechKITT.setStartCommand(recognition.start); 175 | expect(recognition.isStarted()).toBe(false); 176 | SpeechKITT.startRecognition(); 177 | expect(SpeechKITT.isListening()).toBe(true); 178 | expect(recognition.isStarted()).toBe(true); 179 | }); 180 | 181 | it('should throw an exception if called on an already running SpeechRecognition object', function () { 182 | SpeechKITT.setStartCommand(recognition.start); 183 | expect(recognition.isStarted()).toBe(false); 184 | SpeechKITT.startRecognition(); 185 | expect(SpeechKITT.isListening()).toBe(true); 186 | expect(recognition.isStarted()).toBe(true); 187 | expect(function() { 188 | SpeechKITT.startRecognition(); 189 | }).toThrowError(); 190 | }); 191 | 192 | }); 193 | 194 | describe('SpeechKITT.abortRecognition', function() { 195 | 196 | var recognition; 197 | 198 | beforeEach(function() { 199 | Corti.patch(); 200 | recognition = new SpeechRecognition(); 201 | }); 202 | 203 | afterEach(function() { 204 | Corti.unpatch(); 205 | }); 206 | 207 | it('should throw an error when called before setting an abort command', function () { 208 | expect(function() { 209 | SpeechKITT.abortRecognition(); 210 | }).toThrowError(); 211 | }); 212 | 213 | it('should abort SpeechRecognition', function () { 214 | SpeechKITT.setStartCommand(recognition.start); 215 | SpeechKITT.setAbortCommand(recognition.abort); 216 | expect(recognition.isStarted()).toBe(false); 217 | SpeechKITT.startRecognition(); 218 | expect(SpeechKITT.isListening()).toBe(true); 219 | expect(recognition.isStarted()).toBe(true); 220 | SpeechKITT.abortRecognition(); 221 | expect(SpeechKITT.isListening()).toBe(false); 222 | expect(recognition.isStarted()).toBe(false); 223 | SpeechKITT.abortRecognition(); 224 | expect(SpeechKITT.isListening()).toBe(false); 225 | expect(recognition.isStarted()).toBe(false); 226 | }); 227 | 228 | }); 229 | 230 | describe('SpeechKITT.toggleRecognition', function() { 231 | 232 | var recognition; 233 | 234 | beforeEach(function() { 235 | Corti.patch(); 236 | recognition = new SpeechRecognition(); 237 | }); 238 | 239 | afterEach(function() { 240 | Corti.unpatch(); 241 | }); 242 | 243 | it('should alternate between aborting and starting SpeechRecognition', function () { 244 | SpeechKITT.setStartCommand(recognition.start); 245 | SpeechKITT.setAbortCommand(recognition.abort); 246 | SpeechKITT.startRecognition(); 247 | expect(recognition.isStarted()).toBe(true); 248 | expect(SpeechKITT.isListening()).toBe(true); 249 | SpeechKITT.toggleRecognition(); 250 | expect(recognition.isStarted()).toBe(false); 251 | expect(SpeechKITT.isListening()).toBe(false); 252 | SpeechKITT.toggleRecognition(); 253 | expect(recognition.isStarted()).toBe(true); 254 | expect(SpeechKITT.isListening()).toBe(true); 255 | SpeechKITT.toggleRecognition(); 256 | }); 257 | 258 | }); 259 | 260 | describe('SpeechKITT.isListening', function() { 261 | 262 | var recognition; 263 | 264 | beforeEach(function() { 265 | Corti.patch(); 266 | recognition = new SpeechRecognition(); 267 | }); 268 | 269 | afterEach(function() { 270 | Corti.unpatch(); 271 | }); 272 | 273 | it('should return false initially', function () { 274 | expect(SpeechKITT.isListening()).toBe(false); 275 | }); 276 | 277 | it('should return true after starting SpeechKITT', function () { 278 | SpeechKITT.setStartCommand(recognition.start); 279 | expect(SpeechKITT.isListening()).toBe(false); 280 | SpeechKITT.startRecognition(); 281 | expect(SpeechKITT.isListening()).toBe(true); 282 | }); 283 | 284 | }); 285 | 286 | describe('SpeechKITT.annyang', function() { 287 | 288 | var recognition; 289 | 290 | beforeEach(function() { 291 | jasmine.clock().install(); 292 | recognition = annyang.getSpeechRecognizer(); 293 | annyang.removeCommands(); 294 | annyang.addCommands({ 295 | 'Time for some thrilling :action': function() {} 296 | }); 297 | }); 298 | 299 | afterEach(function() { 300 | annyang.abort(); 301 | jasmine.clock().tick(101); 302 | jasmine.clock().uninstall(); 303 | }); 304 | 305 | it('should set start command to annyang.start', function () { 306 | expect(annyang.isListening()).toBe(false); 307 | SpeechKITT.annyang(); 308 | SpeechKITT.startRecognition(); 309 | expect(annyang.isListening()).toBe(true); 310 | }); 311 | 312 | it('should set abort command to annyang.abort', function () { 313 | expect(annyang.isListening()).toBe(false); 314 | SpeechKITT.annyang(); 315 | SpeechKITT.startRecognition(); 316 | expect(annyang.isListening()).toBe(true); 317 | SpeechKITT.abortRecognition(); 318 | expect(annyang.isListening()).toBe(false); 319 | }); 320 | 321 | it('should add a callback to SpeechKITT.onStart to annyang\'s start event', function () { 322 | SpeechKITT.annyang(); 323 | expect(SpeechKITT.isListening()).toBe(false); 324 | annyang.start(); 325 | expect(SpeechKITT.isListening()).toBe(true); 326 | }); 327 | 328 | it('should add a callback to SpeechKITT.onEnd to annyang\'s end event', function () { 329 | SpeechKITT.annyang(); 330 | annyang.start(); 331 | expect(SpeechKITT.isListening()).toBe(true); 332 | annyang.abort(); 333 | jasmine.clock().tick(101); 334 | expect(SpeechKITT.isListening()).toBe(false); 335 | }); 336 | 337 | it('should capture recognized sentence from `resultMatch` event and call SpeechKITT.setRecognizedSentence()', function () { 338 | var sentence = 'Time for some thrilling heroics'; 339 | SpeechKITT.annyang(); 340 | annyang.start(); 341 | recognition.say(sentence); 342 | expect(SpeechKITT.getLastRecognizedSentence()).toBe(sentence); 343 | }); 344 | 345 | it('should capture most probable sentence from `resultNoMatch` event and call SpeechKITT.setRecognizedSentence()', function () { 346 | var sentence = "You can't take the sky from me"; 347 | SpeechKITT.annyang(); 348 | annyang.start(); 349 | recognition.say(sentence); 350 | expect(SpeechKITT.getLastRecognizedSentence()).toBe(sentence); 351 | }); 352 | 353 | }); 354 | 355 | describe('SpeechKITT.onStart', function() { 356 | 357 | it('should set Speech KITT to listening mode if it was not already listening', function () { 358 | expect(SpeechKITT.isListening()).toBe(false); 359 | SpeechKITT.onStart(); 360 | expect(SpeechKITT.isListening()).toBe(true); 361 | }); 362 | 363 | it('should leave Speech KITT in listening mode if it was already listening', function () { 364 | expect(SpeechKITT.isListening()).toBe(true); 365 | SpeechKITT.onStart(); 366 | expect(SpeechKITT.isListening()).toBe(true); 367 | }); 368 | 369 | }); 370 | 371 | describe('SpeechKITT.onEnd', function() { 372 | 373 | beforeEach(function() { 374 | jasmine.clock().install(); 375 | }); 376 | 377 | afterEach(function() { 378 | jasmine.clock().uninstall(); 379 | }); 380 | 381 | it('should set Speech KITT to not listening mode if it was listening only after 100ms have passed without it being restarted', function () { 382 | expect(SpeechKITT.isListening()).toBe(true); 383 | SpeechKITT.onEnd(); 384 | expect(SpeechKITT.isListening()).toBe(true); 385 | jasmine.clock().tick(101); 386 | expect(SpeechKITT.isListening()).toBe(false); 387 | }); 388 | 389 | it('should leave Speech KITT in listening mode if it was called, but then onStart was called within 100ms', function () { 390 | SpeechKITT.startRecognition(); 391 | expect(SpeechKITT.isListening()).toBe(true); 392 | SpeechKITT.onEnd(); 393 | expect(SpeechKITT.isListening()).toBe(true); 394 | SpeechKITT.onStart(); 395 | jasmine.clock().tick(101); 396 | expect(SpeechKITT.isListening()).toBe(true); 397 | }); 398 | 399 | it('should leave Speech KITT in not listening mode if it was not listening', function () { 400 | SpeechKITT.abortRecognition(); 401 | expect(SpeechKITT.isListening()).toBe(false); 402 | SpeechKITT.onEnd(); 403 | expect(SpeechKITT.isListening()).toBe(false); 404 | }); 405 | 406 | }); 407 | 408 | describe('SpeechKITT.getLastRecognizedSentence', function() { 409 | 410 | it('should return the last said sentence if one was set by setRecognizedSentence', function () { 411 | var sentence1 = 'Next time you want to stab me in the back, have the guts to do it to my face'; 412 | var sentence2 = "Man walks down the street in a hat like that, you know he's not afraid of anything"; 413 | SpeechKITT.setRecognizedSentence(sentence1); 414 | SpeechKITT.setRecognizedSentence(sentence2); 415 | expect(SpeechKITT.getLastRecognizedSentence()).toEqual(sentence2); 416 | }); 417 | 418 | }); 419 | 420 | describe('SpeechKITT.setRecognizedSentence', function() { 421 | 422 | var sentence = 'Next time you want to stab me in the back, have the guts to do it to my face'; 423 | 424 | it('should always return undefined', function () { 425 | expect(SpeechKITT.setRecognizedSentence()).toBe(undefined); 426 | expect(SpeechKITT.setRecognizedSentence(sentence)).toBe(undefined); 427 | }); 428 | 429 | it('should add the sentence said to Speech KITT', function () { 430 | SpeechKITT.setRecognizedSentence(sentence); 431 | expect(SpeechKITT.getLastRecognizedSentence()).toEqual(sentence); 432 | }); 433 | 434 | }); 435 | 436 | })(); 437 | -------------------------------------------------------------------------------- /test/spec/2_UISpec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | 4 | describe('SpeechKITT.setStylesheet', function() { 5 | 6 | it('should be callable and return undefined', function () { 7 | expect(SpeechKITT.setStylesheet()).toBe(undefined); 8 | }); 9 | 10 | }); 11 | 12 | describe('SpeechKITT.hide', function() { 13 | it('should throw error if called before render was called', function () { 14 | expect(getWrappers()).toHaveLength(0); 15 | expect(function() { 16 | SpeechKITT.hide(); 17 | }).toThrowError(); 18 | expect(getWrappers()).toHaveLength(0); 19 | }); 20 | }); 21 | 22 | describe('SpeechKITT.show', function() { 23 | it('should throw error if called before render was called', function () { 24 | expect(getWrappers()).toHaveLength(0); 25 | expect(function() { 26 | SpeechKITT.show(); 27 | }).toThrowError(); 28 | expect(getWrappers()).toHaveLength(0); 29 | }); 30 | }); 31 | 32 | describe('SpeechKITT.vroom', function() { 33 | 34 | var recognition; 35 | 36 | beforeEach(function() { 37 | Corti.patch(); 38 | recognition = new SpeechRecognition(); 39 | SpeechKITT.setStartCommand(recognition.start); 40 | SpeechKITT.setAbortCommand(recognition.abort); 41 | }); 42 | 43 | afterEach(function() { 44 | Corti.unpatch(); 45 | }); 46 | 47 | it('should add a visible gui to the DOM inside a div#skitt-ui', function () { 48 | expect(getWrappers()).toHaveLength(0); 49 | SpeechKITT.vroom(); 50 | expect(getWrappers()).toHaveLength(1); 51 | expect(getWrapper()).toBeInDOM(); 52 | expect(getWrapper()).toBeVisible(); 53 | expect($(getWrapper()).attr('id')).toEqual('skitt-ui'); 54 | }); 55 | 56 | it('should add a visible start/end button to the wrapper a#skitt-toggle-button', function () { 57 | expect(getToggleButtons()).toHaveLength(1); 58 | expect(getToggleButton()).toBeInDOM(); 59 | expect(getToggleButton()).toBeVisible(); 60 | expect($(getToggleButton()).attr('id')).toEqual('skitt-toggle-button'); 61 | }); 62 | 63 | it('should add a label to the a#skitt-toggle-button', function () { 64 | expect(getToggleButtonLabels()).toHaveLength(1); 65 | expect(getToggleButtonLabel()).toBeInDOM(); 66 | expect(getToggleButtonLabel()).toBeVisible(); 67 | }); 68 | 69 | it('should add label with default text of "Activate Voice Control"', function () { 70 | expect(getToggleButtonLabel().innerText).toEqual('Activate Voice Control'); 71 | }); 72 | 73 | it('should add listening text', function () { 74 | expect(getListeningTexts()).toHaveLength(1); 75 | expect(getListeningText()).toBeInDOM(); 76 | expect(getListeningText()).toBeVisible(); 77 | }); 78 | 79 | it('should add instructions within listening text area', function () { 80 | expect(getInstructionsTexts()).toHaveLength(1); 81 | expect(getInstructionsText()).toBeInDOM(); 82 | expect(getInstructionsText()).toBeVisible(); 83 | }); 84 | 85 | it('should add instructions with default text of "What can I help you with?"', function () { 86 | expect(getInstructionsText().innerText).toEqual('What can I help you with?'); 87 | }); 88 | 89 | it('should not add samples by default (until they have been set)', function () { 90 | expect(getSamplesTexts()).toHaveLength(0); 91 | }); 92 | 93 | it('should start GUI in not listening mode', function () { 94 | SpeechKITT.abortRecognition(); 95 | SpeechKITT.vroom(); 96 | expect(SpeechKITT.isListening()).toBe(false); 97 | }); 98 | 99 | it('should start GUI in listening mode if recognition previously started', function () { 100 | SpeechKITT.startRecognition(); 101 | SpeechKITT.vroom(); 102 | expect(SpeechKITT.isListening()).toBe(true); 103 | }); 104 | 105 | it('should change the GUI based on listening mode', function () { 106 | SpeechKITT.abortRecognition(); 107 | expect(getWrapper()).toHaveClass('skitt-ui--not-listening'); 108 | expect(getWrapper()).not.toHaveClass('skitt-ui--listening'); 109 | SpeechKITT.startRecognition(); 110 | expect(getWrapper()).not.toHaveClass('skitt-ui--not-listening'); 111 | expect(getWrapper()).toHaveClass('skitt-ui--listening'); 112 | }); 113 | 114 | it('should not attach a style sheet if non was defined', function () { 115 | SpeechKITT.abortRecognition(); 116 | SpeechKITT.vroom(); 117 | expect(getStyleSheets()).toHaveLength(0); 118 | }); 119 | 120 | it('should attach a style sheet if one was defined with SpeechKITT.setStyle', function () { 121 | SpeechKITT.abortRecognition(); 122 | SpeechKITT.setStylesheet('flat.css'); 123 | SpeechKITT.vroom(); 124 | expect(getStyleSheets()).toHaveLength(1); 125 | expect(getStyleSheet().id).toEqual('skitt-style-sheet'); 126 | expect(getStyleSheet().rel).toEqual('stylesheet'); 127 | expect(getStyleSheet().href).toContain('flat.css'); 128 | }); 129 | 130 | it('should change the stylesheet if it is called again', function () { 131 | SpeechKITT.abortRecognition(); 132 | SpeechKITT.vroom(); 133 | SpeechKITT.setStylesheet('style1.css'); 134 | expect(getStyleSheets()).toHaveLength(1); 135 | expect(getStyleSheet().href).toContain('style1.css'); 136 | SpeechKITT.setStylesheet('style2.css'); 137 | expect(getStyleSheets()).toHaveLength(1); 138 | expect(getStyleSheet().href).not.toContain('style1.css'); 139 | expect(getStyleSheet().href).toContain('style2.css'); 140 | }); 141 | 142 | it('should not panic when called more than once', function () { 143 | expect(getWrappers()).toHaveLength(1); 144 | expect(getWrapper()).toBeInDOM(); 145 | expect(getWrapper()).toBeVisible(); 146 | SpeechKITT.vroom(); 147 | expect(getWrappers()).toHaveLength(1); 148 | expect(getWrapper()).toBeInDOM(); 149 | expect(getWrapper()).toBeVisible(); 150 | }); 151 | 152 | }); 153 | 154 | describe('SpeechKITT.hide', function() { 155 | 156 | beforeEach(function() { 157 | SpeechKITT.vroom(); 158 | }); 159 | 160 | it('should add skitt-ui--hidden class to the GUI', function () { 161 | SpeechKITT.show(); 162 | expect(getWrapper()).not.toHaveClass('skitt-ui--hidden'); 163 | expect(getWrapper()).toBeVisible(); 164 | SpeechKITT.hide(); 165 | expect(getWrapper()).toHaveClass('skitt-ui--hidden'); 166 | expect(getWrapper()).not.toBeVisible(); 167 | }); 168 | 169 | }); 170 | 171 | describe('SpeechKITT.show', function() { 172 | 173 | it('should remove skitt-ui--hidden class from the GUI', function () { 174 | SpeechKITT.hide(); 175 | expect(getWrapper()).toHaveClass('skitt-ui--hidden'); 176 | expect(getWrapper()).not.toBeVisible(); 177 | SpeechKITT.show(); 178 | expect(getWrapper()).not.toHaveClass('skitt-ui--hidden'); 179 | expect(getWrapper()).toBeVisible(); 180 | }); 181 | 182 | }); 183 | 184 | describe('SpeechKITT.setToggleLabelText', function() { 185 | 186 | var recognition; 187 | 188 | beforeEach(function() { 189 | Corti.patch(); 190 | recognition = new SpeechRecognition(); 191 | SpeechKITT.setStartCommand(recognition.start); 192 | SpeechKITT.setAbortCommand(recognition.abort); 193 | SpeechKITT.vroom(); 194 | SpeechKITT.abortRecognition(); 195 | }); 196 | 197 | afterEach(function() { 198 | Corti.unpatch(); 199 | }); 200 | 201 | it('should change the text of the toggle button label', function () { 202 | expect(getToggleButtonLabel().innerText).toEqual('Activate Voice Control'); 203 | SpeechKITT.setToggleLabelText('Hi KITT'); 204 | expect(getToggleButtonLabel().innerText).toEqual('Hi KITT'); 205 | }); 206 | 207 | }); 208 | 209 | describe('SpeechKITT.setInstructionsText', function() { 210 | 211 | var recognition; 212 | 213 | beforeEach(function() { 214 | Corti.patch(); 215 | recognition = new SpeechRecognition(); 216 | SpeechKITT.setStartCommand(recognition.start); 217 | SpeechKITT.setAbortCommand(recognition.abort); 218 | SpeechKITT.vroom(); 219 | SpeechKITT.abortRecognition(); 220 | SpeechKITT.setInstructionsText('What can I help you with?'); 221 | }); 222 | 223 | afterEach(function() { 224 | Corti.unpatch(); 225 | }); 226 | 227 | it('should not change the instructions text if parameter is not a string', function () { 228 | expect(getInstructionsText().innerText).toEqual('What can I help you with?'); 229 | SpeechKITT.setInstructionsText(undefined); 230 | expect(getInstructionsText().innerText).toEqual('What can I help you with?'); 231 | SpeechKITT.setInstructionsText('Talk to me Goose!'); 232 | expect(getInstructionsText().innerText).toEqual('Talk to me Goose!'); 233 | SpeechKITT.setInstructionsText(123456789); 234 | expect(getInstructionsText().innerText).toEqual('Talk to me Goose!'); 235 | SpeechKITT.setInstructionsText({}); 236 | expect(getInstructionsText().innerText).toEqual('Talk to me Goose!'); 237 | }); 238 | 239 | it('should change the text of the listening instructions', function () { 240 | expect(getInstructionsText().innerText).toEqual('What can I help you with?'); 241 | SpeechKITT.setInstructionsText('Talk to me Goose!'); 242 | expect(getInstructionsText().innerText).toEqual('Talk to me Goose!'); 243 | }); 244 | 245 | it('should accept HTML', function () { 246 | SpeechKITT.setInstructionsText('Talk to me Goose!'); 247 | expect($('strong', getInstructionsTexts()).length).toEqual(1); 248 | expect($('strong', getInstructionsTexts())[0].innerText).toEqual('Goose'); 249 | }); 250 | 251 | }); 252 | 253 | describe('SpeechKITT.setSampleCommands', function() { 254 | 255 | var recognition; 256 | 257 | beforeEach(function() { 258 | Corti.patch(); 259 | recognition = new SpeechRecognition(); 260 | SpeechKITT.setStartCommand(recognition.start); 261 | SpeechKITT.setAbortCommand(recognition.abort); 262 | SpeechKITT.vroom(); 263 | SpeechKITT.abortRecognition(); 264 | }); 265 | 266 | afterEach(function() { 267 | Corti.unpatch(); 268 | }); 269 | 270 | it('should set the text of the sample commands and add it to the DOM', function () { 271 | expect(getSamplesTexts()).toHaveLength(0); 272 | SpeechKITT.setSampleCommands(['Show directions', 'Call restaurant']); 273 | expect(getSamplesTexts()).toHaveLength(1); 274 | expect(getSamplesText()).toBeInDOM(); 275 | expect(getSamplesText()).toBeVisible(); 276 | expect(getSamplesText().innerText).toEqual('Show directions. Call restaurant.'); 277 | }); 278 | 279 | it('should delete the sample commands and remove them from the DOM when passed with no parameters', function () { 280 | SpeechKITT.setSampleCommands(['Show directions', 'Call restaurant']); 281 | SpeechKITT.setSampleCommands(); 282 | expect(getSamplesTexts()).toHaveLength(0); 283 | }); 284 | 285 | it('should delete the sample commands and remove them from the DOM when passed with an empty array', function () { 286 | SpeechKITT.setSampleCommands(['Show directions', 'Call restaurant']); 287 | SpeechKITT.setSampleCommands(); 288 | expect(getSamplesTexts()).toHaveLength(0); 289 | }); 290 | 291 | it('should add a class `skitt-ui--sample-commands-shown` to the root node when sample commands are shown', function () { 292 | SpeechKITT.setSampleCommands(['Show directions', 'Call restaurant']); 293 | expect($(getWrapper()).hasClass('skitt-ui--sample-commands-shown')).toBeTruthy(); 294 | }); 295 | 296 | it('should remove the class `skitt-ui--sample-commands-shown` from the root node when sample commands are not shown', function () { 297 | SpeechKITT.setSampleCommands(); 298 | expect($(getWrapper()).hasClass('skitt-ui--sample-commands-shown')).toBeFalsy(); 299 | }); 300 | 301 | }); 302 | 303 | describe('SpeechKITT.rememberStatus', function() { 304 | 305 | var recognition; 306 | 307 | beforeEach(function() { 308 | jasmine.clock().install(); 309 | Corti.patch(); 310 | recognition = new SpeechRecognition(); 311 | SpeechKITT.setStartCommand(recognition.start); 312 | SpeechKITT.setAbortCommand(recognition.abort); 313 | recognition.addEventListener('end', SpeechKITT.onEnd); 314 | SpeechKITT.vroom(); 315 | SpeechKITT.abortRecognition(); 316 | }); 317 | 318 | afterEach(function() { 319 | jasmine.clock().uninstall(); 320 | Corti.unpatch(); 321 | }); 322 | 323 | it('should throw an error when called without a parameter or an invalid parameter', function () { 324 | expect(function() { 325 | SpeechKITT.rememberStatus(); 326 | }).toThrowError(); 327 | expect(function() { 328 | SpeechKITT.rememberStatus('Michael'); 329 | }).toThrowError(); 330 | expect(function() { 331 | SpeechKITT.rememberStatus(-12); 332 | }).toThrowError(); 333 | }); 334 | 335 | it('should accept one parameter which is an integer equal to or greater than zero', function () { 336 | expect(function() { 337 | SpeechKITT.rememberStatus(0); 338 | }).not.toThrowError(); 339 | expect(function() { 340 | SpeechKITT.rememberStatus(Infinity); 341 | }).not.toThrowError(); 342 | expect(function() { 343 | SpeechKITT.rememberStatus(60); 344 | }).not.toThrowError(); 345 | }); 346 | 347 | it('should save a cookie called `skittremember` that will expire n minutes after startRecognition() was last called', function () { 348 | expect(document.cookie.indexOf('skittremember')).toBe(-1); 349 | SpeechKITT.rememberStatus(60); 350 | SpeechKITT.vroom(); 351 | expect(document.cookie.indexOf('skittremember')).toBe(-1); 352 | SpeechKITT.startRecognition(); 353 | expect(document.cookie.indexOf('skittremember')).not.toBe(-1); 354 | }); 355 | 356 | it('should clear the cookie called `skittremember` when abortRecognition() is called', function () { 357 | expect(document.cookie.indexOf('skittremember')).toBe(-1); 358 | SpeechKITT.startRecognition(); 359 | expect(document.cookie.indexOf('skittremember')).not.toBe(-1); 360 | SpeechKITT.abortRecognition(); 361 | expect(document.cookie.indexOf('skittremember')).toBe(-1); 362 | }); 363 | 364 | it('should start listening immediately on render() if startRecognition() was previously called, abortRecognition() has not been called since and cookie hasn\'t expired', function () { 365 | expect(SpeechKITT.isListening()).toBe(false); 366 | expect(document.cookie.indexOf('skittremember')).toBe(-1); 367 | SpeechKITT.rememberStatus(60); 368 | SpeechKITT.render(); 369 | expect(SpeechKITT.isListening()).toBe(false); 370 | SpeechKITT.startRecognition(); 371 | expect(document.cookie.indexOf('skittremember')).not.toBe(-1); 372 | expect(SpeechKITT.isListening()).toBe(true); 373 | recognition.abort(); 374 | jasmine.clock().tick(101); 375 | expect(SpeechKITT.isListening()).toBe(false); 376 | expect(document.cookie.indexOf('skittremember')).not.toBe(-1); 377 | SpeechKITT.render(); 378 | expect(SpeechKITT.isListening()).toBe(true); 379 | }); 380 | 381 | }); 382 | 383 | describe('SpeechKITT.displayRecognizedSentence', function() { 384 | 385 | var recognition; 386 | var sentence1 = 'That sounds like something out of science-fiction'; 387 | var sentence2 = 'We live in a spaceship, dear'; 388 | 389 | beforeEach(function() { 390 | Corti.patch(); 391 | recognition = new SpeechRecognition(); 392 | SpeechKITT.setStartCommand(recognition.start); 393 | SpeechKITT.setAbortCommand(recognition.abort); 394 | SpeechKITT.vroom(); 395 | }); 396 | 397 | afterEach(function() { 398 | SpeechKITT.abortRecognition(); 399 | Corti.unpatch(); 400 | }); 401 | 402 | it('should be off by default and add nothing to the DOM', function () { 403 | expect(getLastSentenceTexts()).toHaveLength(0); 404 | SpeechKITT.setRecognizedSentence(sentence1); 405 | expect(getLastSentenceTexts()).toHaveLength(0); 406 | }); 407 | 408 | it('should create a span node', function() { 409 | expect(getLastSentenceText()).toBeUndefined(); 410 | SpeechKITT.displayRecognizedSentence(true); 411 | expect(getLastSentenceTexts().is('span')).toEqual(true); 412 | SpeechKITT.displayRecognizedSentence(false); 413 | }); 414 | 415 | it('should create the new node with the id `skitt-listening-text__recognized-sentence`', function() { 416 | expect(getLastSentenceText()).toBeUndefined(); 417 | SpeechKITT.displayRecognizedSentence(true); 418 | var expectedID = 'skitt-listening-text__recognized-sentence'; 419 | expect($(getLastSentenceText()).attr('id')).toEqual(expectedID); 420 | SpeechKITT.displayRecognizedSentence(false); 421 | }); 422 | 423 | it('should add the text of the last recognized sentence to the DOM even if turned on after it was said', function () { 424 | expect(getLastSentenceTexts()).toHaveLength(0); 425 | SpeechKITT.displayRecognizedSentence(true); 426 | expect(getLastSentenceTexts()).toHaveLength(1); 427 | expect(getLastSentenceText()).toBeInDOM(); 428 | expect(getLastSentenceText()).toBeVisible(); 429 | expect(getLastSentenceText().innerText).toEqual(sentence1); 430 | }); 431 | 432 | it('should replace the last recognized sentence in the div with a new one after another sentence has been recognized', function () { 433 | SpeechKITT.setRecognizedSentence(sentence1); 434 | expect(getLastSentenceText().innerText).toEqual(sentence1); 435 | SpeechKITT.setRecognizedSentence(sentence2); 436 | expect(getLastSentenceText().innerText).toEqual(sentence2); 437 | }); 438 | 439 | it('should remove the last recognized sentence div from the DOM when turned off', function () { 440 | SpeechKITT.displayRecognizedSentence(true); 441 | SpeechKITT.setRecognizedSentence(sentence1); 442 | expect(getLastSentenceTexts()).toHaveLength(1); 443 | SpeechKITT.displayRecognizedSentence(false); 444 | expect(getLastSentenceTexts()).toHaveLength(0); 445 | }); 446 | 447 | it('should default to true when passed with no parameters', function () { 448 | SpeechKITT.setRecognizedSentence(sentence1); 449 | SpeechKITT.displayRecognizedSentence(false); 450 | expect(getLastSentenceTexts()).toHaveLength(0); 451 | SpeechKITT.displayRecognizedSentence(); 452 | expect(getLastSentenceTexts()).toHaveLength(1); 453 | }); 454 | 455 | it('should add a class `skitt-ui--recognized-sentence-shown` to the root node when last recognized sentence is shown', function () { 456 | SpeechKITT.setRecognizedSentence(sentence1); 457 | SpeechKITT.displayRecognizedSentence(true); 458 | expect($(getWrapper()).hasClass('skitt-ui--recognized-sentence-shown')).toBeTruthy(); 459 | }); 460 | 461 | it('should remove the class `skitt-ui--recognized-sentence-shown` from the root node when last recognized sentence is shown', function () { 462 | SpeechKITT.setRecognizedSentence(sentence1); 463 | SpeechKITT.displayRecognizedSentence(false); 464 | expect($(getWrapper()).hasClass('skitt-ui--recognized-sentence-shown')).toBeFalsy(); 465 | }); 466 | 467 | }); 468 | 469 | })(); 470 | -------------------------------------------------------------------------------- /test/spec/3_FunctionalSpec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | 4 | describe('SpeechKITT toggle button', function() { 5 | 6 | beforeEach(function() { 7 | SpeechKITT.abortRecognition(); 8 | }); 9 | 10 | it('should turn speech recognition on when pressed while it is off', function () { 11 | expect(SpeechKITT.isListening()).toBe(false); 12 | simulateClick(getToggleButton()); 13 | expect(SpeechKITT.isListening()).toBe(true); 14 | }); 15 | 16 | it('should turn speech recognition off when pressed while it is on', function () { 17 | SpeechKITT.startRecognition(); 18 | expect(SpeechKITT.isListening()).toBe(true); 19 | simulateClick(getToggleButton()); 20 | expect(SpeechKITT.isListening()).toBe(false); 21 | }); 22 | 23 | }); 24 | 25 | })(); 26 | -------------------------------------------------------------------------------- /test/vendor/annyang.min.js: -------------------------------------------------------------------------------- 1 | //! annyang 2 | //! version : 2.2.1 3 | //! author : Tal Ater @TalAter 4 | //! license : MIT 5 | //! https://www.TalAter.com/annyang/ 6 | (function(a){"use strict";var b=this,c=b.SpeechRecognition||b.webkitSpeechRecognition||b.mozSpeechRecognition||b.msSpeechRecognition||b.oSpeechRecognition;if(!c)return b.annyang=null,a;var d,e,f=[],g={start:[],error:[],end:[],result:[],resultMatch:[],resultNoMatch:[],errorNetwork:[],errorPermissionBlocked:[],errorPermissionDenied:[]},h=0,i=!1,j="font-weight: bold; color: #00f;",k=!1,l=!1,m=/\s*\((.*?)\)\s*/g,n=/(\(\?:[^)]+\))\?/g,o=/(\(\?)?:\w+/g,p=/\*\w+/g,q=/[\-{}\[\]+?.,\\\^$|#]/g,r=function(a){return a=a.replace(q,"\\$&").replace(m,"(?:$1)?").replace(o,function(a,b){return b?a:"([^\\s]+)"}).replace(p,"(.*?)").replace(n,"\\s*$1?\\s*"),new RegExp("^"+a+"$","i")},s=function(a){var b=Array.prototype.slice.call(arguments,1);a.forEach(function(a){a.callback.apply(a.context,b)})},t=function(){return d!==a},u=function(){t()||b.annyang.init({},!1)},v=function(a,c,d){f.push({command:a,callback:c,originalPhrase:d}),i&&b.console.log("Command successfully loaded: %c"+d,j)};b.annyang={init:function(m,n){n=n===a?!0:!!n,d&&d.abort&&d.abort(),d=new c,d.maxAlternatives=5,d.continuous="http:"===b.location.protocol,d.lang="en-US",d.onstart=function(){l=!0,s(g.start)},d.onerror=function(a){switch(s(g.error),a.error){case"network":s(g.errorNetwork);break;case"not-allowed":case"service-not-allowed":e=!1,s((new Date).getTime()-h<200?g.errorPermissionBlocked:g.errorPermissionDenied)}},d.onend=function(){if(l=!1,s(g.end),e){var a=(new Date).getTime()-h;1e3>a?setTimeout(b.annyang.start,1e3-a):b.annyang.start()}},d.onresult=function(a){if(k)return i&&b.console.log("Speech heard, but annyang is paused"),!1;for(var c=a.results[a.resultIndex],d=[],e=0;em;m++){var o=f[m],p=o.command.exec(h);if(p){var q=p.slice(1);return i&&(b.console.log("command matched: %c"+o.originalPhrase,j),q.length&&b.console.log("with parameters",q)),o.callback.apply(this,q),s(g.resultMatch,h,o.originalPhrase,d),!0}}}return s(g.resultNoMatch,d),!1},n&&(f=[]),m.length&&this.addCommands(m)},start:function(c){k=!1,u(),c=c||{},e=c.autoRestart!==a?!!c.autoRestart:!0,c.continuous!==a&&(d.continuous=!!c.continuous),h=(new Date).getTime();try{d.start()}catch(f){i&&b.console.log(f.message)}},abort:function(){e=!1,t()&&d.abort()},pause:function(){k=!0},resume:function(){b.annyang.start()},debug:function(a){i=arguments.length>0?!!a:!0},setLanguage:function(a){u(),d.lang=a},addCommands:function(a){var c;u();for(var d in a)if(a.hasOwnProperty(d))if(c=b[a[d]]||a[d],"function"==typeof c)v(r(d),c,d);else{if(!("object"==typeof c&&c.regexp instanceof RegExp)){i&&b.console.log("Can not register command: %c"+d,j);continue}v(new RegExp(c.regexp.source,"i"),c.callback,d)}},removeCommands:function(b){return b===a?void(f=[]):(b=Array.isArray(b)?b:[b],void(f=f.filter(function(a){for(var c=0;c= this.length) { 120 | return null; 121 | } else { 122 | return this[index]; 123 | } 124 | }; 125 | for (commandIterator = 0; commandIterator<_maxAlternatives; commandIterator++) { 126 | var etc = ''; 127 | for (etcIterator = 0; etcIterator').attr(attributesToSet) 100 | } 101 | 102 | jasmine.Fixtures.prototype.createContainer_ = function (html) { 103 | var container = $('
') 104 | .attr('id', this.containerId) 105 | .html(html) 106 | 107 | $(document.body).append(container) 108 | return container 109 | } 110 | 111 | jasmine.Fixtures.prototype.addToContainer_ = function (html){ 112 | var container = $(document.body).find('#'+this.containerId).append(html) 113 | 114 | if (!container.length) { 115 | this.createContainer_(html) 116 | } 117 | } 118 | 119 | jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) { 120 | if (typeof this.fixturesCache_[url] === 'undefined') { 121 | this.loadFixtureIntoCache_(url) 122 | } 123 | return this.fixturesCache_[url] 124 | } 125 | 126 | jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 127 | var self = this 128 | , url = this.makeFixtureUrl_(relativeUrl) 129 | , htmlText = '' 130 | , request = $.ajax({ 131 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 132 | cache: false, 133 | url: url, 134 | dataType: 'html', 135 | success: function (data, status, $xhr) { 136 | htmlText = $xhr.responseText 137 | } 138 | }).fail(function ($xhr, status, err) { 139 | throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 140 | }) 141 | 142 | var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; 143 | 144 | scripts.each(function(){ 145 | $.ajax({ 146 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 147 | cache: false, 148 | dataType: 'script', 149 | url: $(this).attr('src'), 150 | success: function (data, status, $xhr) { 151 | htmlText += '' 152 | }, 153 | error: function ($xhr, status, err) { 154 | throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 155 | } 156 | }); 157 | }) 158 | 159 | self.fixturesCache_[relativeUrl] = htmlText; 160 | } 161 | 162 | jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){ 163 | return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 164 | } 165 | 166 | jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 167 | return this[methodName].apply(this, passedArguments) 168 | } 169 | 170 | 171 | jasmine.StyleFixtures = function () { 172 | this.fixturesCache_ = {} 173 | this.fixturesNodes_ = [] 174 | this.fixturesPath = 'spec/javascripts/fixtures' 175 | } 176 | 177 | jasmine.StyleFixtures.prototype.set = function (css) { 178 | this.cleanUp() 179 | this.createStyle_(css) 180 | } 181 | 182 | jasmine.StyleFixtures.prototype.appendSet = function (css) { 183 | this.createStyle_(css) 184 | } 185 | 186 | jasmine.StyleFixtures.prototype.preload = function () { 187 | this.read_.apply(this, arguments) 188 | } 189 | 190 | jasmine.StyleFixtures.prototype.load = function () { 191 | this.cleanUp() 192 | this.createStyle_(this.read_.apply(this, arguments)) 193 | } 194 | 195 | jasmine.StyleFixtures.prototype.appendLoad = function () { 196 | this.createStyle_(this.read_.apply(this, arguments)) 197 | } 198 | 199 | jasmine.StyleFixtures.prototype.cleanUp = function () { 200 | while(this.fixturesNodes_.length) { 201 | this.fixturesNodes_.pop().remove() 202 | } 203 | } 204 | 205 | jasmine.StyleFixtures.prototype.createStyle_ = function (html) { 206 | var styleText = $('
').html(html).text() 207 | , style = $('') 208 | 209 | this.fixturesNodes_.push(style) 210 | $('head').append(style) 211 | } 212 | 213 | jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache 214 | jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read 215 | jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ 216 | jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ 217 | jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ 218 | jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ 219 | 220 | jasmine.getJSONFixtures = function () { 221 | return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() 222 | } 223 | 224 | jasmine.JSONFixtures = function () { 225 | this.fixturesCache_ = {} 226 | this.fixturesPath = 'spec/javascripts/fixtures/json' 227 | } 228 | 229 | jasmine.JSONFixtures.prototype.load = function () { 230 | this.read.apply(this, arguments) 231 | return this.fixturesCache_ 232 | } 233 | 234 | jasmine.JSONFixtures.prototype.read = function () { 235 | var fixtureUrls = arguments 236 | 237 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 238 | this.getFixtureData_(fixtureUrls[urlIndex]) 239 | } 240 | 241 | return this.fixturesCache_ 242 | } 243 | 244 | jasmine.JSONFixtures.prototype.clearCache = function () { 245 | this.fixturesCache_ = {} 246 | } 247 | 248 | jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) { 249 | if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url) 250 | return this.fixturesCache_[url] 251 | } 252 | 253 | jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 254 | var self = this 255 | , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 256 | 257 | $.ajax({ 258 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 259 | cache: false, 260 | dataType: 'json', 261 | url: url, 262 | success: function (data) { 263 | self.fixturesCache_[relativeUrl] = data 264 | }, 265 | error: function ($xhr, status, err) { 266 | throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 267 | } 268 | }) 269 | } 270 | 271 | jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 272 | return this[methodName].apply(this, passedArguments) 273 | } 274 | 275 | jasmine.jQuery = function () {} 276 | 277 | jasmine.jQuery.browserTagCaseIndependentHtml = function (html) { 278 | return $('
').append(html).html() 279 | } 280 | 281 | jasmine.jQuery.elementToString = function (element) { 282 | return $(element).map(function () { return this.outerHTML; }).toArray().join(', ') 283 | } 284 | 285 | var data = { 286 | spiedEvents: {} 287 | , handlers: [] 288 | } 289 | 290 | jasmine.jQuery.events = { 291 | spyOn: function (selector, eventName) { 292 | var handler = function (e) { 293 | var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0 294 | data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = { 295 | args: jasmine.util.argsToArray(arguments), 296 | calls: ++calls 297 | } 298 | } 299 | 300 | $(selector).on(eventName, handler) 301 | data.handlers.push(handler) 302 | 303 | return { 304 | selector: selector, 305 | eventName: eventName, 306 | handler: handler, 307 | reset: function (){ 308 | delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 309 | }, 310 | calls: { 311 | count: function () { 312 | return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? 313 | data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0; 314 | }, 315 | any: function () { 316 | return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? 317 | !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false; 318 | } 319 | } 320 | } 321 | }, 322 | 323 | args: function (selector, eventName) { 324 | var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args 325 | 326 | if (!actualArgs) { 327 | throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent." 328 | } 329 | 330 | return actualArgs 331 | }, 332 | 333 | wasTriggered: function (selector, eventName) { 334 | return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) 335 | }, 336 | 337 | wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) { 338 | var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1) 339 | 340 | if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') 341 | actualArgs = actualArgs[0] 342 | 343 | return util.equals(actualArgs, expectedArgs, customEqualityTesters) 344 | }, 345 | 346 | wasPrevented: function (selector, eventName) { 347 | var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 348 | , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args 349 | , e = args ? args[0] : undefined 350 | 351 | return e && e.isDefaultPrevented() 352 | }, 353 | 354 | wasStopped: function (selector, eventName) { 355 | var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 356 | , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args 357 | , e = args ? args[0] : undefined 358 | 359 | return e && e.isPropagationStopped() 360 | }, 361 | 362 | cleanUp: function () { 363 | data.spiedEvents = {} 364 | data.handlers = [] 365 | } 366 | } 367 | 368 | var hasProperty = function (actualValue, expectedValue) { 369 | if (expectedValue === undefined) 370 | return actualValue !== undefined 371 | 372 | return actualValue === expectedValue 373 | } 374 | 375 | beforeEach(function () { 376 | jasmine.addMatchers({ 377 | toHaveClass: function () { 378 | return { 379 | compare: function (actual, className) { 380 | return { pass: $(actual).hasClass(className) } 381 | } 382 | } 383 | }, 384 | 385 | toHaveCss: function () { 386 | return { 387 | compare: function (actual, css) { 388 | var stripCharsRegex = /[\s;\"\']/g 389 | for (var prop in css) { 390 | var value = css[prop] 391 | // see issue #147 on gh 392 | ;if ((value === 'auto') && ($(actual).get(0).style[prop] === 'auto')) continue 393 | var actualStripped = $(actual).css(prop).replace(stripCharsRegex, '') 394 | var valueStripped = value.replace(stripCharsRegex, '') 395 | if (actualStripped !== valueStripped) return { pass: false } 396 | } 397 | return { pass: true } 398 | } 399 | } 400 | }, 401 | 402 | toBeVisible: function () { 403 | return { 404 | compare: function (actual) { 405 | return { pass: $(actual).is(':visible') } 406 | } 407 | } 408 | }, 409 | 410 | toBeHidden: function () { 411 | return { 412 | compare: function (actual) { 413 | return { pass: $(actual).is(':hidden') } 414 | } 415 | } 416 | }, 417 | 418 | toBeSelected: function () { 419 | return { 420 | compare: function (actual) { 421 | return { pass: $(actual).is(':selected') } 422 | } 423 | } 424 | }, 425 | 426 | toBeChecked: function () { 427 | return { 428 | compare: function (actual) { 429 | return { pass: $(actual).is(':checked') } 430 | } 431 | } 432 | }, 433 | 434 | toBeEmpty: function () { 435 | return { 436 | compare: function (actual) { 437 | return { pass: $(actual).is(':empty') } 438 | } 439 | } 440 | }, 441 | 442 | toBeInDOM: function () { 443 | return { 444 | compare: function (actual) { 445 | return { pass: $.contains(document.documentElement, $(actual)[0]) } 446 | } 447 | } 448 | }, 449 | 450 | toExist: function () { 451 | return { 452 | compare: function (actual) { 453 | return { pass: $(actual).length } 454 | } 455 | } 456 | }, 457 | 458 | toHaveLength: function () { 459 | return { 460 | compare: function (actual, length) { 461 | return { pass: $(actual).length === length } 462 | } 463 | } 464 | }, 465 | 466 | toHaveAttr: function () { 467 | return { 468 | compare: function (actual, attributeName, expectedAttributeValue) { 469 | return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) } 470 | } 471 | } 472 | }, 473 | 474 | toHaveProp: function () { 475 | return { 476 | compare: function (actual, propertyName, expectedPropertyValue) { 477 | return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) } 478 | } 479 | } 480 | }, 481 | 482 | toHaveId: function () { 483 | return { 484 | compare: function (actual, id) { 485 | return { pass: $(actual).attr('id') == id } 486 | } 487 | } 488 | }, 489 | 490 | toHaveHtml: function () { 491 | return { 492 | compare: function (actual, html) { 493 | return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) } 494 | } 495 | } 496 | }, 497 | 498 | toContainHtml: function () { 499 | return { 500 | compare: function (actual, html) { 501 | var actualHtml = $(actual).html() 502 | , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html) 503 | 504 | return { pass: (actualHtml.indexOf(expectedHtml) >= 0) } 505 | } 506 | } 507 | }, 508 | 509 | toHaveText: function () { 510 | return { 511 | compare: function (actual, text) { 512 | var actualText = $(actual).text() 513 | var trimmedText = $.trim(actualText) 514 | 515 | if (text && $.isFunction(text.test)) { 516 | return { pass: text.test(actualText) || text.test(trimmedText) } 517 | } else { 518 | return { pass: (actualText == text || trimmedText == text) } 519 | } 520 | } 521 | } 522 | }, 523 | 524 | toContainText: function () { 525 | return { 526 | compare: function (actual, text) { 527 | var trimmedText = $.trim($(actual).text()) 528 | 529 | if (text && $.isFunction(text.test)) { 530 | return { pass: text.test(trimmedText) } 531 | } else { 532 | return { pass: trimmedText.indexOf(text) != -1 } 533 | } 534 | } 535 | } 536 | }, 537 | 538 | toHaveValue: function () { 539 | return { 540 | compare: function (actual, value) { 541 | return { pass: $(actual).val() === value } 542 | } 543 | } 544 | }, 545 | 546 | toHaveData: function () { 547 | return { 548 | compare: function (actual, key, expectedValue) { 549 | return { pass: hasProperty($(actual).data(key), expectedValue) } 550 | } 551 | } 552 | }, 553 | 554 | toContainElement: function () { 555 | return { 556 | compare: function (actual, selector) { 557 | return { pass: $(actual).find(selector).length } 558 | } 559 | } 560 | }, 561 | 562 | toBeMatchedBy: function () { 563 | return { 564 | compare: function (actual, selector) { 565 | return { pass: $(actual).filter(selector).length } 566 | } 567 | } 568 | }, 569 | 570 | toBeDisabled: function () { 571 | return { 572 | compare: function (actual, selector) { 573 | return { pass: $(actual).is(':disabled') } 574 | } 575 | } 576 | }, 577 | 578 | toBeFocused: function (selector) { 579 | return { 580 | compare: function (actual, selector) { 581 | return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement } 582 | } 583 | } 584 | }, 585 | 586 | toHandle: function () { 587 | return { 588 | compare: function (actual, event) { 589 | if ( !actual || actual.length === 0 ) return { pass: false }; 590 | var events = $._data($(actual).get(0), "events") 591 | 592 | if (!events || !event || typeof event !== "string") { 593 | return { pass: false } 594 | } 595 | 596 | var namespaces = event.split(".") 597 | , eventType = namespaces.shift() 598 | , sortedNamespaces = namespaces.slice(0).sort() 599 | , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") 600 | 601 | if (events[eventType] && namespaces.length) { 602 | for (var i = 0; i < events[eventType].length; i++) { 603 | var namespace = events[eventType][i].namespace 604 | 605 | if (namespaceRegExp.test(namespace)) 606 | return { pass: true } 607 | } 608 | } else { 609 | return { pass: (events[eventType] && events[eventType].length > 0) } 610 | } 611 | 612 | return { pass: false } 613 | } 614 | } 615 | }, 616 | 617 | toHandleWith: function () { 618 | return { 619 | compare: function (actual, eventName, eventHandler) { 620 | if ( !actual || actual.length === 0 ) return { pass: false }; 621 | var normalizedEventName = eventName.split('.')[0] 622 | , stack = $._data($(actual).get(0), "events")[normalizedEventName] 623 | 624 | for (var i = 0; i < stack.length; i++) { 625 | if (stack[i].handler == eventHandler) return { pass: true } 626 | } 627 | 628 | return { pass: false } 629 | } 630 | } 631 | }, 632 | 633 | toHaveBeenTriggeredOn: function () { 634 | return { 635 | compare: function (actual, selector) { 636 | var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) } 637 | 638 | result.message = result.pass ? 639 | "Expected event " + $(actual) + " not to have been triggered on " + selector : 640 | "Expected event " + $(actual) + " to have been triggered on " + selector 641 | 642 | return result; 643 | } 644 | } 645 | }, 646 | 647 | toHaveBeenTriggered: function (){ 648 | return { 649 | compare: function (actual) { 650 | var eventName = actual.eventName 651 | , selector = actual.selector 652 | , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) } 653 | 654 | result.message = result.pass ? 655 | "Expected event " + eventName + " not to have been triggered on " + selector : 656 | "Expected event " + eventName + " to have been triggered on " + selector 657 | 658 | return result 659 | } 660 | } 661 | }, 662 | 663 | toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) { 664 | return { 665 | compare: function (actual, selector, expectedArgs) { 666 | var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual) 667 | , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) } 668 | 669 | if (wasTriggered) { 670 | var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] 671 | result.message = result.pass ? 672 | "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : 673 | "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) 674 | 675 | } else { 676 | // todo check on this 677 | result.message = result.pass ? 678 | "Expected event " + actual + " not to have been triggered on " + selector : 679 | "Expected event " + actual + " to have been triggered on " + selector 680 | } 681 | 682 | return result 683 | } 684 | } 685 | }, 686 | 687 | toHaveBeenPreventedOn: function () { 688 | return { 689 | compare: function (actual, selector) { 690 | var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) } 691 | 692 | result.message = result.pass ? 693 | "Expected event " + actual + " not to have been prevented on " + selector : 694 | "Expected event " + actual + " to have been prevented on " + selector 695 | 696 | return result 697 | } 698 | } 699 | }, 700 | 701 | toHaveBeenPrevented: function () { 702 | return { 703 | compare: function (actual) { 704 | var eventName = actual.eventName 705 | , selector = actual.selector 706 | , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) } 707 | 708 | result.message = result.pass ? 709 | "Expected event " + eventName + " not to have been prevented on " + selector : 710 | "Expected event " + eventName + " to have been prevented on " + selector 711 | 712 | return result 713 | } 714 | } 715 | }, 716 | 717 | toHaveBeenStoppedOn: function () { 718 | return { 719 | compare: function (actual, selector) { 720 | var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) } 721 | 722 | result.message = result.pass ? 723 | "Expected event " + actual + " not to have been stopped on " + selector : 724 | "Expected event " + actual + " to have been stopped on " + selector 725 | 726 | return result; 727 | } 728 | } 729 | }, 730 | 731 | toHaveBeenStopped: function () { 732 | return { 733 | compare: function (actual) { 734 | var eventName = actual.eventName 735 | , selector = actual.selector 736 | , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) } 737 | 738 | result.message = result.pass ? 739 | "Expected event " + eventName + " not to have been stopped on " + selector : 740 | "Expected event " + eventName + " to have been stopped on " + selector 741 | 742 | return result 743 | } 744 | } 745 | } 746 | }) 747 | 748 | jasmine.getEnv().addCustomEqualityTester(function(a, b) { 749 | if (a && b) { 750 | if (a instanceof $ || jasmine.isDomNode(a)) { 751 | var $a = $(a) 752 | 753 | if (b instanceof $) 754 | return $a.length == b.length && a.is(b) 755 | 756 | return $a.is(b); 757 | } 758 | 759 | if (b instanceof $ || jasmine.isDomNode(b)) { 760 | var $b = $(b) 761 | 762 | if (a instanceof $) 763 | return a.length == $b.length && $b.is(a) 764 | 765 | return $(b).is(a); 766 | } 767 | } 768 | }) 769 | 770 | jasmine.getEnv().addCustomEqualityTester(function (a, b) { 771 | if (a instanceof $ && b instanceof $ && a.size() == b.size()) 772 | return a.is(b) 773 | }) 774 | }) 775 | 776 | afterEach(function () { 777 | jasmine.getFixtures().cleanUp() 778 | jasmine.getStyleFixtures().cleanUp() 779 | jasmine.jQuery.events.cleanUp() 780 | }) 781 | 782 | window.readFixtures = function () { 783 | return jasmine.getFixtures().proxyCallTo_('read', arguments) 784 | } 785 | 786 | window.preloadFixtures = function () { 787 | jasmine.getFixtures().proxyCallTo_('preload', arguments) 788 | } 789 | 790 | window.loadFixtures = function () { 791 | jasmine.getFixtures().proxyCallTo_('load', arguments) 792 | } 793 | 794 | window.appendLoadFixtures = function () { 795 | jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) 796 | } 797 | 798 | window.setFixtures = function (html) { 799 | return jasmine.getFixtures().proxyCallTo_('set', arguments) 800 | } 801 | 802 | window.appendSetFixtures = function () { 803 | jasmine.getFixtures().proxyCallTo_('appendSet', arguments) 804 | } 805 | 806 | window.sandbox = function (attributes) { 807 | return jasmine.getFixtures().sandbox(attributes) 808 | } 809 | 810 | window.spyOnEvent = function (selector, eventName) { 811 | return jasmine.jQuery.events.spyOn(selector, eventName) 812 | } 813 | 814 | window.preloadStyleFixtures = function () { 815 | jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) 816 | } 817 | 818 | window.loadStyleFixtures = function () { 819 | jasmine.getStyleFixtures().proxyCallTo_('load', arguments) 820 | } 821 | 822 | window.appendLoadStyleFixtures = function () { 823 | jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) 824 | } 825 | 826 | window.setStyleFixtures = function (html) { 827 | jasmine.getStyleFixtures().proxyCallTo_('set', arguments) 828 | } 829 | 830 | window.appendSetStyleFixtures = function (html) { 831 | jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) 832 | } 833 | 834 | window.loadJSONFixtures = function () { 835 | return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) 836 | } 837 | 838 | window.getJSONFixture = function (url) { 839 | return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] 840 | } 841 | })); 842 | -------------------------------------------------------------------------------- /themes/basic.scss: -------------------------------------------------------------------------------- 1 | #skitt-ui { 2 | display: block!important; 3 | } 4 | #skitt-ui.skitt-ui--hidden { 5 | display: none !important; 6 | } 7 | -------------------------------------------------------------------------------- /themes/flat-amethyst/flat-amethyst.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #8E44AD !default; 4 | $buttonColor2: #9B59B6 !default; 5 | $listeningBoxColor: #8E44AD !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-clouds/flat-clouds.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #BDC3C7 !default; 4 | $buttonColor2: #ECF0F1 !default; 5 | $listeningBoxColor: #ECF0F1 !default; 6 | $instructionColor: #333 !default; 7 | 8 | @import '../flat/flat.scss'; 9 | -------------------------------------------------------------------------------- /themes/flat-concrete/flat-concrete.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #95A5A6 !default; 4 | $buttonColor2: #7F8C8D !default; 5 | $listeningBoxColor: #7F8C8D !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-emerald/flat-emerald.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #27AE60 !default; 4 | $buttonColor2: #2ECC71 !default; 5 | $listeningBoxColor: #27AE60 !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-midnight-blue/flat-midnight-blue.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #2C3E50 !default; 4 | $buttonColor2: #34495E !default; 5 | $listeningBoxColor: #2C3E50 !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-orange/flat-orange.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #F39C12 !default; 4 | $buttonColor2: #F1C40F !default; 5 | $listeningBoxColor: #F39C12 !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-pomegranate/flat-pomegranate.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #C0392B !default; 4 | $buttonColor2: #E74C3C !default; 5 | $listeningBoxColor: #C0392B !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-pumpkin/flat-pumpkin.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #D35400 !default; 4 | $buttonColor2: #E67E22 !default; 5 | $listeningBoxColor: #D35400 !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat-turquoise/flat-turquoise.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | $buttonColor1: #16A085 !default; 4 | $buttonColor2: #1ABC9C !default; 5 | $listeningBoxColor: #16A085 !default; 6 | 7 | @import '../flat/flat.scss'; 8 | -------------------------------------------------------------------------------- /themes/flat/flat.scss: -------------------------------------------------------------------------------- 1 | @import '../basic'; 2 | 3 | /* Variables */ 4 | 5 | $toggleButtonWidth: 50px !default; 6 | $toggleButtonHeight: 50px !default; 7 | $buttonColor1: #2980B9 !default; 8 | $buttonColor2: #3498DB !default; 9 | $listeningBoxColor: #2980B9 !default; 10 | $instructionColor: #fff !default; 11 | 12 | /* Theme styles */ 13 | 14 | #skitt-ui { 15 | height: $toggleButtonHeight; 16 | display: inline-block; 17 | background-color: $listeningBoxColor; 18 | z-index: 200; 19 | border-radius: $toggleButtonWidth / 2; 20 | position: fixed; 21 | bottom: 20px; 22 | left: 20px; 23 | outline: none; 24 | border: none; 25 | box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 8px; 26 | cursor: default; 27 | font-family: Lato,Helvetica,Arial,sans-serif; 28 | font-size: 16px; 29 | } 30 | 31 | #skitt-toggle-button { 32 | width: $toggleButtonWidth; 33 | height: $toggleButtonHeight; 34 | border-radius: 50%; 35 | cursor: pointer; 36 | display: inline-block; 37 | background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMSBUaW55Ly9FTicgICdodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS10aW55LmR0ZCc+PHN2ZyBiYXNlUHJvZmlsZT0idGlueSIgaGVpZ2h0PSIzMnB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJHdWlkZXNfX3gyNl9fRm9ybXMiLz48ZyBpZD0iSWNvbnMiPjxnPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMTYsMjFjMi4yMDksMCw0LTEuNzkxLDQtNHYtN2MwLTIuMjA5LTEuNzkxLTQtNC00Yy0yLjIwOSwwLTQsMS43OTEtNCw0djdDMTIsMTkuMjA5LDEzLjc5MSwyMSwxNiwyMXogTTE0LDEwICAgIGMwLTEuMTAzLDAuODk3LTIsMi0yYzEuMTAzLDAsMiwwLjg5NywyLDJ2N2MwLDEuMTAzLTAuODk3LDItMiwyYy0xLjEwMywwLTItMC44OTctMi0yVjEweiIvPjxwYXRoIGZpbGw9IndoaXRlIiBkPSJNMjQsMTdoLTJjMCwzLjMwOC0yLjY5Miw2LTYsNnMtNi0yLjY5Mi02LTZIOGMwLDQuMDc5LDMuMDU1LDcuNDM4LDcsNy45MzFWMjZoLTR2MmgxMHYtMmgtNHYtMS4wNjkgICAgQzIwLjk0NSwyNC40MzgsMjQsMjEuMDc5LDI0LDE3eiIvPjwvZz48L2c+PC9zdmc+'); 38 | background-size: 72% 72%; 39 | background-position: $toggleButtonHeight * 0.14 $toggleButtonWidth * 0.12; 40 | background-repeat: no-repeat; 41 | -webkit-transition: background-color 400ms ease; 42 | float: left; 43 | } 44 | 45 | label#skitt-toggle-button__label { 46 | display: none; 47 | } 48 | 49 | .skitt-ui--not-listening #skitt-toggle-button { 50 | background-color: $buttonColor1; 51 | } 52 | 53 | .skitt-ui--listening #skitt-toggle-button { 54 | -webkit-animation: listen_pulse 2s ease-out infinite; 55 | } 56 | 57 | @-webkit-keyframes "listen_pulse" { 58 | 0% { 59 | background-color: $buttonColor1; 60 | } 61 | 50% { 62 | background-color: $buttonColor2; 63 | } 64 | 100% { 65 | background-color: $buttonColor1; 66 | } 67 | } 68 | 69 | .skitt-ui--not-listening #skitt-toggle-button:hover { 70 | background-color: $buttonColor2 71 | } 72 | .skitt-ui--listening #skitt-toggle-button:hover { 73 | background-color: $buttonColor2 74 | } 75 | 76 | #skitt-listening-box { 77 | float: left; 78 | display: inline-block; 79 | line-height: $toggleButtonHeight; 80 | color: $instructionColor; 81 | } 82 | 83 | #skitt-listening-text { 84 | display: inline-block; 85 | overflow: hidden; 86 | } 87 | .skitt-ui--not-listening #skitt-listening-text { 88 | width: 0; 89 | } 90 | .skitt-ui--listening #skitt-listening-text { 91 | width: 100%; 92 | -webkit-transition: width 1s ease-in-out; 93 | margin: 0 $toggleButtonWidth/2 0 15px; 94 | } 95 | 96 | #skitt-listening-text__samples { 97 | font-weight: bold; 98 | margin-left: 10px; 99 | } 100 | 101 | #skitt-listening-text__recognized-sentence { 102 | display: none; 103 | } 104 | @media (max-width: 1200px) and (orientation: portrait) { 105 | $sizeMultipliers: 2.5; 106 | #skitt-ui { 107 | border-radius: $toggleButtonWidth * $sizeMultipliers / 2; 108 | font-size: 35px; 109 | height: $toggleButtonHeight * $sizeMultipliers; 110 | } 111 | #skitt-toggle-button { 112 | width: $toggleButtonWidth * $sizeMultipliers; 113 | height: $toggleButtonHeight * $sizeMultipliers; 114 | background-position: $toggleButtonHeight * $sizeMultipliers * 0.14 $toggleButtonWidth * $sizeMultipliers * 0.12; 115 | } 116 | #skitt-listening-box { 117 | line-height: $toggleButtonHeight * $sizeMultipliers; 118 | } 119 | } 120 | 121 | @media (max-width: 1200px) and (orientation: landscape) { 122 | $sizeMultipliers: 1.6; 123 | #skitt-ui { 124 | border-radius: $toggleButtonWidth * $sizeMultipliers / 2; 125 | font-size: 25px; 126 | height: $toggleButtonHeight * $sizeMultipliers; 127 | } 128 | #skitt-toggle-button { 129 | width: $toggleButtonWidth * $sizeMultipliers; 130 | height: $toggleButtonHeight * $sizeMultipliers; 131 | background-position: $toggleButtonHeight * $sizeMultipliers * 0.14 $toggleButtonWidth * $sizeMultipliers * 0.12; 132 | } 133 | #skitt-listening-box { 134 | line-height: $toggleButtonHeight * $sizeMultipliers; 135 | } 136 | } 137 | --------------------------------------------------------------------------------