├── icon.png ├── interval-timer.png ├── README.md ├── app.manifest ├── manifest.json ├── images ├── stop.svg ├── play.svg ├── start.svg ├── pause.svg ├── share.svg ├── reset.svg └── octocat.svg ├── 3rdparty └── NoSleep.min.js ├── index.html └── interval-timer.js /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greggman/interval-timer/HEAD/icon.png -------------------------------------------------------------------------------- /interval-timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greggman/interval-timer/HEAD/interval-timer.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interval Timer 2 | 3 | [Click Here](https://greggman.github.io/interval-timer/) 4 | 5 | A simple interval timer. Settings are saved in the URL so set them to whatever 6 | you want and then make a bookmark. 7 | 8 | ## TO DO 9 | 10 | * Localize? 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app.manifest: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | 3 | # version 7 4 | 5 | manifest.json 6 | icon.png 7 | images/reset.svg 8 | images/stop.svg 9 | images/start.svg 10 | images/play.svg 11 | images/share.svg 12 | images/pause.svg 13 | images/octocat.svg 14 | interval-timer.js 15 | 3rdparty/NoSleep.min.js 16 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Interval Timer", 3 | "name": "Interval Timer", 4 | "icons": [ 5 | { 6 | "src": "icon.png", 7 | "type": "image/png", 8 | "sizes": "128x128" 9 | } 10 | ], 11 | "start_url": "index.html", 12 | "background_color": "#00C", 13 | "theme_color": "#00C", 14 | "display": "standalone" 15 | } 16 | -------------------------------------------------------------------------------- /images/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /images/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/octocat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /3rdparty/NoSleep.min.js: -------------------------------------------------------------------------------- 1 | /*! NoSleep.js v0.7.0 - git.io/vfn01 - Rich Tibbett - MIT license */ 2 | (function webpackUniversalModuleDefinition(root, factory) { 3 | if(typeof exports === 'object' && typeof module === 'object') 4 | module.exports = factory(); 5 | else if(typeof define === 'function' && define.amd) 6 | define([], factory); 7 | else if(typeof exports === 'object') 8 | exports["NoSleep"] = factory(); 9 | else 10 | root["NoSleep"] = factory(); 11 | })(this, function() { 12 | return /******/ (function(modules) { // webpackBootstrap 13 | /******/ // The module cache 14 | /******/ var installedModules = {}; 15 | /******/ 16 | /******/ // The require function 17 | /******/ function __webpack_require__(moduleId) { 18 | /******/ 19 | /******/ // Check if module is in cache 20 | /******/ if(installedModules[moduleId]) { 21 | /******/ return installedModules[moduleId].exports; 22 | /******/ } 23 | /******/ // Create a new module (and put it into the cache) 24 | /******/ var module = installedModules[moduleId] = { 25 | /******/ i: moduleId, 26 | /******/ l: false, 27 | /******/ exports: {} 28 | /******/ }; 29 | /******/ 30 | /******/ // Execute the module function 31 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 32 | /******/ 33 | /******/ // Flag the module as loaded 34 | /******/ module.l = true; 35 | /******/ 36 | /******/ // Return the exports of the module 37 | /******/ return module.exports; 38 | /******/ } 39 | /******/ 40 | /******/ 41 | /******/ // expose the modules object (__webpack_modules__) 42 | /******/ __webpack_require__.m = modules; 43 | /******/ 44 | /******/ // expose the module cache 45 | /******/ __webpack_require__.c = installedModules; 46 | /******/ 47 | /******/ // define getter function for harmony exports 48 | /******/ __webpack_require__.d = function(exports, name, getter) { 49 | /******/ if(!__webpack_require__.o(exports, name)) { 50 | /******/ Object.defineProperty(exports, name, { 51 | /******/ configurable: false, 52 | /******/ enumerable: true, 53 | /******/ get: getter 54 | /******/ }); 55 | /******/ } 56 | /******/ }; 57 | /******/ 58 | /******/ // getDefaultExport function for compatibility with non-harmony modules 59 | /******/ __webpack_require__.n = function(module) { 60 | /******/ var getter = module && module.__esModule ? 61 | /******/ function getDefault() { return module['default']; } : 62 | /******/ function getModuleExports() { return module; }; 63 | /******/ __webpack_require__.d(getter, 'a', getter); 64 | /******/ return getter; 65 | /******/ }; 66 | /******/ 67 | /******/ // Object.prototype.hasOwnProperty.call 68 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 69 | /******/ 70 | /******/ // __webpack_public_path__ 71 | /******/ __webpack_require__.p = ""; 72 | /******/ 73 | /******/ // Load entry module and return exports 74 | /******/ return __webpack_require__(__webpack_require__.s = 0); 75 | /******/ }) 76 | /************************************************************************/ 77 | /******/ ([ 78 | /* 0 */ 79 | /***/ (function(module, exports, __webpack_require__) { 80 | 81 | "use strict"; 82 | 83 | 84 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 85 | 86 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 87 | 88 | var mediaFile = __webpack_require__(1); 89 | 90 | // Detect iOS browsers < version 10 91 | var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream; 92 | 93 | var NoSleep = function () { 94 | function NoSleep() { 95 | _classCallCheck(this, NoSleep); 96 | 97 | if (oldIOS) { 98 | this.noSleepTimer = null; 99 | } else { 100 | // Set up no sleep video element 101 | this.noSleepVideo = document.createElement('video'); 102 | 103 | this.noSleepVideo.setAttribute('muted', true); 104 | this.noSleepVideo.setAttribute('playsinline', ''); 105 | this.noSleepVideo.setAttribute('src', mediaFile); 106 | 107 | this.noSleepVideo.addEventListener('timeupdate', function (e) { 108 | if (this.noSleepVideo.currentTime > 0.5) { 109 | this.noSleepVideo.currentTime = Math.random(); 110 | } 111 | }.bind(this)); 112 | } 113 | } 114 | 115 | _createClass(NoSleep, [{ 116 | key: 'enable', 117 | value: function enable() { 118 | if (oldIOS) { 119 | this.disable(); 120 | this.noSleepTimer = window.setInterval(function () { 121 | window.location.href = '/'; 122 | window.setTimeout(window.stop, 0); 123 | }, 15000); 124 | } else { 125 | this.noSleepVideo.play(); 126 | } 127 | } 128 | }, { 129 | key: 'disable', 130 | value: function disable() { 131 | if (oldIOS) { 132 | if (this.noSleepTimer) { 133 | window.clearInterval(this.noSleepTimer); 134 | this.noSleepTimer = null; 135 | } 136 | } else { 137 | this.noSleepVideo.pause(); 138 | } 139 | } 140 | }]); 141 | 142 | return NoSleep; 143 | }(); 144 | 145 | ; 146 | 147 | module.exports = NoSleep; 148 | 149 | /***/ }), 150 | /* 1 */ 151 | /***/ (function(module, exports, __webpack_require__) { 152 | 153 | "use strict"; 154 | 155 | 156 | module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA='; 157 | 158 | /***/ }) 159 | /******/ ]); 160 | }); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Interval Timer 31 | 32 | 33 | 34 | 453 | 454 | 455 |
456 |
457 |
⚙ Settings
458 |
About
459 |
460 |
461 |
462 |
463 |
464 |
465 | 466 | 467 | 00:00 468 | 469 | 470 |
471 |
472 |
473 |
474 |
elapsed
475 |
00:00
476 |
477 |
478 |
interval
479 |
0/0
480 |
481 |
482 |
remaining
483 |
00:00
484 |
485 |
486 |
487 | 492 |
493 |
494 |
495 |
496 |
497 | 498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 | 509 |
510 | 513 |
514 |
515 | 516 |
517 | 523 | 542 | 543 | 544 | 545 | 1010 | 1011 | -------------------------------------------------------------------------------- /interval-timer.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { 40 | /******/ configurable: false, 41 | /******/ enumerable: true, 42 | /******/ get: getter 43 | /******/ }); 44 | /******/ } 45 | /******/ }; 46 | /******/ 47 | /******/ // getDefaultExport function for compatibility with non-harmony modules 48 | /******/ __webpack_require__.n = function(module) { 49 | /******/ var getter = module && module.__esModule ? 50 | /******/ function getDefault() { return module['default']; } : 51 | /******/ function getModuleExports() { return module; }; 52 | /******/ __webpack_require__.d(getter, 'a', getter); 53 | /******/ return getter; 54 | /******/ }; 55 | /******/ 56 | /******/ // Object.prototype.hasOwnProperty.call 57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 | /******/ 59 | /******/ // __webpack_public_path__ 60 | /******/ __webpack_require__.p = ""; 61 | /******/ 62 | /******/ // Load entry module and return exports 63 | /******/ return __webpack_require__(__webpack_require__.s = 1); 64 | /******/ }) 65 | /************************************************************************/ 66 | /******/ ([ 67 | /* 0 */ 68 | /***/ (function(module, exports, __webpack_require__) { 69 | 70 | "use strict"; 71 | var __WEBPACK_AMD_DEFINE_RESULT__; 72 | 73 | !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { 74 | var audio = {}; 75 | (function(samplerate){ 76 | this.SampleRate = samplerate || 44100; 77 | var SampleRate = this.SampleRate; 78 | 79 | // Do not modify parameters without changing code! 80 | var BitsPerSample = 16; 81 | var NumChannels = 1; 82 | var BlockAlign = NumChannels * BitsPerSample >> 3; 83 | var ByteRate = SampleRate * BlockAlign; 84 | 85 | // helper functions 86 | var chr = String.fromCharCode; // alias for getting converting int to char 87 | 88 | ////////////////////// 89 | // Wave /// 90 | ////////////////////// 91 | 92 | var waveTag="data:audio/wav;base64,"; 93 | // constructs a wave from sample array 94 | var constructWave = function(data){ 95 | var l; 96 | return pack( ["RIFF",36+(l=data.length),"WAVEfmt ",16,1,NumChannels,SampleRate, 97 | ByteRate,BlockAlign,BitsPerSample,"data",l,data],"s4s4224422s4s"); 98 | }; 99 | 100 | // creates an audio object from sample data 101 | this.make = function(arr){ 102 | return new Audio(waveTag + btoa(constructWave(arrayToData(arr)))) 103 | }; 104 | 105 | // creates a wave file for downloading 106 | this.makeWaveFile = function(arr){ 107 | dataToFile(waveTag + btoa(constructWave(arrayToData(arr)))) 108 | }; 109 | 110 | this.makeAudioBuffer = function(ctx, data) { 111 | var buffer = ctx.createBuffer(1, data.length, SampleRate); 112 | var array = buffer.getChannelData(0); 113 | for (var i = 0; i < data.length; ++i) { 114 | array[i] = data[i]; 115 | } 116 | return buffer; 117 | }; 118 | 119 | ////////////////////// 120 | // General stuff /// 121 | ////////////////////// 122 | 123 | // Converts an integer to String representation 124 | // a - number 125 | // i - number of bytes 126 | var istr = function(a,i){ 127 | var m8 = 0xff; // 8 bit mask 128 | return i?chr(a&m8)+istr(a>>8,i-1):""; 129 | }; 130 | 131 | // Packs array of data to a string 132 | // data - array 133 | // format - s is for string, numbers denote bytes to store in 134 | var pack = function(data,format){ 135 | var out=""; 136 | for(i=0;i> 8); 172 | }; 173 | return out; 174 | } 175 | 176 | var arrayToData8bit = function(arr){ 177 | var out=""; 178 | var len = arr.length; 179 | for( i=0 ; i < len ; i++){ 180 | var a = (arr[i] * 127 + 128) | 0; 181 | a = a < 0 ? 0 : 255 < a ? 255 : a; 182 | out += String.fromCharCode(a); 183 | }; 184 | return out; 185 | } 186 | 187 | var arrayToData = function(arr){ 188 | if( BitsPerSample == 16 ) 189 | return arrayToData16bit(arr); 190 | else 191 | return arrayToData8bit(arr); 192 | } 193 | 194 | ////////////////////// 195 | // Processing 196 | ////////////////////// 197 | 198 | // adjusts volume of a buffer 199 | this.adjustVolume = function(data, v){ 200 | for(i=0;i A ? 1.0 : sin(phase) < A ? -1.0 : A} 269 | }; 270 | var generators = this.generators; 271 | 272 | this.g = { 273 | noise : function(count){ return generate(count,0, generators.noise) }, 274 | sine : function(count, freq){ return generate(count, freq, generators.sine) }, 275 | synth : function(count, freq){ return generate(count, freq, generators.synth) }, 276 | saw : function(count, freq){ return generate(count, freq, generators.saw) }, 277 | square : function(count, freq, A){ return generate(count, freq, generators.square, A) } 278 | }; 279 | }).apply(audio); 280 | 281 | return audio; 282 | }).call(exports, __webpack_require__, exports, module), 283 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 284 | 285 | 286 | /***/ }), 287 | /* 1 */ 288 | /***/ (function(module, exports, __webpack_require__) { 289 | 290 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ 291 | __webpack_require__(2), 292 | ], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( 293 | AudioManager 294 | ) { 295 | window.AudioManager = AudioManager; 296 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 297 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 298 | 299 | 300 | 301 | /***/ }), 302 | /* 2 */ 303 | /***/ (function(module, exports, __webpack_require__) { 304 | 305 | "use strict"; 306 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* 307 | * Copyright 2014, Gregg Tavares. 308 | * All rights reserved. 309 | * 310 | * Redistribution and use in source and binary forms, with or without 311 | * modification, are permitted provided that the following conditions are 312 | * met: 313 | * 314 | * * Redistributions of source code must retain the above copyright 315 | * notice, this list of conditions and the following disclaimer. 316 | * * Redistributions in binary form must reproduce the above 317 | * copyright notice, this list of conditions and the following disclaimer 318 | * in the documentation and/or other materials provided with the 319 | * distribution. 320 | * * Neither the name of Gregg Tavares. nor the names of its 321 | * contributors may be used to endorse or promote products derived from 322 | * this software without specific prior written permission. 323 | * 324 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 325 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 326 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 328 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 329 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 330 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 331 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 333 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 334 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 335 | */ 336 | 337 | 338 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ 339 | __webpack_require__(3), 340 | __webpack_require__(5) 341 | ], __WEBPACK_AMD_DEFINE_RESULT__ = (function( 342 | jsfxlib, 343 | EventEmitter) { 344 | 345 | var webAudioAPI = window.AudioContext || window.webkitAudioContext || window.mozAudioContext; 346 | 347 | /** 348 | * @typedef {Object} AudioManager~Options 349 | * @property {callback} startedOnTouchCallback: **DEPREICATED** 350 | * Use `mgr.on(`started`) 351 | * 352 | * @property {callback} callback: **DEPRECATED** use 353 | * mgr.on('loaded'). 354 | */ 355 | 356 | /** 357 | * This can either be a path to a file OR jsfx data for sounds 358 | * generated at runtime. Example: 359 | * 360 | * var sounds = { 361 | * coin: { jsfx: ["square",0.0000,0.4000,0.0000,0.0240,0.4080,0.3480,20.0000,909.0000,2400.0000,0.0000,0.0000,0.0000,0.0100,0.0003,0.0000,0.2540,0.1090,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000], }, 362 | * jump: { jsfx: ["square",0.0000,0.4000,0.0000,0.0960,0.0000,0.1720,20.0000,245.0000,2400.0000,0.3500,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.5000,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000], }, 363 | * fire: { filename: "assets/fire.ogg", samples: 8, }, 364 | * boom: { filename: "assets/explosion.ogg", samples: 8, }, 365 | * }; 366 | * 367 | * 368 | * Note Firefox doesn't support MP3s as far as I know so you'll need 369 | * to supply .ogg files for it. Conversely, Safari doesn't support .ogg. 370 | * The library handles loading .mp3 or .ogg files regardless of what you specify 371 | * when you init the library. In other words if you put `filename: "foo.mp3"` 372 | * the library will try to load `foo.mp3` or `foo.ogg` depending on if the 373 | * browser supports one or the other. 374 | * 375 | * @typedef {Object} AudioManager~Sound 376 | * @property {string?} filename path to the file to load 377 | * @property {number?} samples How many of this sound can play 378 | * simultainously. Note: this is NOT needed when using 379 | * the Web Audio API. It is only needed for legacy 380 | * browsers like IE11 and below. 381 | * @property {Array?} jsfx Data from jsfx. See http://egonelbre.com/project/jsfx/ 382 | */ 383 | 384 | /** 385 | * To use this include it with 386 | * 387 | * 388 | * 389 | * Then give it a list of sounds like this 390 | * 391 | * var audioMgr = new AudioManager({ 392 | * fire: { filename: "assets/fire.ogg", samples: 8, }, 393 | * explosion: { filename: "assets/explosion.ogg", samples: 6, }, 394 | * hitshield: { filename: "assets/hitshield.ogg", samples: 6, }, 395 | * launch: { filename: "assets/launch.ogg", samples: 2, }, 396 | * gameover: { filename: "assets/gameover.ogg", samples: 1, }, 397 | * play: { filename: "assets/play.ogg", samples: 1, }, 398 | * }); 399 | * 400 | * After that you can play sounds with 401 | * 402 | * audioMgr.playSound('explosion'); 403 | * audioMgr.playSound('fire'); 404 | * 405 | * The signature for `playSound` is 406 | * `playSound(name, when, loop)` where when is the time to play 407 | * the sound and loop is whether or not to play the sound 408 | * continuously in a loop. 409 | * 410 | * Playsound returns an object you can use to control the sound 411 | * though this part of the API is still in flux. 412 | * 413 | * `samples` is how may of that sound you want to be able to play at 414 | * the same time. THIS IS NOT NEEDED for any browser that supports the 415 | * Web Audio API. In other words it's only needed for IE. 416 | * 417 | * Also note Firefox doesn't support MP3s as far as I know so you'll need 418 | * to supply .ogg files for it. Conversely, Safari doesn't support .ogg. 419 | * The library handles loading .mp3 or .ogg files regardless of what you specify 420 | * when you init the library. In other words if you put `filename: "foo.mp3"` 421 | * the library will try to load `foo.mp3` or `foo.ogg` depending on if the 422 | * browser supports one or the other. 423 | * 424 | * @constructor 425 | * @param {Object(string:AudioManager~Sound}} sounds The sounds 426 | * to load 427 | * @param {AudioManager~Options} options Options 428 | * @fires AudioManager#loaded when all sounds have loaded 429 | * @fires AudioManager#started when the first sound has played. 430 | * On iOS no sounds can be played unless at least one is 431 | * first initiated during a use gesture event. This event 432 | * is useful for situtations where sounds 'should' start 433 | * right from the beginning even if the player as not 434 | * touched the screen. For exampme we might put up a 435 | * message, "touch the screen" and remove that message 436 | * when we get this event 437 | */ 438 | var AudioManager = function(sounds, options) { 439 | options = options || {}; 440 | var g_eventEmitter = new EventEmitter(); 441 | var g_context; 442 | var g_audioMgr; 443 | var g_soundBank = {}; 444 | var g_canPlay = false; 445 | var g_canPlayOgg; 446 | var g_canPlayMp3; 447 | var g_canPlayWav; 448 | var g_canPlayAif; 449 | var g_createFromFileFn; 450 | var g_createFromJSFXFn; 451 | 452 | var changeExt = function(filename, ext) { 453 | return filename.substring(0, filename.length - 3) + ext; 454 | }; 455 | 456 | this.needUserGesture = function() { 457 | return true; 458 | }; 459 | 460 | this.on = g_eventEmitter.on.bind(g_eventEmitter); 461 | this.addListener = this.on; 462 | this.addEventListener = this.on; 463 | this.removeListener = g_eventEmitter.removeListener.bind(g_eventEmitter); 464 | this.removeEventListener = this.removeListener; 465 | 466 | if (options.callback) { 467 | console.warn("AudioManager: options.callback is deprecated. Use mgr.on('loaded', ...)"); 468 | this.on('loaded', options.callback); 469 | } 470 | 471 | if (options.startedOnTouchCallback) { 472 | console.warn("AudioManager: options.startedOnTouchCallback is deprecated. Use mgr.on('started', ...)"); 473 | this.on('started', options.callback); 474 | } 475 | 476 | var WebAudioBuffer = function() { 477 | }; 478 | 479 | WebAudioBuffer.prototype.play = function(opt_when, opt_loop) { 480 | if (!this.buffer) { 481 | console.log(this.name, " not loaded"); 482 | return; 483 | } 484 | var src = g_context.createBufferSource(); 485 | src.buffer = this.buffer; 486 | src.loop = opt_loop || false; 487 | src.connect(g_context.destination); 488 | if (src.start) { 489 | src.start(opt_when || 0); 490 | } else { 491 | src.noteOn(opt_when || 0); 492 | } 493 | return src; 494 | }; 495 | 496 | var WebAudioJSFX = function(name, data, samples, opt_callback) { 497 | this.buffer = jsfxlib.createAudioBuffer(g_context, data); 498 | if (opt_callback) { 499 | setTimeout(opt_callback, 0); 500 | } 501 | }; 502 | 503 | WebAudioJSFX.prototype = new WebAudioBuffer(); 504 | 505 | function WebAudioSound(name, filename, samples, opt_callback) { 506 | this.name = name; 507 | var that = this; 508 | var req = new XMLHttpRequest(); 509 | req.open("GET", filename, true); 510 | req.responseType = "arraybuffer"; 511 | req.onload = function() { 512 | g_context.decodeAudioData(req.response, function onSuccess(decodedBuffer) { 513 | // Decoding was successful, do something useful with the audio buffer 514 | that.buffer = decodedBuffer; 515 | if (opt_callback) { 516 | opt_callback(false); 517 | } 518 | }, function onFailure() { 519 | console.error("failed to decoding audio buffer: " + filename); 520 | if (opt_callback) { 521 | opt_callback(true); 522 | } 523 | }); 524 | } 525 | req.addEventListener("error", function(e) { 526 | console.error("failed to load:", filename, " : ", e.target.status); 527 | }, false); 528 | req.send(); 529 | } 530 | 531 | WebAudioSound.prototype = new WebAudioBuffer(); 532 | 533 | var AudioTagJSFX = function(name, data, samples, opt_callback) { 534 | this.samples = samples || 1; 535 | this.audio = {}; 536 | this.playNdx = 0; 537 | for (var i = 0; i < samples; ++i) { 538 | this.audio[i] = jsfxlib.createWave(data); 539 | } 540 | if (opt_callback) { 541 | setTimeout(opt_callback, 0); 542 | } 543 | }; 544 | 545 | AudioTagJSFX.prototype.play = function(opt_when, opt_loop) { 546 | this.playNdx = (this.playNdx + 1) % this.samples; 547 | var a = this.audio[this.playNdx]; 548 | var b = new Audio(); 549 | b.src = a.src; 550 | // TODO: use when 551 | b.addEventListener("canplaythrough", function() { 552 | b.play(); 553 | }, false); 554 | b.load(); 555 | }; 556 | 557 | function AudioTagSound(name, filename, samples, opt_callback) { 558 | this.waiting_on_load = samples; 559 | this.samples = samples || 1; 560 | this.name = name; 561 | this.play_idx = 0; 562 | this.audio = {}; 563 | for (var i = 0; i < samples; i++) { 564 | var audio = new Audio(); 565 | var that = this; 566 | var checkCallback = function(err) { 567 | that.waiting_on_load--; 568 | if (opt_callback) { 569 | opt_callback(err); 570 | } 571 | }; 572 | audio.addEventListener("canplaythrough", function() { 573 | checkCallback(false); 574 | }, false); 575 | audio.src = filename; 576 | audio.onerror = function() { 577 | checkCallback(true); 578 | }; 579 | audio.load(); 580 | this.audio[i] = audio; 581 | } 582 | }; 583 | 584 | AudioTagSound.prototype.play = function(opt_when, opt_loop) { 585 | if (this.waiting_on_load > 0) { 586 | console.log(this.name, " not loaded"); 587 | return; 588 | } 589 | this.play_idx = (this.play_idx + 1) % this.samples; 590 | var a = this.audio[this.play_idx]; 591 | // console.log(this.name, ":", this.play_idx, ":", a.src); 592 | var b = new Audio(); 593 | b.src = a.src; 594 | // TODO: use when 595 | b.addEventListener("canplaythrough", function() { 596 | b.play(); 597 | }, false); 598 | b.load(); 599 | }; 600 | 601 | var handleError = function(filename, audio) { 602 | return function(e) { 603 | console.error("can't load ", filename); 604 | } 605 | }; 606 | 607 | this.playSound = function(name, opt_when, opt_loop) { 608 | if (!g_canPlay) 609 | return; 610 | var sound = g_soundBank[name]; 611 | if (!sound) { 612 | console.error("audio: '" + name + "' not known."); 613 | return; 614 | } 615 | return sound.play(opt_when, opt_loop); 616 | }.bind(this); 617 | 618 | this.getTime = function() { 619 | return g_context ? g_context.currentTime : Date.now() * 0.001; 620 | }.bind(this); 621 | 622 | // on iOS and possibly other devices you can't play any 623 | // sounds in the browser unless you first play a sound 624 | // in response to a user gesture. So, make something 625 | // to respond to a user gesture. 626 | var setupGesture = function() { 627 | if (this.needUserGesture()) { 628 | var count = 0; 629 | var elem = window; 630 | var that = this; 631 | var eventNames = ['touchstart', 'mousedown']; 632 | var playSoundToStartAudio = function() { 633 | ++count; 634 | if (count < 3) { 635 | // just playing any sound does not seem to work. 636 | var source = g_context.createOscillator(); 637 | var gain = g_context.createGain(); 638 | source.frequency.value = 1; 639 | source.connect(gain); 640 | gain.gain.value = 0; 641 | gain.connect(g_context.destination); 642 | if (source.start) { 643 | source.start(0); 644 | } else { 645 | source.noteOn(0); 646 | } 647 | setTimeout(function() { 648 | source.disconnect(); 649 | }, 100); 650 | } 651 | if (count == 3) { 652 | for (var ii = 0; ii < eventNames.length; ++ii) { 653 | elem.removeEventListener(eventNames[ii], playSoundToStartAudio, false); 654 | } 655 | g_eventEmitter.emit('started'); 656 | } 657 | } 658 | 659 | for (var ii = 0; ii < eventNames.length; ++ii) { 660 | elem.addEventListener(eventNames[ii], playSoundToStartAudio, false); 661 | } 662 | } 663 | }.bind(this); 664 | 665 | this.loadSound = function(soundName, filename, samples, opt_callback) { 666 | var ext = filename.substring(filename.length - 3); 667 | if (ext == 'ogg' && !g_canPlayOgg) { 668 | filename = changeExt(filename, "mp3"); 669 | } else if (ext == 'mp3' && !g_canPlayMp3) { 670 | filename = changeExt(filename, "ogg"); 671 | } 672 | var s = new g_createFromFileFn(soundName, filename, samples, opt_callback); 673 | g_soundBank[soundName] = s; 674 | return s; 675 | }.bind(this); 676 | 677 | this.makeJSFXSound = function(soundName, data, samples, opt_callback) { 678 | var s = new g_createFromJSFXFn(soundName, data, samples, opt_callback); 679 | g_soundBank[soundName] = s; 680 | return s; 681 | }.bind(this); 682 | 683 | this.loadSounds = function(sounds, opt_callback) { 684 | var soundsPending = 1; 685 | var soundsLoaded = function() { 686 | --soundsPending; 687 | if (soundsPending == 0 && opt_callback) { 688 | opt_callback(); 689 | } 690 | }; 691 | 692 | Object.keys(sounds).forEach(function(sound) { 693 | var data = sounds[sound]; 694 | ++soundsPending; 695 | if (data.jsfx) { 696 | this.makeJSFXSound(sound, data.jsfx, data.samples, soundsLoaded); 697 | } else { 698 | this.loadSound(sound, data.filename, data.samples, soundsLoaded); 699 | } 700 | }.bind(this)); 701 | 702 | // so that we generate a callback even if there are no sounds. 703 | // That way users don't have to restructure their code if they have no sounds or if they 704 | // disable sounds by passing none in. 705 | setTimeout(soundsLoaded, 0); 706 | }; 707 | 708 | this.init = function(sounds) { 709 | var a = new Audio() 710 | g_canPlayOgg = a.canPlayType("audio/ogg"); 711 | g_canPlayMp3 = a.canPlayType("audio/mp3"); 712 | g_canPlayWav = a.canPlayType("audio/wav"); 713 | g_canPlayAif = a.canPlayType("audio/aif") || a.canPlayType("audio/aiff"); 714 | g_canPlay = g_canPlayOgg || g_canPlayMp3; 715 | if (!g_canPlay) 716 | return; 717 | 718 | if (webAudioAPI) { 719 | console.log("Using Web Audio API"); 720 | g_context = new webAudioAPI(); 721 | 722 | if (!g_context.createGain) { g_context.createGain = g_context.createGainNode.bind(g_context); } 723 | 724 | g_createFromFileFn = WebAudioSound; 725 | g_createFromJSFXFn = WebAudioJSFX; 726 | } else { 727 | console.log("Using Audio Tag"); 728 | g_createFromFileFn = AudioTagSound; 729 | g_createFromJSFXFn = AudioTagJSFX; 730 | } 731 | 732 | var soundsPending = 1; 733 | var soundsLoaded = function() { 734 | --soundsPending; 735 | if (soundsPending == 0) { 736 | g_eventEmitter.emit('loaded'); 737 | } 738 | }; 739 | 740 | if (sounds) { 741 | Object.keys(sounds).forEach(function(sound) { 742 | var data = sounds[sound]; 743 | ++soundsPending; 744 | if (data.jsfx) { 745 | this.makeJSFXSound(sound, data.jsfx, data.samples, soundsLoaded); 746 | } else { 747 | this.loadSound(sound, data.filename, data.samples, soundsLoaded); 748 | } 749 | }.bind(this)); 750 | } 751 | 752 | // so that we generate a callback even if there are no sounds. 753 | // That way users don't have to restructure their code if they have no sounds or if they 754 | // disable sounds by passing none in. 755 | setTimeout(soundsLoaded, 0); 756 | 757 | if (webAudioAPI) { 758 | setupGesture(); 759 | } 760 | }.bind(this); 761 | this.init(sounds); 762 | 763 | this.getSoundIds = function() { 764 | return Object.keys(g_soundBank); 765 | }; 766 | }; 767 | 768 | AudioManager.hasWebAudio = function() { 769 | return webAudioAPI !== undefined; 770 | }; 771 | 772 | return AudioManager; 773 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 774 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 775 | 776 | 777 | /***/ }), 778 | /* 3 */ 779 | /***/ (function(module, exports, __webpack_require__) { 780 | 781 | "use strict"; 782 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 783 | 784 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(audio, jsfx) { 785 | var jsfxlib = {}; 786 | (function () { 787 | // takes object with param arrays 788 | // audiolib = { 789 | // Sound : ["sine", 1, 2, 4, 1... 790 | // } 791 | // 792 | // returns object with audio samples 793 | // p.Sound.play() 794 | this.createWaves = function(lib){ 795 | var sounds = {}; 796 | for (var e in lib) { 797 | var data = lib[e]; 798 | sounds[e] = this.createWave(data); 799 | } 800 | return sounds; 801 | } 802 | 803 | /* Create a single sound: 804 | var p = jsfxlib.createWave(["sine", 1,2,3, etc.]); 805 | p.play(); 806 | */ 807 | this.createWave = function(lib) { 808 | var params = this.arrayToParams(lib), 809 | data = jsfx.generate(params), 810 | wave = audio.make(data); 811 | 812 | return wave; 813 | } 814 | 815 | // takes object with param arrays 816 | // 817 | // var audiolib = { 818 | // someSound : ["sine", 1, 2, 4, 1... 819 | // } 820 | // 821 | // returns object with AudioBuffers you can use 822 | // with the Web Audio API 823 | // 824 | // var sounds = jsfxlib.createAudioBuffers(ctx, audiolib); 825 | // var ctx = new AudioContext(); 826 | // var src = ctx.createBufferSource(); 827 | // src.buffer = sounds.someSound; 828 | // src.connect(ctx.destination); 829 | // src.start(); 830 | this.createAudioBuffers = function(ctx, lib) { 831 | var sounds = {}; 832 | for (var e in lib) { 833 | var data = lib[e]; 834 | sounds[e] = this.createAudioBuffer(ctx, data); 835 | } 836 | return sounds; 837 | } 838 | 839 | // Create a single AudioBuffer 840 | // 841 | // var buffer = jsfxlib.createAudioBuffer(ctx, ["sine", 1,2,3, etc.]); 842 | // var ctx = new AudioContext(); 843 | // var src = ctx.createBufferSource(); 844 | // src.buffer = buffer; 845 | // src.connect(ctx.destination); 846 | // src.start(); 847 | this.createAudioBuffer = function(ctx, lib) { 848 | var params = this.arrayToParams(lib), 849 | data = jsfx.generate(params), 850 | buffer = audio.makeAudioBuffer(ctx, data); 851 | 852 | return buffer; 853 | } 854 | 855 | this.paramsToArray = function(params){ 856 | var pararr = []; 857 | var len = jsfx.Parameters.length; 858 | for(var i = 0; i < len; i++){ 859 | pararr.push(params[jsfx.Parameters[i].id]); 860 | } 861 | return pararr; 862 | } 863 | 864 | this.arrayToParams = function(pararr){ 865 | var params = {}; 866 | var len = jsfx.Parameters.length; 867 | for(var i = 0; i < len; i++){ 868 | params[jsfx.Parameters[i].id] = pararr[i]; 869 | } 870 | return params; 871 | } 872 | }).apply(jsfxlib); 873 | 874 | return jsfxlib; 875 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 876 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 877 | 878 | 879 | 880 | /***/ }), 881 | /* 4 */ 882 | /***/ (function(module, exports, __webpack_require__) { 883 | 884 | "use strict"; 885 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 886 | 887 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(audio) { 888 | var jsfx = {}; 889 | (function () { 890 | this.Parameters = []; // will be constructed in the end 891 | 892 | this.Generators = { 893 | square : audio.generators.square, 894 | saw : audio.generators.saw, 895 | sine : audio.generators.sine, 896 | noise : audio.generators.noise, 897 | synth : audio.generators.synth 898 | }; 899 | 900 | this.getGeneratorNames = function(){ 901 | var names = []; 902 | for(var e in this.Generators) 903 | names.push(e); 904 | return names; 905 | } 906 | 907 | var nameToParam = function(name){ 908 | return name.replace(/ /g, ""); 909 | } 910 | 911 | this.getParameters = function () { 912 | var params = []; 913 | 914 | var grp = 0; 915 | 916 | // add param 917 | var ap = function (name, min, max, def, step) { 918 | if (step === undefined) 919 | step = (max - min) / 1000; 920 | var param = { name: name, id: nameToParam(name), 921 | min: min, max: max, step:step, def: def, 922 | type: "range", group: grp}; 923 | params.push(param); 924 | }; 925 | 926 | // add option 927 | var ao = function(name, options, def){ 928 | var param = {name: name, id: nameToParam(name), 929 | options: options, def: def, 930 | type: "option", group: grp }; 931 | params.push(param); 932 | } 933 | 934 | var gens = this.getGeneratorNames(); 935 | ao("Generator", gens, gens[0]); 936 | ap("Super Sampling Quality", 0, 16, 0, 1); 937 | ap("Master Volume", 0, 1, 0.4); 938 | grp++; 939 | 940 | ap("Attack Time", 0, 1, 0.1); // seconds 941 | ap("Sustain Time", 0, 2, 0.3); // seconds 942 | ap("Sustain Punch", 0, 3, 2); 943 | ap("Decay Time", 0, 2, 1); // seconds 944 | grp++; 945 | 946 | ap("Min Frequency", 20, 2400, 0, 1); 947 | ap("Start Frequency", 20, 2400, 440, 1); 948 | ap("Max Frequency", 20, 2400, 2000, 1); 949 | ap("Slide", -1, 1, 0); 950 | ap("Delta Slide", -1, 1, 0); 951 | 952 | grp++; 953 | ap("Vibrato Depth", 0, 1, 0); 954 | ap("Vibrato Frequency", 0.01, 48, 8); 955 | ap("Vibrato Depth Slide", -0.3, 1, 0); 956 | ap("Vibrato Frequency Slide", -1, 1, 0); 957 | 958 | grp++; 959 | ap("Change Amount", -1, 1, 0); 960 | ap("Change Speed", 0, 1, 0.1); 961 | 962 | grp++; 963 | ap("Square Duty", 0, 0.5, 0); 964 | ap("Square Duty Sweep", -1, 1, 0); 965 | 966 | grp++; 967 | ap("Repeat Speed", 0, 0.8, 0); 968 | 969 | grp++; 970 | ap("Phaser Offset", -1, 1, 0); 971 | ap("Phaser Sweep", -1, 1, 0); 972 | 973 | grp++; 974 | ap("LP Filter Cutoff", 0, 1, 1); 975 | ap("LP Filter Cutoff Sweep", -1, 1, 0); 976 | ap("LP Filter Resonance", 0, 1, 0); 977 | ap("HP Filter Cutoff", 0, 1, 0); 978 | ap("HP Filter Cutoff Sweep", -1, 1, 0); 979 | 980 | return params; 981 | }; 982 | 983 | 984 | /** 985 | * Input params object has the same parameters as described above 986 | * except all the spaces have been removed 987 | * 988 | * This returns an array of float values of the generated audio. 989 | * 990 | * To make it into a wave use: 991 | * data = jsfx.generate(params) 992 | * audio.make(data) 993 | */ 994 | this.generate = function(params){ 995 | // useful consts/functions 996 | var TAU = 2 * Math.PI, 997 | sin = Math.sin, 998 | cos = Math.cos, 999 | pow = Math.pow, 1000 | abs = Math.abs; 1001 | var SampleRate = audio.SampleRate; 1002 | 1003 | // super sampling 1004 | var super_sampling_quality = params.SuperSamplingQuality | 0; 1005 | if(super_sampling_quality < 1) super_sampling_quality = 1; 1006 | SampleRate = SampleRate * super_sampling_quality; 1007 | 1008 | // enveloping initialization 1009 | var _ss = 1.0 + params.SustainPunch; 1010 | var envelopes = [ {from: 0.0, to: 1.0, time: params.AttackTime}, 1011 | {from: _ss, to: 1.0, time: params.SustainTime}, 1012 | {from: 1.0, to: 0.0, time: params.DecayTime}]; 1013 | var envelopes_len = envelopes.length; 1014 | 1015 | // envelope sample calculation 1016 | for(var i = 0; i < envelopes_len; i++){ 1017 | envelopes[i].samples = 1 + ((envelopes[i].time * SampleRate) | 0); 1018 | } 1019 | // envelope loop variables 1020 | var envelope = undefined; 1021 | var envelope_cur = 0.0; 1022 | var envelope_idx = -1; 1023 | var envelope_increment = 0.0; 1024 | var envelope_last = -1; 1025 | 1026 | // count total samples 1027 | var totalSamples = 0; 1028 | for(var i = 0; i < envelopes_len; i++){ 1029 | totalSamples += envelopes[i].samples; 1030 | } 1031 | 1032 | // fix totalSample limit 1033 | if( totalSamples < SampleRate / 2){ 1034 | totalSamples = SampleRate / 2; 1035 | } 1036 | 1037 | var outSamples = (totalSamples / super_sampling_quality)|0; 1038 | 1039 | // out data samples 1040 | var out = new Array(outSamples); 1041 | var sample = 0; 1042 | var sample_accumulator = 0; 1043 | 1044 | // main generator 1045 | var generator = jsfx.Generators[params.Generator]; 1046 | if (generator === undefined) 1047 | generator = this.Generators.square; 1048 | var generator_A = 0; 1049 | var generator_B = 0; 1050 | 1051 | // square generator 1052 | generator_A = params.SquareDuty; 1053 | var square_slide = params.SquareDutySweep / SampleRate; 1054 | 1055 | // phase calculation 1056 | var phase = 0; 1057 | var phase_speed = params.StartFrequency * TAU / SampleRate; 1058 | 1059 | // phase slide calculation 1060 | var phase_slide = 1.0 + pow(params.Slide, 3.0) * 64.0 / SampleRate; 1061 | var phase_delta_slide = pow(params.DeltaSlide, 3.0) / (SampleRate * 1000); 1062 | if (super_sampling_quality !== undefined) 1063 | phase_delta_slide /= super_sampling_quality; // correction 1064 | 1065 | // frequency limiter 1066 | if(params.MinFrequency > params.StartFrequency) 1067 | params.MinFrequency = params.StartFrequency; 1068 | 1069 | if(params.MaxFrequency < params.StartFrequency) 1070 | params.MaxFrequency = params.StartFrequency; 1071 | 1072 | var phase_min_speed = params.MinFrequency * TAU / SampleRate; 1073 | var phase_max_speed = params.MaxFrequency * TAU / SampleRate; 1074 | 1075 | // frequency vibrato 1076 | var vibrato_phase = 0; 1077 | var vibrato_phase_speed = params.VibratoFrequency * TAU / SampleRate; 1078 | var vibrato_amplitude = params.VibratoDepth; 1079 | 1080 | // frequency vibrato slide 1081 | var vibrato_phase_slide = 1.0 + pow(params.VibratoFrequencySlide, 3.0) * 3.0 / SampleRate; 1082 | var vibrato_amplitude_slide = params.VibratoDepthSlide / SampleRate; 1083 | 1084 | // arpeggiator 1085 | var arpeggiator_time = 0; 1086 | var arpeggiator_limit = params.ChangeSpeed * SampleRate; 1087 | var arpeggiator_mod = pow(params.ChangeAmount, 2); 1088 | if (params.ChangeAmount > 0) 1089 | arpeggiator_mod = 1 + arpeggiator_mod * 10; 1090 | else 1091 | arpeggiator_mod = 1 - arpeggiator_mod * 0.9; 1092 | 1093 | // phaser 1094 | var phaser_max = 1024; 1095 | var phaser_mask = 1023; 1096 | var phaser_buffer = new Array(phaser_max); 1097 | for(var _i = 0; _i < phaser_max; _i++) 1098 | phaser_buffer[_i] = 0; 1099 | var phaser_pos = 0; 1100 | var phaser_offset = pow(params.PhaserOffset, 2.0) * (phaser_max - 4); 1101 | var phaser_offset_slide = pow(params.PhaserSweep, 3.0) * 4000 / SampleRate; 1102 | var phaser_enabled = (abs(phaser_offset_slide) > 0.00001) || 1103 | (abs(phaser_offset) > 0.00001); 1104 | 1105 | // lowpass filter 1106 | var filters_enabled = (params.HPFilterCutoff > 0.001) || (params.LPFilterCutoff < 0.999); 1107 | 1108 | var lowpass_pos = 0; 1109 | var lowpass_pos_slide = 0; 1110 | var lowpass_cutoff = pow(params.LPFilterCutoff, 3.0) / 10; 1111 | var lowpass_cutoff_slide = 1.0 + params.HPFilterCutoffSweep / 10000; 1112 | var lowpass_damping = 5.0 / (1.0 + pow(params.LPFilterResonance, 2) * 20 ) * 1113 | (0.01 + params.LPFilterCutoff); 1114 | if ( lowpass_damping > 0.8) 1115 | lowpass_damping = 0.8; 1116 | lowpass_damping = 1.0 - lowpass_damping; 1117 | var lowpass_enabled = params.LPFilterCutoff < 0.999; 1118 | 1119 | // highpass filter 1120 | var highpass_accumulator = 0; 1121 | var highpass_cutoff = pow(params.HPFilterCutoff, 2.0) / 10; 1122 | var highpass_cutoff_slide = 1.0 + params.HPFilterCutoffSweep / 10000; 1123 | 1124 | // repeat 1125 | var repeat_time = 0; 1126 | var repeat_limit = totalSamples; 1127 | if (params.RepeatSpeed > 0){ 1128 | repeat_limit = pow(1 - params.RepeatSpeed, 2.0) * SampleRate + 32; 1129 | } 1130 | 1131 | // master volume controller 1132 | var master_volume = params.MasterVolume; 1133 | 1134 | var k = 0; 1135 | for(var i = 0; i < totalSamples; i++){ 1136 | // main generator 1137 | sample = generator(phase, generator_A, generator_B); 1138 | 1139 | // square generator 1140 | generator_A += square_slide; 1141 | if(generator_A < 0.0){ 1142 | generator_A = 0.0; 1143 | } else if (generator_A > 0.5){ 1144 | generator_A = 0.5; 1145 | } 1146 | 1147 | if( repeat_time > repeat_limit ){ 1148 | // phase reset 1149 | phase = 0; 1150 | phase_speed = params.StartFrequency * TAU / SampleRate; 1151 | // phase slide reset 1152 | phase_slide = 1.0 + pow(params.Slide, 3.0) * 3.0 / SampleRate; 1153 | phase_delta_slide = pow(params.DeltaSlide, 3.0) / (SampleRate * 1000); 1154 | if (super_sampling_quality !== undefined) 1155 | phase_delta_slide /= super_sampling_quality; // correction 1156 | // arpeggiator reset 1157 | arpeggiator_time = 0; 1158 | arpeggiator_limit = params.ChangeSpeed * SampleRate; 1159 | arpeggiator_mod = 1 + (params.ChangeAmount | 0) / 12.0; 1160 | // repeat reset 1161 | repeat_time = 0; 1162 | } 1163 | repeat_time += 1; 1164 | 1165 | // phase calculation 1166 | phase += phase_speed; 1167 | 1168 | // phase slide calculation 1169 | phase_slide += phase_delta_slide; 1170 | phase_speed *= phase_slide; 1171 | 1172 | // arpeggiator 1173 | if ( arpeggiator_time > arpeggiator_limit ){ 1174 | phase_speed *= arpeggiator_mod; 1175 | arpeggiator_limit = totalSamples; 1176 | } 1177 | arpeggiator_time += 1; 1178 | 1179 | // frequency limiter 1180 | if (phase_speed > phase_max_speed){ 1181 | phase_speed = phase_max_speed; 1182 | } else if(phase_speed < phase_min_speed){ 1183 | phase_speed = phase_min_speed; 1184 | } 1185 | 1186 | // frequency vibrato 1187 | vibrato_phase += vibrato_phase_speed; 1188 | var _vibrato_phase_mod = phase_speed * sin(vibrato_phase) * vibrato_amplitude; 1189 | phase += _vibrato_phase_mod; 1190 | 1191 | // frequency vibrato slide 1192 | vibrato_phase_speed *= vibrato_phase_slide; 1193 | if(vibrato_amplitude_slide){ 1194 | vibrato_amplitude += vibrato_amplitude_slide; 1195 | if(vibrato_amplitude < 0){ 1196 | vibrato_amplitude = 0; 1197 | vibrato_amplitude_slide = 0; 1198 | } else if (vibrato_amplitude > 1){ 1199 | vibrato_amplitude = 1; 1200 | vibrato_amplitude_slide = 0; 1201 | } 1202 | } 1203 | 1204 | // filters 1205 | if( filters_enabled ){ 1206 | 1207 | if( abs(highpass_cutoff) > 0.001){ 1208 | highpass_cutoff *= highpass_cutoff_slide; 1209 | if(highpass_cutoff < 0.00001){ 1210 | highpass_cutoff = 0.00001; 1211 | } else if(highpass_cutoff > 0.1){ 1212 | highpass_cutoff = 0.1; 1213 | } 1214 | } 1215 | 1216 | var _lowpass_pos_old = lowpass_pos; 1217 | lowpass_cutoff *= lowpass_cutoff_slide; 1218 | if(lowpass_cutoff < 0.0){ 1219 | lowpass_cutoff = 0.0; 1220 | } else if ( lowpass_cutoff > 0.1 ){ 1221 | lowpass_cutoff = 0.1; 1222 | } 1223 | if(lowpass_enabled){ 1224 | lowpass_pos_slide += (sample - lowpass_pos) * lowpass_cutoff; 1225 | lowpass_pos_slide *= lowpass_damping; 1226 | } else { 1227 | lowpass_pos = sample; 1228 | lowpass_pos_slide = 0; 1229 | } 1230 | lowpass_pos += lowpass_pos_slide; 1231 | 1232 | highpass_accumulator += lowpass_pos - _lowpass_pos_old; 1233 | highpass_accumulator *= 1.0 - highpass_cutoff; 1234 | sample = highpass_accumulator; 1235 | } 1236 | 1237 | // phaser 1238 | if (phaser_enabled) { 1239 | phaser_offset += phaser_offset_slide; 1240 | if( phaser_offset < 0){ 1241 | phaser_offset = -phaser_offset; 1242 | phaser_offset_slide = -phaser_offset_slide; 1243 | } 1244 | if( phaser_offset > phaser_mask){ 1245 | phaser_offset = phaser_mask; 1246 | phaser_offset_slide = 0; 1247 | } 1248 | 1249 | phaser_buffer[phaser_pos] = sample; 1250 | // phaser sample modification 1251 | var _p = (phaser_pos - (phaser_offset|0) + phaser_max) & phaser_mask; 1252 | sample += phaser_buffer[_p]; 1253 | phaser_pos = (phaser_pos + 1) & phaser_mask; 1254 | } 1255 | 1256 | // envelope processing 1257 | if( i > envelope_last ){ 1258 | envelope_idx += 1; 1259 | if(envelope_idx < envelopes_len) // fault protection 1260 | envelope = envelopes[envelope_idx]; 1261 | else // the trailing envelope is silence 1262 | envelope = {from: 0, to: 0, samples: totalSamples}; 1263 | envelope_cur = envelope.from; 1264 | envelope_increment = (envelope.to - envelope.from) / (envelope.samples + 1); 1265 | envelope_last += envelope.samples; 1266 | } 1267 | sample *= envelope_cur; 1268 | envelope_cur += envelope_increment; 1269 | 1270 | // master volume controller 1271 | sample *= master_volume; 1272 | 1273 | // prepare for next sample 1274 | if(super_sampling_quality > 1){ 1275 | sample_accumulator += sample; 1276 | if( (i + 1) % super_sampling_quality === 0){ 1277 | out[k] = sample_accumulator / super_sampling_quality; 1278 | k += 1; 1279 | sample_accumulator = 0; 1280 | } 1281 | } else { 1282 | out[i] = sample; 1283 | } 1284 | } 1285 | 1286 | // return out; 1287 | 1288 | // add padding 10ms 1289 | var len = (SampleRate / 100)|0; 1290 | var padding = new Array(len); 1291 | for(var i = 0; i < len; i++) 1292 | padding[i] = 0; 1293 | return padding.concat(out).concat(padding); 1294 | } 1295 | 1296 | this.Parameters = this.getParameters(); 1297 | 1298 | }).apply(jsfx); 1299 | 1300 | return jsfx; 1301 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 1302 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 1303 | 1304 | 1305 | 1306 | /***/ }), 1307 | /* 5 */ 1308 | /***/ (function(module, exports, __webpack_require__) { 1309 | 1310 | "use strict"; 1311 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* 1312 | * Copyright 2014, Gregg Tavares. 1313 | * All rights reserved. 1314 | * 1315 | * Redistribution and use in source and binary forms, with or without 1316 | * modification, are permitted provided that the following conditions are 1317 | * met: 1318 | * 1319 | * * Redistributions of source code must retain the above copyright 1320 | * notice, this list of conditions and the following disclaimer. 1321 | * * Redistributions in binary form must reproduce the above 1322 | * copyright notice, this list of conditions and the following disclaimer 1323 | * in the documentation and/or other materials provided with the 1324 | * distribution. 1325 | * * Neither the name of Gregg Tavares. nor the names of its 1326 | * contributors may be used to endorse or promote products derived from 1327 | * this software without specific prior written permission. 1328 | * 1329 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1330 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1331 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1332 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1333 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1334 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1335 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1336 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1337 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1338 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1339 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1340 | */ 1341 | 1342 | 1343 | 1344 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() { 1345 | 1346 | /** 1347 | * This is similar to node's EventEmitter. 1348 | * The major difference is calling `addEventListner` 1349 | * or `removeEventListener` with `null` or `undefined` 1350 | * will remove all listeners for that event. 1351 | */ 1352 | var EventEmitter = function() { 1353 | var events = {}; 1354 | var maxListeners = 10; 1355 | 1356 | var setMaxListeners = function(max) { 1357 | maxListeners = max; 1358 | }; 1359 | 1360 | var addEventListener = function(name, handler) { 1361 | if (!handler) { 1362 | delete events[name]; 1363 | return; 1364 | } 1365 | 1366 | var handlers = events[name]; 1367 | if (!handlers) { 1368 | handlers = []; 1369 | events[name] = handlers; 1370 | } 1371 | handlers.push(handler); 1372 | if (handlers.length > maxListeners) { 1373 | console.warn("More than " + maxListeners + " added to event " + name); 1374 | } 1375 | }; 1376 | 1377 | var removeEventListener = function(name, handler) { 1378 | if (!handler) { 1379 | delete events[name]; 1380 | return; 1381 | } 1382 | 1383 | var handlers = events[name]; 1384 | if (handlers) { 1385 | var ndx = handlers.indexOf(handler); 1386 | if (ndx >= 0) { 1387 | handlers.splice(ndx, 1); 1388 | } 1389 | } 1390 | }; 1391 | 1392 | var removeAllEventListeners = function() { 1393 | events = {}; 1394 | }; 1395 | 1396 | var emit = function(name) { 1397 | var handlers = events[name]; 1398 | if (handlers) { 1399 | var args = Array.prototype.slice.call(arguments, 1); 1400 | handlers.forEach(function(handler) { 1401 | handler.apply(this, args); 1402 | }); 1403 | } 1404 | }; 1405 | 1406 | var listeners = function(name) { 1407 | return events[name]; 1408 | }; 1409 | 1410 | this.on = addEventListener; 1411 | this.addEventListener = addEventListener 1412 | this.removeEventListener = removeEventListener 1413 | this.removeAllEventListeners = removeAllEventListeners; 1414 | this.addListener = addEventListener 1415 | this.removeListener = removeEventListener 1416 | this.removeAllListeners = removeAllEventListeners; 1417 | this.emit = emit; 1418 | this.listeners = listeners; 1419 | this.setMaxListeners = setMaxListeners; 1420 | }; 1421 | 1422 | return EventEmitter; 1423 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 1424 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 1425 | 1426 | 1427 | 1428 | /***/ }) 1429 | /******/ ]); --------------------------------------------------------------------------------