├── public ├── script │ ├── bower_components │ │ └── jquery │ │ │ ├── .gitignore │ │ │ ├── package.json │ │ │ ├── bower.json │ │ │ ├── component.json │ │ │ ├── README.md │ │ │ ├── .bower.json │ │ │ ├── composer.json │ │ │ ├── jquery-migrate.min.js │ │ │ ├── jquery-migrate.js │ │ │ └── jquery.min.js │ ├── bower.json │ ├── listeners.js │ ├── vocoder.js │ └── pitchfinder.js ├── favicon.ico ├── index.html └── assets │ └── css │ ├── main.css │ └── normalize.css ├── config.ru ├── Gemfile ├── server.rb ├── Gemfile.lock ├── .gitignore └── README.md /public/script/bower_components/jquery/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require './server' 2 | 3 | run Sinatra::Application -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'sinatra' 4 | gem 'shotgun' -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bioball/Keyboard-Singer/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /server.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | set :bind, '0.0.0.0' 4 | 5 | get '/' do 6 | File.read(File.join('public', 'index.html')) 7 | end -------------------------------------------------------------------------------- /public/script/bower_components/jquery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "components-jquery", 3 | "version": "2.0.3", 4 | "description": "jQuery component", 5 | "keywords": ["jquery"], 6 | "main": "./jquery.js" 7 | } 8 | -------------------------------------------------------------------------------- /public/script/bower_components/jquery/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.0.3", 4 | "description": "jQuery component", 5 | "keywords": [ 6 | "jquery", 7 | "component" 8 | ], 9 | "main": "jquery.js", 10 | "license": "MIT" 11 | } 12 | -------------------------------------------------------------------------------- /public/script/bower_components/jquery/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "repo": "components/jquery", 4 | "version": "2.0.3", 5 | "description": "jQuery component", 6 | "keywords": [ 7 | "jquery", 8 | "component" 9 | ], 10 | "main": "jquery.js", 11 | "scripts": [ 12 | "jquery.js" 13 | ], 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rack (1.5.2) 5 | rack-protection (1.5.1) 6 | rack 7 | shotgun (0.9) 8 | rack (>= 1.0) 9 | sinatra (1.4.4) 10 | rack (~> 1.4) 11 | rack-protection (~> 1.4) 12 | tilt (~> 1.3, >= 1.3.4) 13 | tilt (1.4.1) 14 | 15 | PLATFORMS 16 | ruby 17 | 18 | DEPENDENCIES 19 | shotgun 20 | sinatra 21 | -------------------------------------------------------------------------------- /public/script/bower_components/jquery/README.md: -------------------------------------------------------------------------------- 1 | jQuery Component 2 | ================ 3 | 4 | Shim repository for the [jQuery](http://jquery.com). 5 | 6 | Package Managers 7 | ---------------- 8 | 9 | * [Bower](http://bower.io/): `jquery` 10 | * [Component](https://github.com/component/component): `components/jquery` 11 | * [Composer](http://packagist.org/packages/components/jquery): `components/jquery` 12 | -------------------------------------------------------------------------------- /public/script/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phasevocoder", 3 | "version": "0.0.0", 4 | "authors": [ 5 | "Daniel Chao " 6 | ], 7 | "description": "An HTML5 phase vocoder!", 8 | "main": "main.html", 9 | "license": "MIT", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "test", 15 | "tests" 16 | ], 17 | "dependencies": { 18 | "jquery": "~2.0.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Keyboard-Singer 2 | =============== 3 | 4 | Sing harmony with yourself! Press down the corresponding keys to hear your voice, pitch mapped (and minion sounding to boot). 5 | 6 | This project uses Peter Hayes' [pitchfinder library](https://github.com/peterkhayes/pitchfinder.js), and a custom hacky pitch shifting algorithm. 7 | 8 | Usage 9 | ----- 10 | 11 | This application only works on Chrome. If you have Chrome and it is not working for you, try updating your Chrome browser. 12 | 13 | Make sure your speakers are a good distance from your microphone. If you are on a laptop, plug in headphones before you sing. -------------------------------------------------------------------------------- /public/script/bower_components/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.0.3", 4 | "description": "jQuery component", 5 | "keywords": [ 6 | "jquery", 7 | "component" 8 | ], 9 | "main": "jquery.js", 10 | "license": "MIT", 11 | "homepage": "https://github.com/components/jquery", 12 | "_release": "2.0.3", 13 | "_resolution": { 14 | "type": "version", 15 | "tag": "2.0.3", 16 | "commit": "452a56b52b8f4a032256cdb8b6838f25f0bdb3d2" 17 | }, 18 | "_source": "git://github.com/components/jquery.git", 19 | "_target": "~2.0.3", 20 | "_originalSource": "jquery", 21 | "_direct": true 22 | } -------------------------------------------------------------------------------- /public/script/listeners.js: -------------------------------------------------------------------------------- 1 | var keyMap = { 2 | 65: 'A', 87: 'As', 83: 'B', 68: 'C', 82: 'Cs', 70: 'D', 3 | 84: 'Ds', 71: 'E', 72: 'F', 85: 'Fs', 74: 'G', 73: 'Gs', 4 | 75: 'uA', 79: 'uAs', 76: 'uB', 186: 'uC', 5 | 97: 'A', 119: 'As', 115: 'B', 100: 'C', 114: 'Cs', 102: 'D', 6 | 116: 'Ds', 103: 'E', 104: 'F', 117: 'Fs', 106: 'G', 105: 'Gs', 7 | 107: 'uA', 111: 'uAs', 108: 'uB', 59: 'uC', 8 | }; 9 | var addListeners = function(){ 10 | $(document).keypress(function(key){ 11 | var key = keyMap[key.which]; 12 | if(!vocoder.players){ 13 | vocoder.createPlayers(); 14 | } 15 | var player = vocoder.players[key]; 16 | if(!player.isPlaying){ 17 | player.play(); 18 | $('.' + key).addClass('pressed'); 19 | } 20 | }); 21 | 22 | $(document).keyup(function(key){ 23 | var key = keyMap[key.which]; 24 | var player = vocoder.players[key]; 25 | player.stop(); 26 | $('.' + key).removeClass('pressed'); 27 | }) 28 | }; -------------------------------------------------------------------------------- /public/script/bower_components/jquery/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "components/jquery", 3 | "description": "jQuery JavaScript Library", 4 | "type": "component", 5 | "homepage": "http://jquery.com", 6 | "license": "MIT", 7 | "support": { 8 | "irc": "irc://irc.freenode.org/jquery", 9 | "issues": "http://bugs.jquery.com", 10 | "forum": "http://forum.jquery.com", 11 | "wiki": "http://docs.jquery.com/", 12 | "source": "https://github.com/jquery/jquery" 13 | }, 14 | "authors": [ 15 | { 16 | "name": "John Resig", 17 | "email": "jeresig@gmail.com" 18 | } 19 | ], 20 | "require": { 21 | "robloach/component-installer": "*" 22 | }, 23 | "extra": { 24 | "component": { 25 | "scripts": [ 26 | "jquery.js" 27 | ], 28 | "files": [ 29 | "jquery.min.js", 30 | "jquery-migrate.js", 31 | "jquery-migrate.min.js" 32 | ] 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Keyboard Singer - Sing harmonies with yourself 10 | 11 | 12 |
13 |
14 | 17 | 18 | Sing harmony with yourself! 19 | 20 | 21 |
22 | 23 |
24 |
25 |
A
26 |
W
27 |
S
28 |
D
29 |
R
30 |
F
31 |
T
32 |
G
33 |
H
34 |
U
35 |
J
36 |
I
37 |
K
38 |
O
39 |
L
40 |
;
41 |
42 |
43 | 44 |
45 |
46 | 57 |
58 |
59 | 60 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | -------------------------------------------------------------------------------- /public/assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Oleo+Script+Swash+Caps:400); 2 | 3 | /* GENERAL STYLES */ 4 | .favicon { 5 | font-family: 'Oleo Script Swash Caps'; 6 | font-size: 12px; 7 | background-color: #E3631E; 8 | color: white; 9 | padding-left: 20px; 10 | } 11 | 12 | html { 13 | height: 100%; 14 | } 15 | 16 | body { 17 | height: 100%; 18 | background-color: #3B240D 19 | } 20 | 21 | .container { 22 | width: 900px; 23 | position: relative; 24 | margin: auto; 25 | } 26 | 27 | /* HEADER ELEMENTS */ 28 | header { 29 | position: relative; 30 | top: 0; 31 | left: 0; 32 | right: 0; 33 | height: 170px; 34 | background-color: #F5EADC; 35 | } 36 | 37 | .logo { 38 | font-family: 'Oleo Script Swash Caps', cursive; 39 | color: #E3631E; 40 | text-align: center; 41 | font-size: 6em; 42 | } 43 | 44 | small { 45 | font-family: Helvetica; 46 | font-style: italic; 47 | font-size: 1.5em; 48 | color: #822E00; 49 | position: absolute; 50 | right: 270px; 51 | top: 100px; 52 | } 53 | 54 | /* FOOTER ELEMENTS */ 55 | .contact { 56 | position: absolute; 57 | right: 333px; 58 | top: 50px; 59 | } 60 | 61 | .icons a { 62 | display: inline-block; 63 | margin: 0px 30px; 64 | font-family: 'FontAwesome'; 65 | color: #996d43; 66 | text-decoration: none; 67 | } 68 | 69 | .icons a:hover { 70 | color: #AAE6F0; 71 | } 72 | 73 | .icons i { 74 | font-style: normal; 75 | } 76 | 77 | /* KEYBOARD */ 78 | .keyboardWorld { 79 | position: relative; 80 | left: 0; 81 | right: 0; 82 | height: 300px; 83 | background-color: #A3540F; 84 | } 85 | 86 | .keyboard { 87 | position: relative; 88 | top: 25px; 89 | width: 840px; 90 | height: 250px; 91 | margin: auto; 92 | } 93 | 94 | .key { 95 | float: left; 96 | text-align: center; 97 | height: 250px; 98 | width: 80px; 99 | background-color: white; 100 | margin: 0px 2px; 101 | border-radius: 0px 0px 5px 5px; 102 | } 103 | 104 | span { 105 | position: relative; 106 | font-family: Helvetica; 107 | font-weight: 300; 108 | font-size: 1.2em; 109 | } 110 | 111 | .key span { 112 | top: 200px; 113 | } 114 | 115 | .black { 116 | position: absolute; 117 | height: 160px; 118 | background-color: black; 119 | width: 60px; 120 | } 121 | 122 | .black span { 123 | top: 120px; 124 | color: white; 125 | font-weight: 200; 126 | } 127 | 128 | .As { 129 | left: 52px; 130 | } 131 | 132 | .Cs { 133 | left: 220px; 134 | } 135 | 136 | .Ds { 137 | left: 304px; 138 | } 139 | 140 | .Fs { 141 | left: 472px; 142 | } 143 | 144 | .Gs { 145 | left: 556px; 146 | } 147 | 148 | .uAs { 149 | left: 640px; 150 | } 151 | 152 | .pressed { 153 | background-color: #AAE6F0; 154 | } 155 | 156 | /* DISCLAIMER & INSTRUCTIONS */ 157 | 158 | .screen { 159 | background-color: black; 160 | position: absolute; 161 | opacity: 0.7; 162 | top: 0; 163 | right: 0; 164 | bottom: 0; 165 | left: 0; 166 | } 167 | 168 | .disclaimer { 169 | position: absolute; 170 | top: 300px; 171 | right: 0; 172 | left: 0; 173 | height: 700px; 174 | text-align: center; 175 | color: white; 176 | font-family: Helvetica; 177 | } -------------------------------------------------------------------------------- /public/script/vocoder.js: -------------------------------------------------------------------------------- 1 | // YIN detector is brought in from the Pitchfinder library, courtesy of 2 | // the brilliant Peter Hayes. 3 | var vocoder = {}; 4 | 5 | (function(){ 6 | var 7 | context = new webkitAudioContext(), 8 | yinDetector = YIN(), 9 | micSource, 10 | sourceNode, 11 | currentPitch; 12 | 13 | vocoder.notes = { 14 | octave1: { 15 | 'A': 110, 'As': 116.541, 16 | 'B': 123.471, 17 | 'C': 130.813, 'Cs': 138.591, 18 | 'D': 146.832, 'Ds': 155.563, 19 | 'E': 164.814, 20 | 'F': 174.614, 'Fs': 174.614, 21 | 'G': 195.998, 'Gs': 207.652, 22 | 'uA': 220, 'uAs': 233.082, 23 | 'uB': 246.942, 'uC': 261.626 24 | }, 25 | octave2: { 26 | 'A': 220, 'As': 233.082, 27 | 'B': 246.942, 28 | 'C': 261.626, 'Cs': 277.183, 29 | 'D': 293.665, 'Ds': 311.127, 30 | 'E': 329.528, 31 | 'F': 349.228, 'Fs': 369.994, 32 | 'G': 391.995, 'Gs': 415.305, 33 | 'uA': 440, 'uAs': 466.164, 34 | 'uB': 493.883, 'uC': 523.251 35 | } 36 | }; 37 | 38 | vocoder.getMicSource = function(){ 39 | if(navigator.webkitGetUserMedia){ 40 | navigator.webkitGetUserMedia({audio: true}, initialize, function(error){ 41 | alert("Error capturing audio. Try refreshing, or updating your Chrome browser.") 42 | }); 43 | } else { 44 | alert("This application only supports Chrome browsers"); 45 | } 46 | }; 47 | 48 | vocoder.createPlayers = function(octave){ 49 | octave = octave || 'octave1'; 50 | vocoder.players = {}; 51 | Object.keys(vocoder.notes[octave]).forEach(function(note){ 52 | vocoder.players[note] = createPitchNode(vocoder.notes[octave][note]); 53 | }) 54 | }; 55 | 56 | var createPitchNode = function(targetPitch){ 57 | var node = context.createJavaScriptNode(2048, 1, 1); 58 | sourceNode.connect(node); 59 | node.onaudioprocess = function(e){ 60 | changePitch(e, targetPitch); 61 | }; 62 | node.play = function(){ 63 | this.connect(context.destination); 64 | this.isPlaying = true; 65 | }; 66 | node.stop = function(){ 67 | this.disconnect(context.destination); 68 | this.isPlaying = false; 69 | }; 70 | node.isPlaying = false; 71 | return node; 72 | }; 73 | 74 | var initialize = function(micSource){ 75 | sourceNode = context.createMediaStreamSource(micSource); 76 | var gainNode = context.createGain(); 77 | var pitchNode = context.createJavaScriptNode(2048, 1, 1); 78 | pitchNode.onaudioprocess = findPitch; 79 | 80 | sourceNode.connect(gainNode); 81 | gainNode.connect(pitchNode); 82 | pitchNode.connect(context.destination); 83 | }; 84 | 85 | var findPitch = function(e){ 86 | var freq = yinDetector(e.inputBuffer.getChannelData(0)).freq; 87 | if(freq > 0){ 88 | currentPitch = freq; 89 | } 90 | }; 91 | 92 | var changePitch = function(e, targetPitch){ 93 | var shiftRatio = targetPitch/currentPitch; 94 | 95 | buffer = smoothBuffer(e.inputBuffer.getChannelData(0)), 96 | buffer = resizeBuffer(buffer, shiftRatio), 97 | source = context.createBufferSource() 98 | gain = context.createGain(); 99 | 100 | source.buffer = context.createBuffer(1, 2048*shiftRatio, 44100); 101 | source.buffer.getChannelData(0).set(buffer); 102 | source.playbackRate.value = shiftRatio; 103 | 104 | source.connect(gain); 105 | gain.connect(context.destination); 106 | source.start(0); 107 | }; 108 | 109 | var resizeBuffer = function(buffer, percentage){ 110 | var newLength = buffer.length * percentage 111 | var newBuffer = new Float32Array(newLength) 112 | 113 | for(var i = 0; i < newLength; i++){ 114 | newBuffer[i] = buffer[i % buffer.length] 115 | } 116 | return newBuffer; 117 | }; 118 | 119 | var smoothBuffer = function(buffer){ 120 | var i = 0; 121 | if(buffer[0] < 0){ 122 | while(buffer[i] < 0){ 123 | buffer[i] = 0; 124 | i++; 125 | } 126 | } else { 127 | while(buffer[i] > 0){ 128 | buffer[i] = 0; 129 | i++ 130 | } 131 | } 132 | i = buffer.length - 1; 133 | if(buffer[buffer.length - 1] < 0){ 134 | while(buffer[i] < 0){ 135 | buffer[i] = 0; 136 | i--; 137 | } 138 | } else { 139 | while(buffer[i] > 0){ 140 | buffer[i] = 0; 141 | i--; 142 | } 143 | } 144 | return buffer; 145 | }; 146 | 147 | var getPitch = function(buffer){ 148 | return yinDetector(buffer) 149 | }; 150 | })(); -------------------------------------------------------------------------------- /public/script/bower_components/jquery/jquery-migrate.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Migrate v1.1.1 | (c) 2005, 2013 jQuery Foundation, Inc. and other contributors | jquery.org/license */ 2 | jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0),function(e,t,n){function r(n){o[n]||(o[n]=!0,e.migrateWarnings.push(n),t.console&&console.warn&&!e.migrateMute&&(console.warn("JQMIGRATE: "+n),e.migrateTrace&&console.trace&&console.trace()))}function a(t,a,o,i){if(Object.defineProperty)try{return Object.defineProperty(t,a,{configurable:!0,enumerable:!0,get:function(){return r(i),o},set:function(e){r(i),o=e}}),n}catch(s){}e._definePropertyBroken=!0,t[a]=o}var o={};e.migrateWarnings=[],!e.migrateMute&&t.console&&console.log&&console.log("JQMIGRATE: Logging is active"),e.migrateTrace===n&&(e.migrateTrace=!0),e.migrateReset=function(){o={},e.migrateWarnings.length=0},"BackCompat"===document.compatMode&&r("jQuery is not compatible with Quirks Mode");var i=e("",{size:1}).attr("size")&&e.attrFn,s=e.attr,u=e.attrHooks.value&&e.attrHooks.value.get||function(){return null},c=e.attrHooks.value&&e.attrHooks.value.set||function(){return n},l=/^(?:input|button)$/i,d=/^[238]$/,p=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,f=/^(?:checked|selected)$/i;a(e,"attrFn",i||{},"jQuery.attrFn is deprecated"),e.attr=function(t,a,o,u){var c=a.toLowerCase(),g=t&&t.nodeType;return u&&(4>s.length&&r("jQuery.fn.attr( props, pass ) is deprecated"),t&&!d.test(g)&&(i?a in i:e.isFunction(e.fn[a])))?e(t)[a](o):("type"===a&&o!==n&&l.test(t.nodeName)&&t.parentNode&&r("Can't change the 'type' of an input or button in IE 6/7/8"),!e.attrHooks[c]&&p.test(c)&&(e.attrHooks[c]={get:function(t,r){var a,o=e.prop(t,r);return o===!0||"boolean"!=typeof o&&(a=t.getAttributeNode(r))&&a.nodeValue!==!1?r.toLowerCase():n},set:function(t,n,r){var a;return n===!1?e.removeAttr(t,r):(a=e.propFix[r]||r,a in t&&(t[a]=!0),t.setAttribute(r,r.toLowerCase())),r}},f.test(c)&&r("jQuery.fn.attr('"+c+"') may use property instead of attribute")),s.call(e,t,a,o))},e.attrHooks.value={get:function(e,t){var n=(e.nodeName||"").toLowerCase();return"button"===n?u.apply(this,arguments):("input"!==n&&"option"!==n&&r("jQuery.fn.attr('value') no longer gets properties"),t in e?e.value:null)},set:function(e,t){var a=(e.nodeName||"").toLowerCase();return"button"===a?c.apply(this,arguments):("input"!==a&&"option"!==a&&r("jQuery.fn.attr('value', val) no longer sets properties"),e.value=t,n)}};var g,h,v=e.fn.init,m=e.parseJSON,y=/^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;e.fn.init=function(t,n,a){var o;return t&&"string"==typeof t&&!e.isPlainObject(n)&&(o=y.exec(t))&&o[1]&&("<"!==t.charAt(0)&&r("$(html) HTML strings must start with '<' character"),n&&n.context&&(n=n.context),e.parseHTML)?v.call(this,e.parseHTML(e.trim(t),n,!0),n,a):v.apply(this,arguments)},e.fn.init.prototype=e.fn,e.parseJSON=function(e){return e||null===e?m.apply(this,arguments):(r("jQuery.parseJSON requires a valid JSON string"),null)},e.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||0>e.indexOf("compatible")&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e.browser||(g=e.uaMatch(navigator.userAgent),h={},g.browser&&(h[g.browser]=!0,h.version=g.version),h.chrome?h.webkit=!0:h.webkit&&(h.safari=!0),e.browser=h),a(e,"browser",e.browser,"jQuery.browser is deprecated"),e.sub=function(){function t(e,n){return new t.fn.init(e,n)}e.extend(!0,t,this),t.superclass=this,t.fn=t.prototype=this(),t.fn.constructor=t,t.sub=this.sub,t.fn.init=function(r,a){return a&&a instanceof e&&!(a instanceof t)&&(a=t(a)),e.fn.init.call(this,r,a,n)},t.fn.init.prototype=t.fn;var n=t(document);return r("jQuery.sub() is deprecated"),t},e.ajaxSetup({converters:{"text json":e.parseJSON}});var b=e.fn.data;e.fn.data=function(t){var a,o,i=this[0];return!i||"events"!==t||1!==arguments.length||(a=e.data(i,t),o=e._data(i,t),a!==n&&a!==o||o===n)?b.apply(this,arguments):(r("Use of jQuery.fn.data('events') is deprecated"),o)};var j=/\/(java|ecma)script/i,w=e.fn.andSelf||e.fn.addBack;e.fn.andSelf=function(){return r("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),w.apply(this,arguments)},e.clean||(e.clean=function(t,a,o,i){a=a||document,a=!a.nodeType&&a[0]||a,a=a.ownerDocument||a,r("jQuery.clean() is deprecated");var s,u,c,l,d=[];if(e.merge(d,e.buildFragment(t,a).childNodes),o)for(c=function(e){return!e.type||j.test(e.type)?i?i.push(e.parentNode?e.parentNode.removeChild(e):e):o.appendChild(e):n},s=0;null!=(u=d[s]);s++)e.nodeName(u,"script")&&c(u)||(o.appendChild(u),u.getElementsByTagName!==n&&(l=e.grep(e.merge([],u.getElementsByTagName("script")),c),d.splice.apply(d,[s+1,0].concat(l)),s+=l.length));return d});var Q=e.event.add,x=e.event.remove,k=e.event.trigger,N=e.fn.toggle,C=e.fn.live,S=e.fn.die,T="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",M=RegExp("\\b(?:"+T+")\\b"),H=/(?:^|\s)hover(\.\S+|)\b/,A=function(t){return"string"!=typeof t||e.event.special.hover?t:(H.test(t)&&r("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'"),t&&t.replace(H,"mouseenter$1 mouseleave$1"))};e.event.props&&"attrChange"!==e.event.props[0]&&e.event.props.unshift("attrChange","attrName","relatedNode","srcElement"),e.event.dispatch&&a(e.event,"handle",e.event.dispatch,"jQuery.event.handle is undocumented and deprecated"),e.event.add=function(e,t,n,a,o){e!==document&&M.test(t)&&r("AJAX events should be attached to document: "+t),Q.call(this,e,A(t||""),n,a,o)},e.event.remove=function(e,t,n,r,a){x.call(this,e,A(t)||"",n,r,a)},e.fn.error=function(){var e=Array.prototype.slice.call(arguments,0);return r("jQuery.fn.error() is deprecated"),e.splice(0,0,"error"),arguments.length?this.bind.apply(this,e):(this.triggerHandler.apply(this,e),this)},e.fn.toggle=function(t,n){if(!e.isFunction(t)||!e.isFunction(n))return N.apply(this,arguments);r("jQuery.fn.toggle(handler, handler...) is deprecated");var a=arguments,o=t.guid||e.guid++,i=0,s=function(n){var r=(e._data(this,"lastToggle"+t.guid)||0)%i;return e._data(this,"lastToggle"+t.guid,r+1),n.preventDefault(),a[r].apply(this,arguments)||!1};for(s.guid=o;a.length>i;)a[i++].guid=o;return this.click(s)},e.fn.live=function(t,n,a){return r("jQuery.fn.live() is deprecated"),C?C.apply(this,arguments):(e(this.context).on(t,this.selector,n,a),this)},e.fn.die=function(t,n){return r("jQuery.fn.die() is deprecated"),S?S.apply(this,arguments):(e(this.context).off(t,this.selector||"**",n),this)},e.event.trigger=function(e,t,n,a){return n||M.test(e)||r("Global events are undocumented and deprecated"),k.call(this,e,t,n||document,a)},e.each(T.split("|"),function(t,n){e.event.special[n]={setup:function(){var t=this;return t!==document&&(e.event.add(document,n+"."+e.guid,function(){e.event.trigger(n,null,t,!0)}),e._data(this,n,e.guid++)),!1},teardown:function(){return this!==document&&e.event.remove(document,n+"."+e._data(this,n)),!1}}})}(jQuery,window); 3 | //@ sourceMappingURL=dist/jquery-migrate.min.map -------------------------------------------------------------------------------- /public/assets/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.3 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /** 8 | * Correct `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | main, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | 26 | /** 27 | * Correct `inline-block` display not defined in IE 8/9. 28 | */ 29 | 30 | audio, 31 | canvas, 32 | video { 33 | display: inline-block; 34 | } 35 | 36 | /** 37 | * Prevent modern browsers from displaying `audio` without controls. 38 | * Remove excess height in iOS 5 devices. 39 | */ 40 | 41 | audio:not([controls]) { 42 | display: none; 43 | height: 0; 44 | } 45 | 46 | /** 47 | * Address `[hidden]` styling not present in IE 8/9. 48 | * Hide the `template` element in IE, Safari, and Firefox < 22. 49 | */ 50 | 51 | [hidden], 52 | template { 53 | display: none; 54 | } 55 | 56 | /* ========================================================================== 57 | Base 58 | ========================================================================== */ 59 | 60 | /** 61 | * 1. Set default font family to sans-serif. 62 | * 2. Prevent iOS text size adjust after orientation change, without disabling 63 | * user zoom. 64 | */ 65 | 66 | html { 67 | font-family: sans-serif; /* 1 */ 68 | -ms-text-size-adjust: 100%; /* 2 */ 69 | -webkit-text-size-adjust: 100%; /* 2 */ 70 | } 71 | 72 | /** 73 | * Remove default margin. 74 | */ 75 | 76 | body { 77 | margin: 0; 78 | } 79 | 80 | /* ========================================================================== 81 | Links 82 | ========================================================================== */ 83 | 84 | /** 85 | * Remove the gray background color from active links in IE 10. 86 | */ 87 | 88 | a { 89 | background: transparent; 90 | } 91 | 92 | /** 93 | * Address `outline` inconsistency between Chrome and other browsers. 94 | */ 95 | 96 | a:focus { 97 | outline: thin dotted; 98 | } 99 | 100 | /** 101 | * Improve readability when focused and also mouse hovered in all browsers. 102 | */ 103 | 104 | a:active, 105 | a:hover { 106 | outline: 0; 107 | } 108 | 109 | /* ========================================================================== 110 | Typography 111 | ========================================================================== */ 112 | 113 | /** 114 | * Address variable `h1` font-size and margin within `section` and `article` 115 | * contexts in Firefox 4+, Safari 5, and Chrome. 116 | */ 117 | 118 | h1 { 119 | font-size: 2em; 120 | margin: 0.67em 0; 121 | } 122 | 123 | /** 124 | * Address styling not present in IE 8/9, Safari 5, and Chrome. 125 | */ 126 | 127 | abbr[title] { 128 | border-bottom: 1px dotted; 129 | } 130 | 131 | /** 132 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 133 | */ 134 | 135 | b, 136 | strong { 137 | font-weight: bold; 138 | } 139 | 140 | /** 141 | * Address styling not present in Safari 5 and Chrome. 142 | */ 143 | 144 | dfn { 145 | font-style: italic; 146 | } 147 | 148 | /** 149 | * Address differences between Firefox and other browsers. 150 | */ 151 | 152 | hr { 153 | -moz-box-sizing: content-box; 154 | box-sizing: content-box; 155 | height: 0; 156 | } 157 | 158 | /** 159 | * Address styling not present in IE 8/9. 160 | */ 161 | 162 | mark { 163 | background: #ff0; 164 | color: #000; 165 | } 166 | 167 | /** 168 | * Correct font family set oddly in Safari 5 and Chrome. 169 | */ 170 | 171 | code, 172 | kbd, 173 | pre, 174 | samp { 175 | font-family: monospace, serif; 176 | font-size: 1em; 177 | } 178 | 179 | /** 180 | * Improve readability of pre-formatted text in all browsers. 181 | */ 182 | 183 | pre { 184 | white-space: pre-wrap; 185 | } 186 | 187 | /** 188 | * Set consistent quote types. 189 | */ 190 | 191 | q { 192 | quotes: "\201C" "\201D" "\2018" "\2019"; 193 | } 194 | 195 | /** 196 | * Address inconsistent and variable font size in all browsers. 197 | */ 198 | 199 | small { 200 | font-size: 80%; 201 | } 202 | 203 | /** 204 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 205 | */ 206 | 207 | sub, 208 | sup { 209 | font-size: 75%; 210 | line-height: 0; 211 | position: relative; 212 | vertical-align: baseline; 213 | } 214 | 215 | sup { 216 | top: -0.5em; 217 | } 218 | 219 | sub { 220 | bottom: -0.25em; 221 | } 222 | 223 | /* ========================================================================== 224 | Embedded content 225 | ========================================================================== */ 226 | 227 | /** 228 | * Remove border when inside `a` element in IE 8/9. 229 | */ 230 | 231 | img { 232 | border: 0; 233 | } 234 | 235 | /** 236 | * Correct overflow displayed oddly in IE 9. 237 | */ 238 | 239 | svg:not(:root) { 240 | overflow: hidden; 241 | } 242 | 243 | /* ========================================================================== 244 | Figures 245 | ========================================================================== */ 246 | 247 | /** 248 | * Address margin not present in IE 8/9 and Safari 5. 249 | */ 250 | 251 | figure { 252 | margin: 0; 253 | } 254 | 255 | /* ========================================================================== 256 | Forms 257 | ========================================================================== */ 258 | 259 | /** 260 | * Define consistent border, margin, and padding. 261 | */ 262 | 263 | fieldset { 264 | border: 1px solid #c0c0c0; 265 | margin: 0 2px; 266 | padding: 0.35em 0.625em 0.75em; 267 | } 268 | 269 | /** 270 | * 1. Correct `color` not being inherited in IE 8/9. 271 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 272 | */ 273 | 274 | legend { 275 | border: 0; /* 1 */ 276 | padding: 0; /* 2 */ 277 | } 278 | 279 | /** 280 | * 1. Correct font family not being inherited in all browsers. 281 | * 2. Correct font size not being inherited in all browsers. 282 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. 283 | */ 284 | 285 | button, 286 | input, 287 | select, 288 | textarea { 289 | font-family: inherit; /* 1 */ 290 | font-size: 100%; /* 2 */ 291 | margin: 0; /* 3 */ 292 | } 293 | 294 | /** 295 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 296 | * the UA stylesheet. 297 | */ 298 | 299 | button, 300 | input { 301 | line-height: normal; 302 | } 303 | 304 | /** 305 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 306 | * All other form control elements do not inherit `text-transform` values. 307 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. 308 | * Correct `select` style inheritance in Firefox 4+ and Opera. 309 | */ 310 | 311 | button, 312 | select { 313 | text-transform: none; 314 | } 315 | 316 | /** 317 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 318 | * and `video` controls. 319 | * 2. Correct inability to style clickable `input` types in iOS. 320 | * 3. Improve usability and consistency of cursor style between image-type 321 | * `input` and others. 322 | */ 323 | 324 | button, 325 | html input[type="button"], /* 1 */ 326 | input[type="reset"], 327 | input[type="submit"] { 328 | -webkit-appearance: button; /* 2 */ 329 | cursor: pointer; /* 3 */ 330 | } 331 | 332 | /** 333 | * Re-set default cursor for disabled elements. 334 | */ 335 | 336 | button[disabled], 337 | html input[disabled] { 338 | cursor: default; 339 | } 340 | 341 | /** 342 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 343 | * 2. Remove excess padding in IE 8/9/10. 344 | */ 345 | 346 | input[type="checkbox"], 347 | input[type="radio"] { 348 | box-sizing: border-box; /* 1 */ 349 | padding: 0; /* 2 */ 350 | } 351 | 352 | /** 353 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 354 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 355 | * (include `-moz` to future-proof). 356 | */ 357 | 358 | input[type="search"] { 359 | -webkit-appearance: textfield; /* 1 */ 360 | -moz-box-sizing: content-box; 361 | -webkit-box-sizing: content-box; /* 2 */ 362 | box-sizing: content-box; 363 | } 364 | 365 | /** 366 | * Remove inner padding and search cancel button in Safari 5 and Chrome 367 | * on OS X. 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Remove inner padding and border in Firefox 4+. 377 | */ 378 | 379 | button::-moz-focus-inner, 380 | input::-moz-focus-inner { 381 | border: 0; 382 | padding: 0; 383 | } 384 | 385 | /** 386 | * 1. Remove default vertical scrollbar in IE 8/9. 387 | * 2. Improve readability and alignment in all browsers. 388 | */ 389 | 390 | textarea { 391 | overflow: auto; /* 1 */ 392 | vertical-align: top; /* 2 */ 393 | } 394 | 395 | /* ========================================================================== 396 | Tables 397 | ========================================================================== */ 398 | 399 | /** 400 | * Remove most spacing between table cells. 401 | */ 402 | 403 | table { 404 | border-collapse: collapse; 405 | border-spacing: 0; 406 | } -------------------------------------------------------------------------------- /public/script/bower_components/jquery/jquery-migrate.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Migrate - v1.1.1 - 2013-02-16 3 | * https://github.com/jquery/jquery-migrate 4 | * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT 5 | */ 6 | (function( jQuery, window, undefined ) { 7 | // See http://bugs.jquery.com/ticket/13335 8 | // "use strict"; 9 | 10 | 11 | var warnedAbout = {}; 12 | 13 | // List of warnings already given; public read only 14 | jQuery.migrateWarnings = []; 15 | 16 | // Set to true to prevent console output; migrateWarnings still maintained 17 | // jQuery.migrateMute = false; 18 | 19 | // Show a message on the console so devs know we're active 20 | if ( !jQuery.migrateMute && window.console && console.log ) { 21 | console.log("JQMIGRATE: Logging is active"); 22 | } 23 | 24 | // Set to false to disable traces that appear with warnings 25 | if ( jQuery.migrateTrace === undefined ) { 26 | jQuery.migrateTrace = true; 27 | } 28 | 29 | // Forget any warnings we've already given; public 30 | jQuery.migrateReset = function() { 31 | warnedAbout = {}; 32 | jQuery.migrateWarnings.length = 0; 33 | }; 34 | 35 | function migrateWarn( msg) { 36 | if ( !warnedAbout[ msg ] ) { 37 | warnedAbout[ msg ] = true; 38 | jQuery.migrateWarnings.push( msg ); 39 | if ( window.console && console.warn && !jQuery.migrateMute ) { 40 | console.warn( "JQMIGRATE: " + msg ); 41 | if ( jQuery.migrateTrace && console.trace ) { 42 | console.trace(); 43 | } 44 | } 45 | } 46 | } 47 | 48 | function migrateWarnProp( obj, prop, value, msg ) { 49 | if ( Object.defineProperty ) { 50 | // On ES5 browsers (non-oldIE), warn if the code tries to get prop; 51 | // allow property to be overwritten in case some other plugin wants it 52 | try { 53 | Object.defineProperty( obj, prop, { 54 | configurable: true, 55 | enumerable: true, 56 | get: function() { 57 | migrateWarn( msg ); 58 | return value; 59 | }, 60 | set: function( newValue ) { 61 | migrateWarn( msg ); 62 | value = newValue; 63 | } 64 | }); 65 | return; 66 | } catch( err ) { 67 | // IE8 is a dope about Object.defineProperty, can't warn there 68 | } 69 | } 70 | 71 | // Non-ES5 (or broken) browser; just set the property 72 | jQuery._definePropertyBroken = true; 73 | obj[ prop ] = value; 74 | } 75 | 76 | if ( document.compatMode === "BackCompat" ) { 77 | // jQuery has never supported or tested Quirks Mode 78 | migrateWarn( "jQuery is not compatible with Quirks Mode" ); 79 | } 80 | 81 | 82 | var attrFn = jQuery( "", { size: 1 } ).attr("size") && jQuery.attrFn, 83 | oldAttr = jQuery.attr, 84 | valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get || 85 | function() { return null; }, 86 | valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set || 87 | function() { return undefined; }, 88 | rnoType = /^(?:input|button)$/i, 89 | rnoAttrNodeType = /^[238]$/, 90 | rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, 91 | ruseDefault = /^(?:checked|selected)$/i; 92 | 93 | // jQuery.attrFn 94 | migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" ); 95 | 96 | jQuery.attr = function( elem, name, value, pass ) { 97 | var lowerName = name.toLowerCase(), 98 | nType = elem && elem.nodeType; 99 | 100 | if ( pass ) { 101 | // Since pass is used internally, we only warn for new jQuery 102 | // versions where there isn't a pass arg in the formal params 103 | if ( oldAttr.length < 4 ) { 104 | migrateWarn("jQuery.fn.attr( props, pass ) is deprecated"); 105 | } 106 | if ( elem && !rnoAttrNodeType.test( nType ) && 107 | (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) { 108 | return jQuery( elem )[ name ]( value ); 109 | } 110 | } 111 | 112 | // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking 113 | // for disconnected elements we don't warn on $( "