diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..51d9923 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Chrome against localhost, with sourcemaps", + "type": "chrome", + "request": "launch", + "url": "file:///Users/peterwang/GitHub/MusicVisualizer/audio-test.html", + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + }, + { + "name": "Attach to Chrome, with sourcemaps", + "type": "chrome", + "request": "attach", + "port": 9222, + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/final/OrbitControls.js b/OrbitControls.js similarity index 100% rename from final/OrbitControls.js rename to OrbitControls.js diff --git a/final/animation.js b/animation.js similarity index 100% rename from final/animation.js rename to animation.js diff --git a/atomaudioviz b/atomaudioviz new file mode 160000 index 0000000..d6fd7a5 --- /dev/null +++ b/atomaudioviz @@ -0,0 +1 @@ +Subproject commit d6fd7a5152edf650103403560a1f510e0b7a67ad diff --git a/audio-test.html b/audio-test.html deleted file mode 100644 index df51ad6..0000000 --- a/audio-test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/final/master.js b/final/master.js deleted file mode 100644 index b31b23e..0000000 --- a/final/master.js +++ /dev/null @@ -1,195 +0,0 @@ -$(document).ready(function() { - getElements(); - addEventListeners(); - initMp3Player(); - threeInit(); - frameLooper(); - loadAudioFromSC(DEFAULT_SC_MUSIC); -}); - -function getElements() { - soundcloudURL = document.getElementById("soundcloud-url"); - audio = document.getElementById("audio-player"); - volumeBar = document.getElementById("volumeBar"); - seekbar = document.getElementById("seekbar"); - pausePlay = document.getElementById("pause_play"); - currentTime = document.getElementById("currentTime"); - maxTime = document.getElementById("maxTime"); - micToggle = document.getElementById("mic_toggle"); - audioTitle = document.getElementById("audio-title"); - pulseToggle = document.getElementById("pulseToggle"); -} - -function addEventListeners() { - //event listener for when user presses enter, process the request - soundcloudURL.addEventListener("keypress", function(e) { - if(e.which === 13) { - loadAudioFromSC(soundcloudURL.value); - } - }); - - //event listeners to change the internal text - soundcloudURL.addEventListener("click", function(e) { - soundcloudURL.value = ""; - }); - soundcloudURL.addEventListener("blur", function(e) { - soundcloudURL.value = "Soundcloud URL"; - }); - - //fade in fade out of volume controls, seek bar, input div, pulse toggle - $("#volumeControl").hover(function() {$("#volumeslider").stop(true, false).fadeTo(500, 1);}, - function() {$("#volumeslider").stop(true, false).fadeTo(500, 0);}); - - $("#audio-controls").hover(function() {$("#timeControl").stop(true, false).fadeTo(500, 1);}, - function() {$("#timeControl").stop(true, false).fadeTo(500, 0);}); - - $("#audio-input").hover(function() {$("#audio-input").stop(true, false).fadeTo(500, 1);}, - function() {$("#audio-input").stop(true, false).fadeTo(500, 0); $("#soundcloud-url").trigger("blur");}); - - $("#pulseToggle").hover(function() {$("#pulseToggle").stop(true, false).fadeTo(500, 1);}, - function() {$("#pulseToggle").stop(true, false).fadeTo(500, 0);}); -} - -// animation loop -function frameLooper(){ - window.requestAnimationFrame(frameLooper); - fbc_array = new Uint8Array(analyser.frequencyBinCount); - analyser.getByteFrequencyData(fbc_array); - updateSphereSizeColor(); - cyclePulseSpheres(); - renderer.render(scene, camera); -} - -//initialize audio player and audio analyser -function initMp3Player(){ - context = new AudioContext(); - analyser = context.createAnalyser(); - analyser.fftSize = 256; - analyser.smoothingTimeConstant = smoothingConstant; - source = context.createMediaElementSource(document.getElementById("audio-player")); - source.connect(analyser); - analyser.connect(context.destination); -} - -//read audio upload from user -function readMusic(input) { - if(input.files && input.files[0]) { - audio.src = URL.createObjectURL(input.files[0]); - audioTitle.innerHTML = input.files[0].name.slice(0,-4); - playAudio(); - } -} - -//play/pause button -function toggleAudio() { - if(micToggle.dataset.state == "off") { //only allow toggling mic is off - (pausePlay.dataset.state == "pause") ? pauseAudio() : playAudio(); - } -} - -//play audio -function playAudio() { - audio.play(); - pausePlay.src = "img/pause.png"; - pausePlay.dataset.state = "pause"; -} - -//pause audio -function pauseAudio() { - audio.pause(); - pausePlay.src = "img/play.png"; - pausePlay.dataset.state = "play"; -} - -//change audio volume -function setVolume(volume) { - audio.volume = volume/100; -} - -//set max of seek bar when audio selected -function initSeekBar() { - seekbar.max = audio.duration; - maxTime.innerHTML = toMinSec(audio.duration); -} - -//update seek bar as music plays -function updateSeekBar() { - if(!mouseDown) { - seekbar.value = audio.currentTime; - currentTime.innerHTML = toMinSec(audio.currentTime); - } -} - -//jump to specified seekbar time -function seekBarMouseUp() { - audio.currentTime = seekbar.value; - mouseDown = false; -} - -//allow for seeking -function seekBarMouseDown() { - mouseDown = true; - currentTime.innerHTML = toMinSec(seekbar.value); -} - -//convert seconds to MIN:SEC format for display -function toMinSec(seconds) { - var minutes = Math.floor(seconds / 60); - var seconds = Math.floor(seconds % 60); - var results = minutes + ":" + ((seconds < 10) ? ("0" + seconds) : seconds); - return results; -} - -//load audio from soundcloud given url -function loadAudioFromSC(input) { - SC.initialize({client_id: SC_CLIENT_ID}); - SC.get("https://api.soundcloud.com/resolve", { url: input, client_id: SC_CLIENT_ID }, - function(sound) { - scData = sound; - try { - audio.src = sound.stream_url + '?client_id=' + SC_CLIENT_ID; - audioTitle.innerHTML = sound.title; - } catch(e) { - soundcloudURL.value = "Invalid Soundcloud URL"; - } - playAudio(); - }); -} - - -//toggle microphone -function toggleMic() { - if(micToggle.dataset.state == "off") { - micToggle.dataset.state = "on"; - navigator.mediaDevices.getUserMedia({audio: true, video: false}) - .then(initMicrophone) - .catch(function(e) {}); - } else { - micToggle.dataset.state = "off"; - turnOffMicrophone(); - } -} - -//initialize microphone by disconnecting audio souce from analyser and connecting mic source to the analyser -function initMicrophone(stream) { - micToggle.src = "img/mic-on.png"; - source.disconnect(); - micSource = context.createMediaStreamSource(stream); - micSource.connect(analyser); - analyser.disconnect(); //disconnects the analyser from the window audio output - pauseAudio(); //pause music if any playing -} - -//turns off microphone by disconnecting mic source and connecting audio source -function turnOffMicrophone() { - micToggle.src = "img/mic-off.png"; - micSource.disconnect(); - source.connect(analyser); - analyser.connect(context.destination); -} - -//enable/disable pulsing -function togglePulse() { - pulseToggle.innerHTML = radiusPulsingEnable ? "Pulsing Disabled" : "Pulsing Enabled"; - radiusPulsingEnable = radiusPulsingEnable ? false : true; -} diff --git a/final/index.html b/home.html similarity index 100% rename from final/index.html rename to home.html diff --git a/final/img/icon.png b/img/icon.png similarity index 100% rename from final/img/icon.png rename to img/icon.png diff --git a/final/img/mic-off.png b/img/mic-off.png similarity index 100% rename from final/img/mic-off.png rename to img/mic-off.png diff --git a/final/img/mic-on.png b/img/mic-on.png similarity index 100% rename from final/img/mic-on.png rename to img/mic-on.png diff --git a/final/img/pause.png b/img/pause.png similarity index 100% rename from final/img/pause.png rename to img/pause.png diff --git a/final/img/play.png b/img/play.png similarity index 100% rename from final/img/play.png rename to img/play.png diff --git a/final/img/volume.png b/img/volume.png similarity index 100% rename from final/img/volume.png rename to img/volume.png diff --git a/index.html b/index.html deleted file mode 100644 index 16f64ea..0000000 --- a/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - -
- - - - - - - - - diff --git a/index.php b/index.php new file mode 100644 index 0000000..f6e1009 --- /dev/null +++ b/index.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/final/main.css b/main.css similarity index 97% rename from final/main.css rename to main.css index 54a11cb..8ebf772 100644 --- a/final/main.css +++ b/main.css @@ -76,8 +76,9 @@ Audio Controls } #audio-title { - margin-left: 40px; - margin-top: 5px; + position: absolute; + left: 35px; + padding-top: 5px; width: 800px; } diff --git a/master.js b/master.js index 2ffa8ca..b31b23e 100644 --- a/master.js +++ b/master.js @@ -1,37 +1,195 @@ -var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x, bar_width, bar_height; - $(document).ready(function() { - initMp3Player(); + getElements(); + addEventListeners(); + initMp3Player(); + threeInit(); + frameLooper(); + loadAudioFromSC(DEFAULT_SC_MUSIC); }); +function getElements() { + soundcloudURL = document.getElementById("soundcloud-url"); + audio = document.getElementById("audio-player"); + volumeBar = document.getElementById("volumeBar"); + seekbar = document.getElementById("seekbar"); + pausePlay = document.getElementById("pause_play"); + currentTime = document.getElementById("currentTime"); + maxTime = document.getElementById("maxTime"); + micToggle = document.getElementById("mic_toggle"); + audioTitle = document.getElementById("audio-title"); + pulseToggle = document.getElementById("pulseToggle"); +} + +function addEventListeners() { + //event listener for when user presses enter, process the request + soundcloudURL.addEventListener("keypress", function(e) { + if(e.which === 13) { + loadAudioFromSC(soundcloudURL.value); + } + }); + + //event listeners to change the internal text + soundcloudURL.addEventListener("click", function(e) { + soundcloudURL.value = ""; + }); + soundcloudURL.addEventListener("blur", function(e) { + soundcloudURL.value = "Soundcloud URL"; + }); + + //fade in fade out of volume controls, seek bar, input div, pulse toggle + $("#volumeControl").hover(function() {$("#volumeslider").stop(true, false).fadeTo(500, 1);}, + function() {$("#volumeslider").stop(true, false).fadeTo(500, 0);}); + + $("#audio-controls").hover(function() {$("#timeControl").stop(true, false).fadeTo(500, 1);}, + function() {$("#timeControl").stop(true, false).fadeTo(500, 0);}); + + $("#audio-input").hover(function() {$("#audio-input").stop(true, false).fadeTo(500, 1);}, + function() {$("#audio-input").stop(true, false).fadeTo(500, 0); $("#soundcloud-url").trigger("blur");}); + + $("#pulseToggle").hover(function() {$("#pulseToggle").stop(true, false).fadeTo(500, 1);}, + function() {$("#pulseToggle").stop(true, false).fadeTo(500, 0);}); +} + +// animation loop function frameLooper(){ window.requestAnimationFrame(frameLooper); fbc_array = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(fbc_array); - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = "#00CCFF"; - bars = 100; - for (var i = 0; i < bars; i++){ - bar_x = i * 3; - bar_width = 2; - bar_height = -(fbc_array[i]/2); - ctx.fillRect(bar_x, canvas.height, bar_width, bar_height); - } + updateSphereSizeColor(); + cyclePulseSpheres(); + renderer.render(scene, camera); } +//initialize audio player and audio analyser function initMp3Player(){ context = new AudioContext(); analyser = context.createAnalyser(); - canvas = document.getElementById('analyser_render'); - ctx = canvas.getContext('2d'); + analyser.fftSize = 256; + analyser.smoothingTimeConstant = smoothingConstant; source = context.createMediaElementSource(document.getElementById("audio-player")); source.connect(analyser); analyser.connect(context.destination); - frameLooper(); } +//read audio upload from user function readMusic(input) { - var file = input.files[0]; - var objectUrl = URL.createObjectURL(file); - $("#audio-player").attr("src", objectUrl); + if(input.files && input.files[0]) { + audio.src = URL.createObjectURL(input.files[0]); + audioTitle.innerHTML = input.files[0].name.slice(0,-4); + playAudio(); + } +} + +//play/pause button +function toggleAudio() { + if(micToggle.dataset.state == "off") { //only allow toggling mic is off + (pausePlay.dataset.state == "pause") ? pauseAudio() : playAudio(); + } +} + +//play audio +function playAudio() { + audio.play(); + pausePlay.src = "img/pause.png"; + pausePlay.dataset.state = "pause"; +} + +//pause audio +function pauseAudio() { + audio.pause(); + pausePlay.src = "img/play.png"; + pausePlay.dataset.state = "play"; +} + +//change audio volume +function setVolume(volume) { + audio.volume = volume/100; +} + +//set max of seek bar when audio selected +function initSeekBar() { + seekbar.max = audio.duration; + maxTime.innerHTML = toMinSec(audio.duration); +} + +//update seek bar as music plays +function updateSeekBar() { + if(!mouseDown) { + seekbar.value = audio.currentTime; + currentTime.innerHTML = toMinSec(audio.currentTime); + } +} + +//jump to specified seekbar time +function seekBarMouseUp() { + audio.currentTime = seekbar.value; + mouseDown = false; +} + +//allow for seeking +function seekBarMouseDown() { + mouseDown = true; + currentTime.innerHTML = toMinSec(seekbar.value); +} + +//convert seconds to MIN:SEC format for display +function toMinSec(seconds) { + var minutes = Math.floor(seconds / 60); + var seconds = Math.floor(seconds % 60); + var results = minutes + ":" + ((seconds < 10) ? ("0" + seconds) : seconds); + return results; +} + +//load audio from soundcloud given url +function loadAudioFromSC(input) { + SC.initialize({client_id: SC_CLIENT_ID}); + SC.get("https://api.soundcloud.com/resolve", { url: input, client_id: SC_CLIENT_ID }, + function(sound) { + scData = sound; + try { + audio.src = sound.stream_url + '?client_id=' + SC_CLIENT_ID; + audioTitle.innerHTML = sound.title; + } catch(e) { + soundcloudURL.value = "Invalid Soundcloud URL"; + } + playAudio(); + }); +} + + +//toggle microphone +function toggleMic() { + if(micToggle.dataset.state == "off") { + micToggle.dataset.state = "on"; + navigator.mediaDevices.getUserMedia({audio: true, video: false}) + .then(initMicrophone) + .catch(function(e) {}); + } else { + micToggle.dataset.state = "off"; + turnOffMicrophone(); + } +} + +//initialize microphone by disconnecting audio souce from analyser and connecting mic source to the analyser +function initMicrophone(stream) { + micToggle.src = "img/mic-on.png"; + source.disconnect(); + micSource = context.createMediaStreamSource(stream); + micSource.connect(analyser); + analyser.disconnect(); //disconnects the analyser from the window audio output + pauseAudio(); //pause music if any playing +} + +//turns off microphone by disconnecting mic source and connecting audio source +function turnOffMicrophone() { + micToggle.src = "img/mic-off.png"; + micSource.disconnect(); + source.connect(analyser); + analyser.connect(context.destination); +} + +//enable/disable pulsing +function togglePulse() { + pulseToggle.innerHTML = radiusPulsingEnable ? "Pulsing Disabled" : "Pulsing Enabled"; + radiusPulsingEnable = radiusPulsingEnable ? false : true; } diff --git a/prelim/CanvasInput.js b/prelim/CanvasInput.js new file mode 100644 index 0000000..78b584c --- /dev/null +++ b/prelim/CanvasInput.js @@ -0,0 +1,10 @@ +/*! + * CanvasInput v1.2.3 + * http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input + * + * (c) 2013-2016, James Simpson of GoldFire Studios + * goldfirestudios.com + * + * MIT License + */ +!function(){var e=[],t=window.CanvasInput=function(t){var n=this;t=t?t:{},n._canvas=t.canvas||null,n._ctx=n._canvas?n._canvas.getContext("2d"):null,n._x=t.x||0,n._y=t.y||0,n._extraX=t.extraX||0,n._extraY=t.extraY||0,n._fontSize=t.fontSize||14,n._fontFamily=t.fontFamily||"Arial",n._fontColor=t.fontColor||"#000",n._placeHolderColor=t.placeHolderColor||"#bfbebd",n._fontWeight=t.fontWeight||"normal",n._fontStyle=t.fontStyle||"normal",n._fontShadowColor=t.fontShadowColor||"",n._fontShadowBlur=t.fontShadowBlur||0,n._fontShadowOffsetX=t.fontShadowOffsetX||0,n._fontShadowOffsetY=t.fontShadowOffsetY||0,n._readonly=t.readonly||!1,n._maxlength=t.maxlength||null,n._width=t.width||150,n._height=t.height||n._fontSize,n._padding=t.padding>=0?t.padding:5,n._borderWidth=t.borderWidth>=0?t.borderWidth:1,n._borderColor=t.borderColor||"#959595",n._borderRadius=t.borderRadius>=0?t.borderRadius:3,n._backgroundImage=t.backgroundImage||"",n._boxShadow=t.boxShadow||"1px 1px 0px rgba(255, 255, 255, 1)",n._innerShadow=t.innerShadow||"0px 0px 4px rgba(0, 0, 0, 0.4)",n._selectionColor=t.selectionColor||"rgba(179, 212, 253, 0.8)",n._placeHolder=t.placeHolder||"",n._value=(t.value||n._placeHolder)+"",n._onsubmit=t.onsubmit||function(){},n._onkeydown=t.onkeydown||function(){},n._onkeyup=t.onkeyup||function(){},n._onfocus=t.onfocus||function(){},n._onblur=t.onblur||function(){},n._cursor=!1,n._cursorPos=0,n._hasFocus=!1,n._selection=[0,0],n._wasOver=!1,n.boxShadow(n._boxShadow,!0),n._calcWH(),n._renderCanvas=document.createElement("canvas"),n._renderCanvas.setAttribute("width",n.outerW),n._renderCanvas.setAttribute("height",n.outerH),n._renderCtx=n._renderCanvas.getContext("2d"),n._shadowCanvas=document.createElement("canvas"),n._shadowCanvas.setAttribute("width",n._width+2*n._padding),n._shadowCanvas.setAttribute("height",n._height+2*n._padding),n._shadowCtx=n._shadowCanvas.getContext("2d"),"undefined"!=typeof t.backgroundGradient?(n._backgroundColor=n._renderCtx.createLinearGradient(0,0,0,n.outerH),n._backgroundColor.addColorStop(0,t.backgroundGradient[0]),n._backgroundColor.addColorStop(1,t.backgroundGradient[1])):n._backgroundColor=t.backgroundColor||"#fff",n._canvas&&(n._canvas.addEventListener("mousemove",function(e){e=e||window.event,n.mousemove(e,n)},!1),n._canvas.addEventListener("mousedown",function(e){e=e||window.event,n.mousedown(e,n)},!1),n._canvas.addEventListener("mouseup",function(e){e=e||window.event,n.mouseup(e,n)},!1)),window.addEventListener("mouseup",function(e){e=e||window.event,n._hasFocus&&!n._mouseDown&&n.blur()},!0),n._hiddenInput=document.createElement("input"),n._hiddenInput.type="text",n._hiddenInput.style.position="absolute",n._hiddenInput.style.opacity=0,n._hiddenInput.style.pointerEvents="none",n._hiddenInput.style.left=n._x+n._extraX+(n._canvas?n._canvas.offsetLeft:0)+"px",n._hiddenInput.style.top=n._y+n._extraY+(n._canvas?n._canvas.offsetTop:0)+"px",n._hiddenInput.style.width=n._width+"px",n._hiddenInput.style.height=n._height+"px",n._hiddenInput.style.zIndex=0,n._maxlength&&(n._hiddenInput.maxLength=n._maxlength),document.body.appendChild(n._hiddenInput),n._hiddenInput.value=n._value,n._hiddenInput.addEventListener("keydown",function(e){e=e||window.event,n._hasFocus&&n.keydown(e,n)}),n._hiddenInput.addEventListener("keyup",function(e){e=e||window.event,n._value=n._hiddenInput.value,n._cursorPos=n._hiddenInput.selectionStart,n._selection=[n._hiddenInput.selectionStart,n._hiddenInput.selectionEnd],n.render(),n._hasFocus&&n._onkeyup(e,n)}),e.push(n),n._inputsIndex=e.length-1,n.render()};t.prototype={canvas:function(e){var t=this;return"undefined"!=typeof e?(t._canvas=e,t._ctx=t._canvas.getContext("2d"),t.render()):t._canvas},x:function(e){var t=this;return"undefined"!=typeof e?(t._x=e,t.render()):t._x},y:function(e){var t=this;return"undefined"!=typeof e?(t._y=e,t.render()):t._y},extraX:function(e){var t=this;return"undefined"!=typeof e?(t._extraX=e,t.render()):t._extraX},extraY:function(e){var t=this;return"undefined"!=typeof e?(t._extraY=e,t.render()):t._extraY},fontSize:function(e){var t=this;return"undefined"!=typeof e?(t._fontSize=e,t.render()):t._fontSize},fontFamily:function(e){var t=this;return"undefined"!=typeof e?(t._fontFamily=e,t.render()):t._fontFamily},fontColor:function(e){var t=this;return"undefined"!=typeof e?(t._fontColor=e,t.render()):t._fontColor},placeHolderColor:function(e){var t=this;return"undefined"!=typeof e?(t._placeHolderColor=e,t.render()):t._placeHolderColor},fontWeight:function(e){var t=this;return"undefined"!=typeof e?(t._fontWeight=e,t.render()):t._fontWeight},fontStyle:function(e){var t=this;return"undefined"!=typeof e?(t._fontStyle=e,t.render()):t._fontStyle},fontShadowColor:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowColor=e,t.render()):t._fontShadowColor},fontShadowBlur:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowBlur=e,t.render()):t._fontShadowBlur},fontShadowOffsetX:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowOffsetX=e,t.render()):t._fontShadowOffsetX},fontShadowOffsetY:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowOffsetY=e,t.render()):t._fontShadowOffsetY},width:function(e){var t=this;return"undefined"!=typeof e?(t._width=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._width},height:function(e){var t=this;return"undefined"!=typeof e?(t._height=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._height},padding:function(e){var t=this;return"undefined"!=typeof e?(t._padding=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._padding},borderWidth:function(e){var t=this;return"undefined"!=typeof e?(t._borderWidth=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._borderWidth},borderColor:function(e){var t=this;return"undefined"!=typeof e?(t._borderColor=e,t.render()):t._borderColor},borderRadius:function(e){var t=this;return"undefined"!=typeof e?(t._borderRadius=e,t.render()):t._borderRadius},backgroundColor:function(e){var t=this;return"undefined"!=typeof e?(t._backgroundColor=e,t.render()):t._backgroundColor},backgroundGradient:function(e){var t=this;return"undefined"!=typeof e?(t._backgroundColor=t._renderCtx.createLinearGradient(0,0,0,t.outerH),t._backgroundColor.addColorStop(0,e[0]),t._backgroundColor.addColorStop(1,e[1]),t.render()):t._backgroundColor},boxShadow:function(e,t){var n=this;if("undefined"==typeof e)return n._boxShadow;var o=e.split("px ");return n._boxShadow={x:"none"===n._boxShadow?0:parseInt(o[0],10),y:"none"===n._boxShadow?0:parseInt(o[1],10),blur:"none"===n._boxShadow?0:parseInt(o[2],10),color:"none"===n._boxShadow?"":o[3]},n._boxShadow.x<0?(n.shadowL=Math.abs(n._boxShadow.x)+n._boxShadow.blur,n.shadowR=n._boxShadow.blur+n._boxShadow.x):(n.shadowL=Math.abs(n._boxShadow.blur-n._boxShadow.x),n.shadowR=n._boxShadow.blur+n._boxShadow.x),n._boxShadow.y<0?(n.shadowT=Math.abs(n._boxShadow.y)+n._boxShadow.blur,n.shadowB=n._boxShadow.blur+n._boxShadow.y):(n.shadowT=Math.abs(n._boxShadow.blur-n._boxShadow.y),n.shadowB=n._boxShadow.blur+n._boxShadow.y),n.shadowW=n.shadowL+n.shadowR,n.shadowH=n.shadowT+n.shadowB,n._calcWH(),t?void 0:(n._updateCanvasWH(),n.render())},innerShadow:function(e){var t=this;return"undefined"!=typeof e?(t._innerShadow=e,t.render()):t._innerShadow},selectionColor:function(e){var t=this;return"undefined"!=typeof e?(t._selectionColor=e,t.render()):t._selectionColor},placeHolder:function(e){var t=this;return"undefined"!=typeof e?(t._placeHolder=e,t.render()):t._placeHolder},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e+"",t._hiddenInput.value=e+"",t._cursorPos=t._clipText().length,t.render(),t):t._value===t._placeHolder?"":t._value},onsubmit:function(e){var t=this;return"undefined"!=typeof e?(t._onsubmit=e,t):void t._onsubmit()},onkeydown:function(e){var t=this;return"undefined"!=typeof e?(t._onkeydown=e,t):void t._onkeydown()},onkeyup:function(e){var t=this;return"undefined"!=typeof e?(t._onkeyup=e,t):void t._onkeyup()},focus:function(t){var n=this;if(!n._hasFocus){n._onfocus(n);for(var o=0;o