├── audio ├── synth.mp3 └── guitar.mp3 ├── libs ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.svg ├── css │ └── bootstrap-theme.min.css └── js │ ├── jquery.knob.js │ └── bootstrap.min.js ├── README.md ├── LICENSE ├── css └── style.css ├── js ├── gui.js └── main.js └── index.html /audio/synth.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zya/granular/HEAD/audio/synth.mp3 -------------------------------------------------------------------------------- /audio/guitar.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zya/granular/HEAD/audio/guitar.mp3 -------------------------------------------------------------------------------- /libs/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zya/granular/HEAD/libs/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /libs/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zya/granular/HEAD/libs/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /libs/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zya/granular/HEAD/libs/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTML5 Granular Synthesiser 1.0 # 2 | 3 | The demo is a granular synthesiser with multi-touch support which uses Web Audio API for sound sampling and Processing.js for drawing and interactivity. 4 | 5 | Runs on: Chrome, Chrome iOS, Safari, Safari iOS, Firefox 6 | 7 | 8 | ----- 9 | Libraries used: 10 | 11 | Web Audio API : http://www.w3.org/TR/webaudio/ 12 | 13 | Processing.js : http://processingjs.org/ 14 | 15 | jQuery Knob : http://anthonyterrien.com/knob/ 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ehsan Ziya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | html{ 2 | width: 100%; 3 | height: 100%; 4 | padding: 0; 5 | margin: 0; 6 | overflow:hidden; 7 | } 8 | body{ 9 | width: 100%; 10 | height: 100%; 11 | padding: 0; 12 | margin: 0; 13 | 14 | 15 | } 16 | #header{ 17 | background: white; 18 | width: 100%; 19 | height: 5%; 20 | padding: 0; 21 | margin: 0; 22 | font-family: 'Open Sans', sans-serif; 23 | font-weight: 100; 24 | font-size: 1.3em; 25 | font-weight: 300; 26 | color: black; 27 | padding-top: 1vh; 28 | border-bottom: 1px solid white; 29 | } 30 | #waveform{ 31 | background: black; 32 | width: 100%; 33 | height: 71%; 34 | padding: 0; 35 | margin: 0; 36 | -moz-user-select: -moz-none; 37 | -khtml-user-select: none; 38 | -webkit-user-select: none; 39 | -o-user-select: none; 40 | user-select: none; 41 | 42 | 43 | 44 | 45 | } 46 | #controls{ 47 | border-top: 1px solid white; 48 | background: white; 49 | width: 100%; 50 | height: 23%; 51 | padding: 0; 52 | margin: 0; 53 | padding-top: 1.5%; 54 | text-align: center; 55 | z-index: 3; 56 | overflow: hidden; 57 | 58 | } 59 | 60 | #canvas{ 61 | 62 | position: absolute; 63 | -moz-user-select: -moz-none; 64 | -khtml-user-select: none; 65 | -webkit-user-select: none; 66 | -o-user-select: none; 67 | user-select: none; 68 | cursor: pointer; 69 | 70 | opacity: 0.0; 71 | } 72 | #canvas2{ 73 | position: absolute; 74 | -moz-user-select: -moz-none; 75 | -khtml-user-select: none; 76 | -webkit-user-select: none; 77 | -o-user-select: none; 78 | user-select: none; 79 | z-index: 5; 80 | 81 | 82 | 83 | } 84 | 85 | 86 | 87 | 88 | .label{ 89 | font-size: 1.3em; 90 | text-align: center; 91 | font-family: 'Open Sans', sans-serif; 92 | -webkit-font-smoothing: antialiased; 93 | font-weight: 300; 94 | color: black; 95 | margin-bottom: -15px; 96 | } 97 | 98 | 99 | 100 | #transopse{ 101 | width: 100%; 102 | margin: auto; 103 | display: inline; 104 | } 105 | 106 | #plus{ 107 | background-color: #2a6496; 108 | width: 48%; 109 | cursor: pointer; 110 | float: right; 111 | color: white; 112 | } 113 | #minus{ 114 | background-color: #2a6496; 115 | width: 48%; 116 | height: 40%; 117 | float: left; 118 | cursor: pointer; 119 | color: white; 120 | 121 | } 122 | 123 | #github{ 124 | text-align: right; 125 | } 126 | 127 | 128 | #helpbutton{ 129 | font-size: 2em; 130 | color:#2a6496; 131 | cursor: pointer; 132 | } 133 | 134 | #help{ 135 | width: 100%; 136 | height: 100%; 137 | background-color: black; 138 | z-index: 3; 139 | text-align: center; 140 | font-family: 'Open Sans', sans-serif; 141 | color:white; 142 | z-index: 3; 143 | } 144 | 145 | #drop{ 146 | width: 50%; 147 | height: 12%; 148 | border: 2px dotted white; 149 | margin: auto; 150 | font-size: 1.5em; 151 | margin-top:4%; 152 | } 153 | 154 | .sample{ 155 | background-color: white; 156 | border-right: black 2px solid; 157 | border-left: black 2px solid; 158 | color: black; 159 | padding-top: 0.5em; 160 | padding-bottom: 0.5em; 161 | cursor: pointer; 162 | } 163 | 164 | #x{ 165 | font-size: 0.8em; 166 | color: #888888; 167 | margin-bottom: -40px; 168 | } 169 | 170 | #description{ 171 | text-align: justify; 172 | margin:0; 173 | padding:0; 174 | font-size: 0.85em; 175 | font-weight: 100; 176 | } 177 | 178 | #badge{ 179 | float: right; 180 | position: absolute; 181 | right: 15px; 182 | } 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /js/gui.js: -------------------------------------------------------------------------------- 1 | function guiinit(){ 2 | var dialwidth = parseInt($('.col-sm-2').css('width')) - ( parseInt($('.col-sm-2').css('width')) / 6); 3 | 4 | var settings = { 5 | 'min':0, 6 | 'max':100, 7 | 'width' : dialwidth, 8 | "displayInput" : false, 9 | "angleArc" : 180, 10 | "angleOffset" : -90 11 | }; 12 | 13 | var bg = '#E4E4E4'; 14 | var fg = '#2a6496'; 15 | $("#attack").knob({ 16 | 'min':1, 17 | 'max':100, 18 | 'width' : dialwidth, 19 | "displayInput" : false, 20 | "val": 50, 21 | "angleArc" : 180, 22 | "angleOffset" : -90, 23 | 'bgColor': bg, 24 | 'fgColor': fg, 25 | "change": function(v){ 26 | attack = v / 100; 27 | 28 | } 29 | }); 30 | 31 | $("#release").knob({ 32 | 'min':1, 33 | 'max':100, 34 | 'width' : dialwidth, 35 | "displayInput" : false, 36 | "val": 50, 37 | "angleArc" : 180, 38 | "angleOffset" : -90, 39 | 'bgColor': bg, 40 | 'fgColor': fg, 41 | "change": function(v){ 42 | release = v / 100; 43 | 44 | } 45 | }); 46 | $('#density').knob({ 47 | 'min':0, 48 | 'max':100, 49 | 'width' : dialwidth, 50 | "displayInput" : false, 51 | "val": 50, 52 | "angleArc" : 180, 53 | "angleOffset" : -90, 54 | 'bgColor': bg, 55 | 'fgColor': fg, 56 | "change": function(v){ 57 | density = v / 100; 58 | 59 | } 60 | }); 61 | $('#spread').knob({ 62 | 'min':0, 63 | 'max':200, 64 | 'width' : dialwidth, 65 | "displayInput" : false, 66 | "val": 50, 67 | "angleArc" : 180, 68 | "angleOffset" : -90, 69 | 'bgColor': bg, 70 | 'fgColor': fg, 71 | "change": function(v){ 72 | spread = v / 100; 73 | 74 | 75 | } 76 | }); 77 | $('#pan').knob({ 78 | 'min':0, 79 | 'max':200, 80 | 'width' : dialwidth, 81 | "displayInput" : false, 82 | "val": 50, 83 | "angleArc" : 180, 84 | "angleOffset" : -90, 85 | 'bgColor': bg, 86 | 'fgColor': fg, 87 | "change": function(v){ 88 | pan = v / 100; 89 | 90 | 91 | } 92 | }); 93 | 94 | $('#minus').click(function(){ 95 | trans = trans * 0.5; 96 | $('#minus').css('opacity',0.3); 97 | setTimeout(function(){ 98 | $('#minus').css('opacity',1); 99 | },200); 100 | }); 101 | 102 | $('#plus').click(function(){ 103 | trans = trans * 2; 104 | $('#plus').css('opacity',0.3); 105 | setTimeout(function(){ 106 | $('#plus').css('opacity',1); 107 | },200); 108 | }); 109 | 110 | var minus = document.getElementById('minus'); 111 | minus.addEventListener('touchstart',function(e){ 112 | e.preventDefault(); 113 | $('#minus').css('opacity',0.3); 114 | trans = trans * 0.5; 115 | }); 116 | minus.addEventListener('touchend',function(e){ 117 | e.preventDefault(); 118 | $('#minus').css('opacity',1); 119 | }); 120 | 121 | var plus = document.getElementById('plus'); 122 | plus.addEventListener('touchstart',function(e){ 123 | e.preventDefault(); 124 | $('#plus').css('opacity',0.3); 125 | trans = trans * 2; 126 | }); 127 | plus.addEventListener('touchend',function(e){ 128 | e.preventDefault(); 129 | $('#plus').css('opacity',1); 130 | }); 131 | 132 | 133 | function load(){ 134 | $('#canvas').show(); 135 | $('#canvas2').show(); 136 | 137 | $('#canvas').animate({ 138 | opacity : 1 139 | },1000); 140 | 141 | $('#canvas2').animate({ 142 | opacity : 1 143 | },1000); 144 | 145 | $('#help').animate({ 146 | opacity : 0 147 | },1000,function(){ 148 | $('#help').hide(); 149 | helpvisible = false; 150 | }); 151 | } 152 | 153 | $('#canvas2').hide(); 154 | $('#canvas').hide(); 155 | $('#helpbutton').click(function(){ 156 | if(helpvisible){ 157 | load(); 158 | helpvisible = false; 159 | 160 | }else{ 161 | //$('#help').css('opacity','0'); 162 | $('#canvas2').animate({ 163 | opacity:0.1 164 | },1000,function(){ 165 | $('#help').css('opacity',0); 166 | 167 | $('#canvas2').hide(); 168 | $('#help').animate({ 169 | opacity : 1 170 | },1000); 171 | 172 | $('#help').show(); 173 | 174 | }); 175 | 176 | $('#canvas').animate({ 177 | opacity:0.0 178 | },1000,function(){ 179 | $('#help').show(); 180 | $('#canvas').hide(); 181 | }); 182 | 183 | helpvisible = true; 184 | } 185 | 186 | }); 187 | 188 | $('.sample').hover(function(){ 189 | $(this).css('opacity','0.5'); 190 | },function(){ 191 | $(this).css('opacity','1'); 192 | }); 193 | 194 | 195 | $('#sample1').click(function(){ 196 | load(); 197 | }); 198 | 199 | $('#sample2').click(function(){ 200 | //loading the sound with XML HTTP REQUEST 201 | 202 | var request = new XMLHttpRequest(); 203 | request.open('GET','audio/synth.mp3',true); 204 | request.responseType = "arraybuffer"; 205 | request.onload = function(){ 206 | context.decodeAudioData(request.response,function(b){ 207 | buffer = b; //set the buffer 208 | data = buffer.getChannelData(0); 209 | isloaded = true; 210 | var canvas1 = document.getElementById('canvas'); 211 | //initialize the processing draw when the buffer is ready 212 | var processing = new Processing(canvas1,waveformdisplay); 213 | load(); 214 | 215 | },function(){ 216 | console.log('loading failed'); 217 | alert('loading failed'); 218 | 219 | }); 220 | }; 221 | request.send(); 222 | 223 | 224 | }); 225 | 226 | //drop 227 | var drop = document.getElementById('waveform'); 228 | 229 | drop.addEventListener("dragover",function(e){ 230 | //prevents from loading the file in a new page 231 | e.preventDefault(); 232 | },false); 233 | drop.addEventListener('drop',function(e){ 234 | e.preventDefault(); 235 | var file = e.dataTransfer.files[0]; 236 | var reader = new FileReader(); 237 | reader.onload = function(e){ 238 | var array = e.target.result; 239 | context.decodeAudioData(array,function(b){ 240 | 241 | buffer = b 242 | data = buffer.getChannelData(0); 243 | var canvas1 = document.getElementById('canvas'); 244 | var processing = new Processing(canvas1,waveformdisplay); 245 | load(); 246 | 247 | },function(){ 248 | console.log('loading failed'); 249 | alert('loading failed'); 250 | }); 251 | } 252 | reader.readAsArrayBuffer(file); 253 | },false); 254 | 255 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Web Audio Granular Synthesiser 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 43 | 44 |
45 | 46 | 47 | 48 |
49 | See my Experiment on ChromeExperiments.com 50 |
51 |
x axis - grain position


y axis - grain amplitude
52 |
53 |
54 | 55 |
56 |

57 |
58 |
59 |
sample file 1 - guitar
60 |
sample file 2 - synth
61 |
62 |

63 | 84 | 85 |
86 | 87 |
88 | 89 | 90 |
91 |
92 |

93 |

94 | 95 |
96 | 97 |
98 |

99 | 100 |
101 | 102 |
103 |

104 | 105 |
106 | 107 |
108 |

109 | 110 |
111 | 112 |
113 |

114 | 115 |
116 | 117 | 133 | 134 |
135 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext; 2 | var context = new AudioContext(); 3 | 4 | var buffer,buffer2; //global variables for sample files 5 | 6 | //master gain node 7 | var master = context.createGain(); 8 | master.connect(context.destination); 9 | 10 | //global varuables 11 | var w,h; 12 | var data; 13 | var drawingdata = []; //an array that keeps the data 14 | var voices = []; //an array for touch events - polyphonic 15 | var voicesmono = []; //this will be used for mouse events - monophonic 16 | var isloaded = false; 17 | var X = 0; 18 | var Y = 0; 19 | var mouseState = false; 20 | var helpvisible = true; 21 | 22 | //control initial settings 23 | var attack = 0.40; 24 | var release = 0.40; 25 | var density = 0.85; 26 | var spread = 0.2; 27 | var reverb = 0.5; 28 | var pan = 0.1; 29 | var trans = 1; 30 | 31 | 32 | //the grain class 33 | function grain(p,buffer,positionx,positiony,attack,release,spread,pan){ 34 | 35 | var that = this; //for scope issues 36 | this.now = context.currentTime; //update the time value 37 | //create the source 38 | this.source = context.createBufferSource(); 39 | this.source.playbackRate.value = this.source.playbackRate.value * trans; 40 | this.source.buffer = buffer; 41 | //create the gain for enveloping 42 | this.gain = context.createGain(); 43 | 44 | //experimenting with adding a panner node - not all the grains will be panned for better performance 45 | var yes = parseInt(p.random(3),10); 46 | if( yes === 1){ 47 | this.panner = context.createPanner(); 48 | this.panner.panningModel = "equalpower"; 49 | this.panner.distanceModel = "linear"; 50 | this.panner.setPosition(p.random(pan * -1,pan),0,0); 51 | //connections 52 | this.source.connect(this.panner); 53 | this.panner.connect(this.gain); 54 | }else{ 55 | this.source.connect(this.gain); 56 | } 57 | 58 | 59 | this.gain.connect(master); 60 | 61 | //update the position and calcuate the offset 62 | this.positionx = positionx; 63 | this.offset = this.positionx * (buffer.duration / w); //pixels to seconds 64 | 65 | //update and calculate the amplitude 66 | this.positiony = positiony; 67 | this.amp = this.positiony / h; 68 | this.amp = p.map(this.amp,0.0,1.0,1.0,0.0) * 0.7; 69 | 70 | //parameters 71 | this.attack = attack * 0.4; 72 | this.release = release * 1.5; 73 | 74 | if(this.release < 0){ 75 | this.release = 0.1; // 0 - release causes mute for some reason 76 | } 77 | this.spread = spread; 78 | 79 | this.randomoffset = (Math.random() * this.spread) - (this.spread / 2); //in seconds 80 | ///envelope 81 | this.source.start(this.now,Math.max(0, this.offset + this.randomoffset),this.attack + this.release); //parameters (when,offset,duration) 82 | this.gain.gain.setValueAtTime(0.0, this.now); 83 | this.gain.gain.linearRampToValueAtTime(this.amp,this.now + this.attack); 84 | this.gain.gain.linearRampToValueAtTime(0,this.now + (this.attack + this.release) ); 85 | 86 | //garbage collection 87 | this.source.stop(this.now + this.attack + this.release + 0.1); 88 | var tms = (this.attack + this.release) * 1000; //calculate the time in miliseconds 89 | setTimeout(function(){ 90 | that.gain.disconnect(); 91 | if(yes === 1){ 92 | that.panner.disconnect(); 93 | } 94 | },tms + 200); 95 | 96 | //drawing the lines 97 | p.stroke(p.random(125) + 125,p.random(250),p.random(250)); //,(this.amp + 0.8) * 255 98 | //p.strokeWeight(this.amp * 5); 99 | this.randomoffsetinpixels = this.randomoffset / (buffer.duration / w); 100 | //p.background(); 101 | p.line(this.positionx + this.randomoffsetinpixels,0,this.positionx + this.randomoffsetinpixels,p.height); 102 | setTimeout(function(){ 103 | p.background(); 104 | p.line(that.positionx + that.randomoffsetinpixels,0,that.positionx + that.randomoffsetinpixels,p.height); 105 | },200); 106 | 107 | } 108 | 109 | 110 | //the voice class 111 | function voice(id){ 112 | 113 | this.touchid = id; //the id of the touch event 114 | } 115 | 116 | //play function for mouse event 117 | voice.prototype.playmouse = function(p){ 118 | this.grains = []; 119 | this.grainscount = 0; 120 | var that = this; //for scope issues 121 | this.play = function(){ 122 | //create new grain 123 | var g = new grain(p,buffer,p.mouseX,p.mouseY,attack,release,spread,pan); 124 | //push to the array 125 | that.grains[that.graincount] = g; 126 | that.graincount+=1; 127 | 128 | if(that.graincount > 20){ 129 | that.graincount = 0; 130 | } 131 | //next interval 132 | this.dens = p.map(density,1,0,0,1); 133 | this.interval = (this.dens * 500) + 70; 134 | that.timeout = setTimeout(that.play,this.interval); 135 | 136 | } 137 | this.play(); 138 | } 139 | //play function for touch events - this will get the position from touch events 140 | voice.prototype.playtouch = function(p,positionx,positiony){ 141 | //this.positiony = positiony; 142 | this.positionx = positionx; 143 | this.positiony = positiony; 144 | this.grains = []; 145 | this.graincount = 0; 146 | 147 | var that = this; //for scope issues 148 | this.play = function(){ 149 | //create new grain 150 | var g = new grain(p,buffer,that.positionx,that.positiony,attack,release,spread,pan); 151 | 152 | //push to the array 153 | that.grains[that.graincount] = g; 154 | that.graincount+=1; 155 | 156 | if(that.graincount > 30){ 157 | that.graincount = 0; 158 | } 159 | //next interval 160 | this.dens = p.map(density,1,0,0,1); 161 | this.interval = (this.dens * 500) + 70; 162 | that.timeout = setTimeout( that.play, this.interval ); 163 | } 164 | this.play(); 165 | } 166 | 167 | //stop method 168 | voice.prototype.stop = function(){ 169 | clearTimeout(this.timeout); 170 | } 171 | 172 | //loading the first sound with XML HTTP REQUEST 173 | var request = new XMLHttpRequest(); 174 | request.open('GET','audio/guitar.mp3',true); 175 | request.responseType = "arraybuffer"; 176 | request.onload = function(){ 177 | context.decodeAudioData(request.response,function(b){ 178 | buffer = b; //set the buffer 179 | data = buffer.getChannelData(0); 180 | isloaded = true; 181 | var canvas1 = document.getElementById('canvas'); 182 | //initialize the processing draw when the buffer is ready 183 | var processing = new Processing(canvas1,waveformdisplay); 184 | 185 | },function(){ 186 | console.log('loading failed') 187 | }); 188 | }; 189 | request.send(); 190 | 191 | 192 | //processing - waveform display - canvas 193 | function waveformdisplay(p){ 194 | w = parseInt($('#waveform').css('width'),10); //get the width 195 | h = parseInt($('#waveform').css('height'),10); //get the height 196 | 197 | //draw the buffer 198 | function drawBuffer() { 199 | var step = Math.ceil( data.length / w ); 200 | var amp = h / 2; 201 | 202 | p.background(0); 203 | for( var i=0; i < w; i++ ){ 204 | var min = 1.0; 205 | var max = -1.0; 206 | 207 | for( j=0; j max){ 213 | max = datum; 214 | } 215 | 216 | } 217 | //p.stroke(p.random(255),p.random(255),p.random(255)); 218 | p.rect(i,(1+min)*amp,1,Math.max(1,(max-min)*amp)); 219 | } 220 | } 221 | 222 | p.setup = function(){ 223 | p.size(w,h); 224 | p.background(0);//background black 225 | 226 | //change the size on resize 227 | $(window).resize(function(){ 228 | w = parseInt($('#waveform').css('width'),10); 229 | h = parseInt($('#waveform').css('height'),10); 230 | p.size(w,h); 231 | //redraw buffer on resize 232 | p.stroke(255); 233 | drawBuffer(); 234 | 235 | }); 236 | p.strokeWeight(0.01); 237 | p.stroke(255); 238 | drawBuffer(); 239 | p.noLoop(); 240 | 241 | }; 242 | 243 | } 244 | 245 | //processing - grain display and main interaction system 246 | function grainsdisplay(p){ 247 | w = parseInt($('#waveform').css('width'),10); 248 | h = parseInt($('#waveform').css('height'),10); 249 | 250 | //setup 251 | p.setup = function(){ 252 | p.size(w,h); 253 | p.background(0,0);//backgorund black alpha 0 254 | p.frameRate(24); 255 | p.noLoop(); 256 | 257 | //change the size on resize 258 | $(window).resize(function(){ 259 | w = parseInt($('#waveform').css('width'),10); 260 | h = parseInt($('#waveform').css('height'),10); 261 | p.size(w,h); 262 | 263 | }); 264 | 265 | }; 266 | 267 | 268 | //mouse events 269 | $('#canvas2').mousedown(function(){ 270 | mouseState = true; 271 | 272 | if(mouseState){ 273 | var v = new voice(); 274 | v.playmouse(p); 275 | voicesmono[0] = v; //have in the array 276 | } 277 | }).mouseup(function(){ 278 | mouseState = false; 279 | for(var i = 0; i < voicesmono.length;i++){ 280 | voicesmono[i].stop(); 281 | voicesmono.splice(i); 282 | } 283 | setTimeout(function(){ 284 | p.background(); 285 | },300); 286 | }).mousemove(function(){ 287 | X = p.mouseX; 288 | Y = p.mouseY; 289 | 290 | }); 291 | //safety for when the mouse is out of the canvas 292 | $(document).mousemove(function(e){ 293 | if(e.target.id !== 'canvas2'){ 294 | for(var i = 0; i < voicesmono.length;i++){ 295 | voicesmono[i].stop(); 296 | voicesmono.splice(i); 297 | setTimeout(function(){ 298 | p.background(); 299 | },300); 300 | } 301 | } 302 | }); 303 | 304 | //touch events 305 | var canvas2 = document.getElementById('canvas2'); 306 | canvas2.addEventListener('touchstart',function(event){ 307 | 308 | event.preventDefault(); //to prevent scrolling 309 | 310 | //4 touches glitches on ipad 311 | if(event.touches.length < 4){ 312 | 313 | for(var i = 0; i < event.touches.length; i++){ 314 | 315 | if(event.touches[i].target.id === 'canvas2'){ 316 | var id = event.touches[i].identifier; //the id will be used for voice stop 317 | var v = new voice(id); 318 | var clientX = event.touches[i].clientX; 319 | var clientY = event.touches[i].clientY; 320 | 321 | //multitouch optimization 322 | var interval; 323 | //calculate the reverse interval 324 | if(event.touches.length > 1){ 325 | interval = p.map(density,0,1,1,0.7); 326 | }else{ 327 | interval = p.map(density,0,1,1,0); 328 | } 329 | 330 | //play 331 | v.playtouch(p,clientX,clientY,interval); 332 | voices.push(v); 333 | } 334 | } 335 | } 336 | }); 337 | 338 | canvas2.addEventListener('touchend',function(event){ 339 | 340 | for(var i = 0; i < voices.length; i++){ 341 | 342 | for(var j = 0; j < event.changedTouches.length;j++){ 343 | 344 | if(voices[i].touchid === event.changedTouches[j].identifier){ 345 | 346 | voices[i].stop(); 347 | 348 | } 349 | } 350 | } 351 | 352 | //safety and garbage collection 353 | if(event.touches.length < 1){ 354 | for(var i = 0; i < voices.length; i++){ 355 | voices[i].stop(); 356 | } 357 | voices = []; 358 | setTimeout(function(){ 359 | p.background(); 360 | 361 | },200); 362 | } 363 | 364 | 365 | }); 366 | 367 | canvas2.addEventListener('touchmove',function(event){ 368 | event.preventDefault(); 369 | 370 | for(var i = 0; i < voices.length; i++){ 371 | 372 | for(var j = 0; j < event.changedTouches.length;j++){ 373 | 374 | if(voices[i].touchid === event.changedTouches[j].identifier){ 375 | if(event.changedTouches[j].clientY < h + 50){ 376 | voices[i].positiony = event.changedTouches[j].clientY; 377 | voices[i].positionx = event.changedTouches[j].clientX; 378 | }else{ 379 | voices[i].stop(); 380 | } 381 | } 382 | } 383 | } 384 | }); 385 | } 386 | 387 | 388 | //onload 389 | $(document).ready(function(){ 390 | window.history.pushState(null,null,''); 391 | //grain display init 392 | var canvas2 = document.getElementById('canvas2'); 393 | var processing = new Processing(canvas2,grainsdisplay); 394 | 395 | document.addEventListener("touchmove",function(e){ 396 | e.preventDefault(); 397 | }); 398 | //gui 399 | guiinit(); 400 | 401 | }); 402 | -------------------------------------------------------------------------------- /libs/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.3 (http://getbootstrap.com) 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | 7 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);background-repeat:repeat-x;border-color:#2b669a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff2d6ca2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff419641',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffeb9316',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);background-repeat:repeat-x;border-color:#b92c28;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc12e2a',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2aabd2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff3f3f3',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff282828',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /libs/js/jquery.knob.js: -------------------------------------------------------------------------------- 1 | /*!jQuery Knob*/ 2 | /** 3 | * Downward compatible, touchable dial 4 | * 5 | * Version: 1.2.0 (15/07/2012) 6 | * Requires: jQuery v1.7+ 7 | * 8 | * Copyright (c) 2012 Anthony Terrien 9 | * Under MIT and GPL licenses: 10 | * http://www.opensource.org/licenses/mit-license.php 11 | * http://www.gnu.org/licenses/gpl.html 12 | * 13 | * Thanks to vor, eskimoblood, spiffistan, FabrizioC 14 | */ 15 | (function($) { 16 | 17 | /** 18 | * Kontrol library 19 | */ 20 | "use strict"; 21 | 22 | /** 23 | * Definition of globals and core 24 | */ 25 | var k = {}, // kontrol 26 | max = Math.max, 27 | min = Math.min; 28 | 29 | k.c = {}; 30 | k.c.d = $(document); 31 | k.c.t = function (e) { 32 | return e.originalEvent.touches.length - 1; 33 | }; 34 | 35 | /** 36 | * Kontrol Object 37 | * 38 | * Definition of an abstract UI control 39 | * 40 | * Each concrete component must call this one. 41 | * 42 | * k.o.call(this); 43 | * 44 | */ 45 | k.o = function () { 46 | var s = this; 47 | 48 | this.o = null; // array of options 49 | this.$ = null; // jQuery wrapped element 50 | this.i = null; // mixed HTMLInputElement or array of HTMLInputElement 51 | this.g = null; // 2D graphics context for 'pre-rendering' 52 | this.v = null; // value ; mixed array or integer 53 | this.cv = null; // change value ; not commited value 54 | this.x = 0; // canvas x position 55 | this.y = 0; // canvas y position 56 | this.$c = null; // jQuery canvas element 57 | this.c = null; // rendered canvas context 58 | this.t = 0; // touches index 59 | this.isInit = false; 60 | this.fgColor = null; // main color 61 | this.pColor = null; // previous color 62 | this.dH = null; // draw hook 63 | this.cH = null; // change hook 64 | this.eH = null; // cancel hook 65 | this.rH = null; // release hook 66 | 67 | this.run = function () { 68 | var cf = function (e, conf) { 69 | var k; 70 | for (k in conf) { 71 | s.o[k] = conf[k]; 72 | } 73 | s.init(); 74 | s._configure() 75 | ._draw(); 76 | }; 77 | 78 | if(this.$.data('kontroled')) return; 79 | this.$.data('kontroled', true); 80 | 81 | this.extend(); 82 | this.o = $.extend( 83 | { 84 | // Config 85 | min : this.$.data('min') || 0, 86 | max : this.$.data('max') || 100, 87 | stopper : true, 88 | readOnly : this.$.data('readonly'), 89 | 90 | // UI 91 | cursor : (this.$.data('cursor') === true && 30) 92 | || this.$.data('cursor') 93 | || 0, 94 | thickness : this.$.data('thickness') || 0.35, 95 | lineCap : this.$.data('linecap') || 'butt', 96 | width : this.$.data('width') || 200, 97 | height : this.$.data('height') || 200, 98 | displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'), 99 | displayPrevious : this.$.data('displayprevious'), 100 | fgColor : this.$.data('fgcolor') || '#87CEEB', 101 | inputColor: this.$.data('inputcolor') || this.$.data('fgcolor') || '#87CEEB', 102 | inline : false, 103 | step : this.$.data('step') || 1, 104 | 105 | // Hooks 106 | draw : null, // function () {} 107 | change : null, // function (value) {} 108 | cancel : null, // function () {} 109 | release : null // function (value) {} 110 | }, this.o 111 | ); 112 | 113 | // routing value 114 | if(this.$.is('fieldset')) { 115 | 116 | // fieldset = array of integer 117 | this.v = {}; 118 | this.i = this.$.find('input') 119 | this.i.each(function(k) { 120 | var $this = $(this); 121 | s.i[k] = $this; 122 | s.v[k] = $this.val(); 123 | 124 | $this.bind( 125 | 'change' 126 | , function () { 127 | var val = {}; 128 | val[k] = $this.val(); 129 | s.val(val); 130 | } 131 | ); 132 | }); 133 | this.$.find('legend').remove(); 134 | 135 | } else { 136 | // input = integer 137 | this.i = this.$; 138 | this.v = this.$.val(); 139 | (this.v == '') && (this.v = this.o.min); 140 | 141 | this.$.bind( 142 | 'change' 143 | , function () { 144 | s.val(s._validate(s.$.val())); 145 | } 146 | ); 147 | } 148 | 149 | (!this.o.displayInput) && this.$.hide(); 150 | 151 | this.$c = $(''); 154 | this.c = this.$c[0].getContext("2d"); 155 | 156 | this.$ 157 | .wrap($('
')) 160 | .before(this.$c); 161 | 162 | if (this.v instanceof Object) { 163 | this.cv = {}; 164 | this.copy(this.v, this.cv); 165 | } else { 166 | this.cv = this.v; 167 | } 168 | 169 | this.$ 170 | .bind("configure", cf) 171 | .parent() 172 | .bind("configure", cf); 173 | 174 | this._listen() 175 | ._configure() 176 | ._xy() 177 | .init(); 178 | 179 | this.isInit = true; 180 | 181 | this._draw(); 182 | 183 | return this; 184 | }; 185 | 186 | this._draw = function () { 187 | 188 | // canvas pre-rendering 189 | var d = true, 190 | c = document.createElement('canvas'); 191 | 192 | c.width = s.o.width; 193 | c.height = s.o.height; 194 | s.g = c.getContext('2d'); 195 | 196 | s.clear(); 197 | 198 | s.dH 199 | && (d = s.dH()); 200 | 201 | (d !== false) && s.draw(); 202 | 203 | s.c.drawImage(c, 0, 0); 204 | c = null; 205 | }; 206 | 207 | this._touch = function (e) { 208 | 209 | var touchMove = function (e) { 210 | 211 | var v = s.xy2val( 212 | e.originalEvent.touches[s.t].pageX, 213 | e.originalEvent.touches[s.t].pageY 214 | ); 215 | 216 | if (v == s.cv) return; 217 | 218 | if ( 219 | s.cH 220 | && (s.cH(v) === false) 221 | ) return; 222 | 223 | 224 | s.change(s._validate(v)); 225 | s._draw(); 226 | }; 227 | 228 | // get touches index 229 | this.t = k.c.t(e); 230 | 231 | // First touch 232 | touchMove(e); 233 | 234 | // Touch events listeners 235 | k.c.d 236 | .bind("touchmove.k", touchMove) 237 | .bind( 238 | "touchend.k" 239 | , function () { 240 | k.c.d.unbind('touchmove.k touchend.k'); 241 | 242 | if ( 243 | s.rH 244 | && (s.rH(s.cv) === false) 245 | ) return; 246 | 247 | s.val(s.cv); 248 | } 249 | ); 250 | 251 | return this; 252 | }; 253 | 254 | this._mouse = function (e) { 255 | 256 | var mouseMove = function (e) { 257 | var v = s.xy2val(e.pageX, e.pageY); 258 | if (v == s.cv) return; 259 | 260 | if ( 261 | s.cH 262 | && (s.cH(v) === false) 263 | ) return; 264 | 265 | s.change(s._validate(v)); 266 | s._draw(); 267 | }; 268 | 269 | // First click 270 | mouseMove(e); 271 | 272 | // Mouse events listeners 273 | k.c.d 274 | .bind("mousemove.k", mouseMove) 275 | .bind( 276 | // Escape key cancel current change 277 | "keyup.k" 278 | , function (e) { 279 | if (e.keyCode === 27) { 280 | k.c.d.unbind("mouseup.k mousemove.k keyup.k"); 281 | 282 | if ( 283 | s.eH 284 | && (s.eH() === false) 285 | ) return; 286 | 287 | s.cancel(); 288 | } 289 | } 290 | ) 291 | .bind( 292 | "mouseup.k" 293 | , function (e) { 294 | k.c.d.unbind('mousemove.k mouseup.k keyup.k'); 295 | 296 | if ( 297 | s.rH 298 | && (s.rH(s.cv) === false) 299 | ) return; 300 | 301 | s.val(s.cv); 302 | } 303 | ); 304 | 305 | return this; 306 | }; 307 | 308 | this._xy = function () { 309 | var o = this.$c.offset(); 310 | this.x = o.left; 311 | this.y = o.top; 312 | return this; 313 | }; 314 | 315 | this._listen = function () { 316 | 317 | if (!this.o.readOnly) { 318 | this.$c 319 | .bind( 320 | "mousedown" 321 | , function (e) { 322 | e.preventDefault(); 323 | s._xy()._mouse(e); 324 | } 325 | ) 326 | .bind( 327 | "touchstart" 328 | , function (e) { 329 | e.preventDefault(); 330 | s._xy()._touch(e); 331 | } 332 | ); 333 | this.listen(); 334 | } else { 335 | this.$.attr('readonly', 'readonly'); 336 | } 337 | 338 | return this; 339 | }; 340 | 341 | this._configure = function () { 342 | 343 | // Hooks 344 | if (this.o.draw) this.dH = this.o.draw; 345 | if (this.o.change) this.cH = this.o.change; 346 | if (this.o.cancel) this.eH = this.o.cancel; 347 | if (this.o.release) this.rH = this.o.release; 348 | 349 | if (this.o.displayPrevious) { 350 | this.pColor = this.h2rgba(this.o.fgColor, "0.4"); 351 | this.fgColor = this.h2rgba(this.o.fgColor, "0.6"); 352 | } else { 353 | this.fgColor = this.o.fgColor; 354 | } 355 | 356 | return this; 357 | }; 358 | 359 | this._clear = function () { 360 | this.$c[0].width = this.$c[0].width; 361 | }; 362 | 363 | this._validate = function(v) { 364 | return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step; 365 | }; 366 | 367 | // Abstract methods 368 | this.listen = function () {}; // on start, one time 369 | this.extend = function () {}; // each time configure triggered 370 | this.init = function () {}; // each time configure triggered 371 | this.change = function (v) {}; // on change 372 | this.val = function (v) {}; // on release 373 | this.xy2val = function (x, y) {}; // 374 | this.draw = function () {}; // on change / on release 375 | this.clear = function () { this._clear(); }; 376 | 377 | // Utils 378 | this.h2rgba = function (h, a) { 379 | var rgb; 380 | h = h.substring(1,7) 381 | rgb = [parseInt(h.substring(0,2),16) 382 | ,parseInt(h.substring(2,4),16) 383 | ,parseInt(h.substring(4,6),16)]; 384 | return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")"; 385 | }; 386 | 387 | this.copy = function (f, t) { 388 | for (var i in f) { t[i] = f[i]; } 389 | }; 390 | }; 391 | 392 | 393 | /** 394 | * k.Dial 395 | */ 396 | k.Dial = function () { 397 | k.o.call(this); 398 | 399 | this.startAngle = null; 400 | this.xy = null; 401 | this.radius = null; 402 | this.lineWidth = null; 403 | this.cursorExt = null; 404 | this.w2 = null; 405 | this.PI2 = 2*Math.PI; 406 | 407 | this.extend = function () { 408 | this.o = $.extend( 409 | { 410 | bgColor : this.$.data('bgcolor') || '#EEEEEE', 411 | angleOffset : this.$.data('angleoffset') || 0, 412 | angleArc : this.$.data('anglearc') || 360, 413 | inline : true 414 | }, this.o 415 | ); 416 | }; 417 | 418 | this.val = function (v) { 419 | if (null != v) { 420 | this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v; 421 | this.v = this.cv; 422 | this.$.val(this.v); 423 | this._draw(); 424 | } else { 425 | return this.v; 426 | } 427 | }; 428 | 429 | this.xy2val = function (x, y) { 430 | var a, ret; 431 | 432 | a = Math.atan2( 433 | x - (this.x + this.w2) 434 | , - (y - this.y - this.w2) 435 | ) - this.angleOffset; 436 | 437 | if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) { 438 | // if isset angleArc option, set to min if .5 under min 439 | a = 0; 440 | } else if (a < 0) { 441 | a += this.PI2; 442 | } 443 | 444 | ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc)) 445 | + this.o.min; 446 | 447 | this.o.stopper 448 | && (ret = max(min(ret, this.o.max), this.o.min)); 449 | 450 | return ret; 451 | }; 452 | 453 | this.listen = function () { 454 | // bind MouseWheel 455 | var s = this, 456 | mw = function (e) { 457 | e.preventDefault(); 458 | var ori = e.originalEvent 459 | ,deltaX = ori.detail || ori.wheelDeltaX 460 | ,deltaY = ori.detail || ori.wheelDeltaY 461 | ,v = parseInt(s.$.val()) + (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0); 462 | 463 | if ( 464 | s.cH 465 | && (s.cH(v) === false) 466 | ) return; 467 | 468 | s.val(v); 469 | } 470 | , kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step}; 471 | 472 | this.$ 473 | .bind( 474 | "keydown" 475 | ,function (e) { 476 | var kc = e.keyCode; 477 | 478 | // numpad support 479 | if(kc >= 96 && kc <= 105) { 480 | kc = e.keyCode = kc - 48; 481 | } 482 | 483 | kval = parseInt(String.fromCharCode(kc)); 484 | 485 | if (isNaN(kval)) { 486 | 487 | (kc !== 13) // enter 488 | && (kc !== 8) // bs 489 | && (kc !== 9) // tab 490 | && (kc !== 189) // - 491 | && e.preventDefault(); 492 | 493 | // arrows 494 | if ($.inArray(kc,[37,38,39,40]) > -1) { 495 | e.preventDefault(); 496 | 497 | var v = parseInt(s.$.val()) + kv[kc] * m; 498 | 499 | s.o.stopper 500 | && (v = max(min(v, s.o.max), s.o.min)); 501 | 502 | s.change(v); 503 | s._draw(); 504 | 505 | // long time keydown speed-up 506 | to = window.setTimeout( 507 | function () { m*=2; } 508 | ,30 509 | ); 510 | } 511 | } 512 | } 513 | ) 514 | .bind( 515 | "keyup" 516 | ,function (e) { 517 | if (isNaN(kval)) { 518 | if (to) { 519 | window.clearTimeout(to); 520 | to = null; 521 | m = 1; 522 | s.val(s.$.val()); 523 | } 524 | } else { 525 | // kval postcond 526 | (s.$.val() > s.o.max && s.$.val(s.o.max)) 527 | || (s.$.val() < s.o.min && s.$.val(s.o.min)); 528 | } 529 | 530 | } 531 | ); 532 | 533 | this.$c.bind("mousewheel DOMMouseScroll", mw); 534 | this.$.bind("mousewheel DOMMouseScroll", mw) 535 | }; 536 | 537 | this.init = function () { 538 | 539 | if ( 540 | this.v < this.o.min 541 | || this.v > this.o.max 542 | ) this.v = this.o.min; 543 | 544 | this.$.val(this.v); 545 | this.w2 = this.o.width / 2; 546 | this.cursorExt = this.o.cursor / 100; 547 | this.xy = this.w2; 548 | this.lineWidth = this.xy * this.o.thickness; 549 | this.lineCap = this.o.lineCap; 550 | this.radius = this.xy - this.lineWidth / 2; 551 | 552 | this.o.angleOffset 553 | && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset); 554 | 555 | this.o.angleArc 556 | && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc); 557 | 558 | // deg to rad 559 | this.angleOffset = this.o.angleOffset * Math.PI / 180; 560 | this.angleArc = this.o.angleArc * Math.PI / 180; 561 | 562 | // compute start and end angles 563 | this.startAngle = 1.5 * Math.PI + this.angleOffset; 564 | this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc; 565 | 566 | var s = max( 567 | String(Math.abs(this.o.max)).length 568 | , String(Math.abs(this.o.min)).length 569 | , 2 570 | ) + 2; 571 | 572 | this.o.displayInput 573 | && this.i.css({ 574 | 'width' : ((this.o.width / 2 + 4) >> 0) + 'px' 575 | ,'height' : ((this.o.width / 3) >> 0) + 'px' 576 | ,'position' : 'absolute' 577 | ,'vertical-align' : 'middle' 578 | ,'margin-top' : ((this.o.width / 3) >> 0) + 'px' 579 | ,'margin-left' : '-' + ((this.o.width * 3 / 4 + 2) >> 0) + 'px' 580 | ,'border' : 0 581 | ,'background' : 'none' 582 | ,'font' : 'bold ' + ((this.o.width / s) >> 0) + 'px Arial' 583 | ,'text-align' : 'center' 584 | ,'color' : this.o.inputColor || this.o.fgColor 585 | ,'padding' : '0px' 586 | ,'-webkit-appearance': 'none' 587 | }) 588 | || this.i.css({ 589 | 'width' : '0px' 590 | ,'visibility' : 'hidden' 591 | }); 592 | }; 593 | 594 | this.change = function (v) { 595 | this.cv = v; 596 | this.$.val(v); 597 | }; 598 | 599 | this.angle = function (v) { 600 | return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min); 601 | }; 602 | 603 | this.draw = function () { 604 | 605 | var c = this.g, // context 606 | a = this.angle(this.cv) // Angle 607 | , sat = this.startAngle // Start angle 608 | , eat = sat + a // End angle 609 | , sa, ea // Previous angles 610 | , r = 1; 611 | 612 | c.lineWidth = this.lineWidth; 613 | 614 | c.lineCap = this.lineCap; 615 | 616 | this.o.cursor 617 | && (sat = eat - this.cursorExt) 618 | && (eat = eat + this.cursorExt); 619 | 620 | c.beginPath(); 621 | c.strokeStyle = this.o.bgColor; 622 | c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true); 623 | c.stroke(); 624 | 625 | if (this.o.displayPrevious) { 626 | ea = this.startAngle + this.angle(this.v); 627 | sa = this.startAngle; 628 | this.o.cursor 629 | && (sa = ea - this.cursorExt) 630 | && (ea = ea + this.cursorExt); 631 | 632 | c.beginPath(); 633 | c.strokeStyle = this.pColor; 634 | c.arc(this.xy, this.xy, this.radius, sa, ea, false); 635 | c.stroke(); 636 | r = (this.cv == this.v); 637 | } 638 | 639 | c.beginPath(); 640 | c.strokeStyle = r ? this.o.fgColor : this.fgColor ; 641 | c.arc(this.xy, this.xy, this.radius, sat, eat, false); 642 | c.stroke(); 643 | }; 644 | 645 | this.cancel = function () { 646 | this.val(this.v); 647 | }; 648 | }; 649 | 650 | $.fn.dial = $.fn.knob = function (o) { 651 | return this.each( 652 | function () { 653 | var d = new k.Dial(); 654 | d.o = o; 655 | d.$ = $(this); 656 | d.run(); 657 | } 658 | ).parent(); 659 | }; 660 | 661 | })(jQuery); -------------------------------------------------------------------------------- /libs/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.3 (http://getbootstrap.com) 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | 7 | if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); -------------------------------------------------------------------------------- /libs/fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | --------------------------------------------------------------------------------