+++ /dev/null
-/** @license
-
- SoundManager 2: JavaScript Sound for the Web
- ----------------------------------------------
- http://schillmania.com/projects/soundmanager2/
-
- Copyright (c) 2007, Scott Schiller. All rights reserved.
- Code provided under the BSD License:
- http://schillmania.com/projects/soundmanager2/license.txt
-
- V2.97a.20110424
-*/
-(function(Y){function M(M,X){function i(c){return function(a){return!this._t||!this._t._a?null:c.call(this,a)}}function pa(){if(c.debugURLParam.test(N))c.debugMode=!0}this.flashVersion=8;this.debugFlash=this.debugMode=!1;this.useConsole=!0;this.waitForWindowLoad=this.consoleOnly=!1;this.nullURL="about:blank";this.allowPolling=!0;this.useFastPolling=!1;this.useMovieStar=!0;this.bgColor="#ffffff";this.useHighPerformance=!1;this.flashPollingInterval=null;this.flashLoadTimeout=1E3;this.wmode=null;this.allowScriptAccess=
-"always";this.useHTML5Audio=this.useFlashBlock=!1;this.html5Test=/^probably$/i;this.useGlobalHTML5Audio=!0;this.requireFlash=!1;this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!0},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave",
-"audio/x-wav"],required:!1}};this.defaultOptions={autoLoad:!1,stream:!0,autoPlay:!1,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfailure:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5E3,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:!0,multiShotEvents:!1,position:null,pan:0,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,
-useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.version=null;this.versionNumber="V2.97a.20110424";this.movieURL=null;this.url=M||null;this.altURL=null;this.enabled=this.swfLoaded=!1;this.o=null;this.movieID="sm2-container";this.id=X||"sm2movie";this.swfCSS={swfBox:"sm2-object-box",swfDefault:"movieContainer",swfError:"swf_error",swfTimedout:"swf_timedout",swfLoaded:"swf_loaded",swfUnblocked:"swf_unblocked",sm2Debug:"sm2_debug",
-highPerf:"high_performance",flashDebug:"flash_debug"};this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=!1;this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.didFlashBlock=this.specialWmodeCase=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.baseMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamTypes=["aac","flv","mov","mp4","m4v",
-"f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.mimePattern=this.baseMimeTypes;this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={};this.hasHTML5=null;this.html5={usingFlash:null};this.ignoreFlash=!1;var Z,c=this,y,n=navigator.userAgent,h=Y,N=h.location.href.toString(),k=this.flashVersion,g=document,$,O,r=[],E=!1,F=!1,m=!1,t=!1,qa=!1,G,o,aa,u,z,ba,P,ra,ca,v,sa,H,A,da,ea,Q,fa,ta,ua,R,
-va,I=null,ga=null,w,ha,B,S,T,ia,j,U=!1,ja=!1,wa,xa,x=null,ya,V,p=!1,J,s,ka,za,l,Da=Array.prototype.slice,K=!1,la,C,Aa,Ba=n.match(/pre\//i),Ea=n.match(/(ipad|iphone|ipod)/i);n.match(/mobile/i);var q=n.match(/msie/i),Fa=n.match(/webkit/i),L=n.match(/safari/i)&&!n.match(/chrome/i),Ga=n.match(/opera/i),ma=!N.match(/usehtml5audio/i)&&!N.match(/sm2\-ignorebadua/i)&&L&&n.match(/OS X 10_6_([3-9])/i),na=typeof g.hasFocus!=="undefined"?g.hasFocus():null,D=typeof g.hasFocus==="undefined"&&L,Ca=!D;this._use_maybe=
-N.match(/sm2\-useHTML5Maybe\=1/i);this._overHTTP=g.location?g.location.protocol.match(/http/i):null;this._http=!this._overHTTP?"http:":"";this.useAltURL=!this._overHTTP;this._global_a=null;if(Ea||Ba)c.useHTML5Audio=!0,c.ignoreFlash=!0,c.useGlobalHTML5Audio&&(K=!0);if(Ba||this._use_maybe)c.html5Test=/^(probably|maybe)$/i;this.supported=this.ok=function(){return x?m&&!t:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return q?h[c]:L?y(c)||g[c]:y(c)};this.createSound=function(b){function a(){e=
-S(e);c.sounds[d.id]=new Z(d);c.soundIDs.push(d.id);return c.sounds[d.id]}var e=null,f=null,d=null;if(!m||!c.ok())return ia("soundManager.createSound(): "+w(!m?"notReady":"notOK")),!1;arguments.length===2&&(b={id:arguments[0],url:arguments[1]});d=e=o(b);if(j(d.id,!0))return c.sounds[d.id];if(V(d))f=a(),f._setup_html5(d);else{if(k>8&&c.useMovieStar){if(d.isMovieStar===null)d.isMovieStar=d.serverURL||d.type&&d.type.match(c.netStreamPattern)||d.url.match(c.netStreamPattern)?!0:!1;if(d.isMovieStar&&d.usePeakData)d.usePeakData=
-!1}d=T(d,"soundManager.createSound(): ");f=a();if(k===8)c.o._createSound(d.id,d.onjustbeforefinishtime,d.loops||1,d.usePolicyFile);else if(c.o._createSound(d.id,d.url,d.onjustbeforefinishtime,d.usePeakData,d.useWaveformData,d.useEQData,d.isMovieStar,d.isMovieStar?d.bufferTime:!1,d.loops||1,d.serverURL,d.duration||null,d.autoPlay,!0,d.autoLoad,d.usePolicyFile),!d.serverURL)f.connected=!0,d.onconnect&&d.onconnect.apply(f);(d.autoLoad||d.autoPlay)&&!d.serverURL&&f.load(d)}d.autoPlay&&!d.serverURL&&f.play();
-return f};this.destroySound=function(b,a){if(!j(b))return!1;var e=c.sounds[b],f;e._iO={};e.stop();e.unload();for(f=0;f<c.soundIDs.length;f++)if(c.soundIDs[f]===b){c.soundIDs.splice(f,1);break}a||e.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,a){if(!j(b))return!1;return c.sounds[b].load(a)};this.unload=function(b){if(!j(b))return!1;return c.sounds[b].unload()};this.start=this.play=function(b,a){if(!m||!c.ok())return ia("soundManager.play(): "+w(!m?"notReady":"notOK")),!1;if(!j(b))return a instanceof
-Object||(a={url:a}),a&&a.url?(a.id=b,c.createSound(a).play()):!1;return c.sounds[b].play(a)};this.setPosition=function(b,a){if(!j(b))return!1;return c.sounds[b].setPosition(a)};this.stop=function(b){if(!j(b))return!1;return c.sounds[b].stop()};this.stopAll=function(){for(var b in c.sounds)c.sounds[b]instanceof Z&&c.sounds[b].stop()};this.pause=function(b){if(!j(b))return!1;return c.sounds[b].pause()};this.pauseAll=function(){for(var b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].pause()};this.resume=
-function(b){if(!j(b))return!1;return c.sounds[b].resume()};this.resumeAll=function(){for(var b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){if(!j(b))return!1;return c.sounds[b].togglePause()};this.setPan=function(b,a){if(!j(b))return!1;return c.sounds[b].setPan(a)};this.setVolume=function(b,a){if(!j(b))return!1;return c.sounds[b].setVolume(a)};this.mute=function(b){var a=0;typeof b!=="string"&&(b=null);if(b){if(!j(b))return!1;return c.sounds[b].mute()}else{for(a=
-c.soundIDs.length;a--;)c.sounds[c.soundIDs[a]].mute();c.muted=!0}return!0};this.muteAll=function(){c.mute()};this.unmute=function(b){typeof b!=="string"&&(b=null);if(b){if(!j(b))return!1;return c.sounds[b].unmute()}else{for(b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].unmute();c.muted=!1}return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){if(!j(b))return!1;return c.sounds[b].toggleMute()};this.getMemoryUse=function(){if(k===8)return 0;if(c.o)return parseInt(c.o._getMemoryUse(),
-10)};this.disable=function(b){typeof b==="undefined"&&(b=!1);if(t)return!1;t=!0;for(var a=c.soundIDs.length;a--;)ua(c.sounds[c.soundIDs[a]]);G(b);l.remove(h,"load",z);return!0};this.canPlayMIME=function(b){var a;c.hasHTML5&&(a=J({type:b}));return!x||a?a:b?b.match(c.mimePattern)?!0:!1:null};this.canPlayURL=function(b){var a;c.hasHTML5&&(a=J(b));return!x||a?a:b?b.match(c.filePattern)?!0:!1:null};this.canPlayLink=function(b){if(typeof b.type!=="undefined"&&b.type&&c.canPlayMIME(b.type))return!0;return c.canPlayURL(b.href)};
-this.getSoundById=function(b){if(!b)throw Error("soundManager.getSoundById(): sID is null/undefined");return c.sounds[b]};this.onready=function(c,a){if(c&&c instanceof Function)return a||(a=h),aa("onready",c,a),u(),!0;else throw w("needFunction","onready");};this.ontimeout=function(c,a){if(c&&c instanceof Function)return a||(a=h),aa("ontimeout",c,a),u({type:"ontimeout"}),!0;else throw w("needFunction","ontimeout");};this.getMoviePercent=function(){return c.o&&typeof c.o.PercentLoaded!=="undefined"?
-c.o.PercentLoaded():null};this._wD=this._writeDebug=function(){return!0};this._debug=function(){};this.reboot=function(){var b,a;for(b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].destruct();try{if(q)ga=c.o.innerHTML;I=c.o.parentNode.removeChild(c.o)}catch(e){}ga=I=null;c.enabled=m=U=ja=E=F=t=c.swfLoaded=!1;c.soundIDs=c.sounds=[];c.o=null;for(b in r)if(r.hasOwnProperty(b))for(a=r[b].length;a--;)r[b][a].fired=!1;h.setTimeout(function(){c.beginDelayedInit()},20)};this.destruct=function(){c.disable(!0)};
-this.beginDelayedInit=function(){qa=!0;A();setTimeout(sa,20);P()};this._html5_events={abort:i(function(){}),canplay:i(function(){this._t._onbufferchange(0);var c=!isNaN(this._t.position)?this._t.position/1E3:null;this._t._html5_canplay=!0;if(this._t.position&&this.currentTime!==c)try{this.currentTime=c}catch(a){}}),load:i(function(){this._t.loaded||(this._t._onbufferchange(0),this._t._whileloading(this._t.bytesTotal,this._t.bytesTotal,this._t._get_html5_duration()),this._t._onload(!0))}),emptied:i(function(){}),
-ended:i(function(){this._t._onfinish()}),error:i(function(){this._t._onload(!1)}),loadeddata:i(function(){}),loadedmetadata:i(function(){}),loadstart:i(function(){this._t._onbufferchange(1)}),play:i(function(){this._t._onbufferchange(0)}),playing:i(function(){this._t._onbufferchange(0)}),progress:i(function(b){if(this._t.loaded)return!1;var a,e=0,f=b.type==="progress",d=b.target.buffered;a=b.loaded||0;var oa=b.total||1;if(d&&d.length){for(a=d.length;a--;)e=d.end(a)-d.start(a);a=e/b.target.duration;
-f&&isNaN(a)}isNaN(a)||(this._t._onbufferchange(0),this._t._whileloading(a,oa,this._t._get_html5_duration()),a&&oa&&a===oa&&c._html5_events.load.call(this,b))}),ratechange:i(function(){}),suspend:i(function(b){c._html5_events.progress.call(this,b)}),stalled:i(function(){}),timeupdate:i(function(){this._t._onTimer()}),waiting:i(function(){this._t._onbufferchange(1)})};Z=function(b){var a=this,e,f,d;this.sID=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=o(b);this.pan=this.options.pan;
-this.volume=this.options.volume;this._lastURL=null;this.isHTML5=!1;this._a=null;this.id3={};this._debug=function(){};this._debug();this.load=function(b){var d=null;if(typeof b!=="undefined")a._iO=o(b,a.options),a.instanceOptions=a._iO;else if(b=a.options,a._iO=b,a.instanceOptions=a._iO,a._lastURL&&a._lastURL!==a.url)a._iO.url=a.url,a.url=null;if(!a._iO.url)a._iO.url=a.url;if(a._iO.url===a.url&&a.readyState!==0&&a.readyState!==2)return a;a._lastURL=a.url;a.loaded=!1;a.readyState=1;a.playState=0;if(V(a._iO)){if(d=
-a._setup_html5(a._iO),!d._called_load)d.load(),d._called_load=!0,a._iO.autoPlay&&a.play()}else try{a.isHTML5=!1,a._iO=T(S(a._iO)),k===8?c.o._load(a.sID,a._iO.url,a._iO.stream,a._iO.autoPlay,a._iO.whileloading?1:0,a._iO.loops||1,a._iO.usePolicyFile):c.o._load(a.sID,a._iO.url,a._iO.stream?!0:!1,a._iO.autoPlay?!0:!1,a._iO.loops||1,a._iO.autoLoad?!0:!1,a._iO.usePolicyFile)}catch(e){fa()}return a};this.unload=function(){if(a.readyState!==0){if(a.isHTML5){if(f(),a._a)a._a.pause(),a._a.src=""}else k===8?
-c.o._unload(a.sID,c.nullURL):c.o._unload(a.sID);e()}return a};this.destruct=function(b){if(a.isHTML5){if(f(),a._a)a._a.pause(),a._a.src="",K||a._remove_html5_events()}else a._iO.onfailure=null,c.o._destroySound(a.sID);b||c.destroySound(a.sID,!0)};this.start=this.play=function(b,W){var e,W=W===void 0?!0:W;b||(b={});a._iO=o(b,a._iO);a._iO=o(a._iO,a.options);a.instanceOptions=a._iO;if(a._iO.serverURL&&!a.connected)return a.getAutoPlay()||a.setAutoPlay(!0),a;V(a._iO)&&(a._setup_html5(a._iO),d());if(a.playState===
-1&&!a.paused)if(e=a._iO.multiShot)a.isHTML5&&a.setPosition(a._iO.position);else return a;if(!a.loaded)if(a.readyState===0){if(!a.isHTML5)a._iO.autoPlay=!0;a.load(a._iO)}else if(a.readyState===2)return a;if(a.paused&&a.position&&a.position>0)a.resume();else{a.playState=1;a.paused=!1;(!a.instanceCount||a._iO.multiShotEvents||k>8&&!a.isHTML5&&!a.getAutoPlay())&&a.instanceCount++;a.position=typeof a._iO.position!=="undefined"&&!isNaN(a._iO.position)?a._iO.position:0;if(!a.isHTML5)a._iO=T(S(a._iO));if(a._iO.onplay&&
-W)a._iO.onplay.apply(a),a._onplay_called=!0;a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?(d(),a._setup_html5().play()):c.o._start(a.sID,a._iO.loops||1,k===9?a.position:a.position/1E3)}return a};this.stop=function(b){if(a.playState===1){a._onbufferchange(0);a.resetOnPosition(0);if(!a.isHTML5)a.playState=0;a.paused=!1;a._iO.onstop&&a._iO.onstop.apply(a);if(a.isHTML5){if(a._a)a.setPosition(0),a._a.pause(),a.playState=0,a._onTimer(),f(),a.unload()}else c.o._stop(a.sID,b),a._iO.serverURL&&
-a.unload();a.instanceCount=0;a._iO={}}return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5?a._a&&b&&a.play():c.o._setAutoPlay(a.sID,b);b&&!a.instanceCount&&a.readyState===1&&a.instanceCount++};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===void 0&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a.resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a&&a._html5_canplay&&
-a._a.currentTime!==b)try{a._a.currentTime=b}catch(e){}}else b=k===9?a.position:b,a.readyState&&a.readyState!==2&&c.o._setPosition(a.sID,b,a.paused||!a.playState);a.isHTML5&&a.paused&&a._onTimer(!0);return a};this.pause=function(b){if(a.paused||a.playState===0&&a.readyState!==1)return a;a.paused=!0;a.isHTML5?(a._setup_html5().pause(),f()):(b||b===void 0)&&c.o._pause(a.sID);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5?
-(a._setup_html5().play(),d()):(a._iO.isMovieStar&&a.setPosition(a.position),c.o._pause(a.sID));!a._onplay_called&&a._iO.onplay?(a._iO.onplay.apply(a),a._onplay_called=!0):a._iO.onresume&&a._iO.onresume.apply(a);return a};this.togglePause=function(){if(a.playState===0)return a.play({position:k===9&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,d){typeof b==="undefined"&&(b=0);typeof d==="undefined"&&(d=!1);a.isHTML5||c.o._setPan(a.sID,b);a._iO.pan=
-b;if(!d)a.pan=b,a.options.pan=b;return a};this.setVolume=function(b,d){typeof b==="undefined"&&(b=100);typeof d==="undefined"&&(d=!1);if(a.isHTML5){if(a._a)a._a.volume=Math.max(0,Math.min(1,b/100))}else c.o._setVolume(a.sID,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;if(!d)a.volume=b,a.options.volume=b;return a};this.mute=function(){a.muted=!0;if(a.isHTML5){if(a._a)a._a.muted=!0}else c.o._setVolume(a.sID,0);return a};this.unmute=function(){a.muted=!1;var b=typeof a._iO.volume!=="undefined";if(a.isHTML5){if(a._a)a._a.muted=
-!1}else c.o._setVolume(a.sID,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=function(c,b,d){a._onPositionItems.push({position:c,method:b,scope:typeof d!=="undefined"?d:a,fired:!1});return a};this.processOnPosition=function(){var b,d;b=a._onPositionItems.length;if(!b||!a.playState||a._onPositionFired>=b)return!1;for(;b--;)if(d=a._onPositionItems[b],!d.fired&&a.position>=d.position)d.method.apply(d.scope,[d.position]),d.fired=
-!0,c._onPositionFired++;return!0};this.resetOnPosition=function(b){var d,e;d=a._onPositionItems.length;if(!d)return!1;for(;d--;)if(e=a._onPositionItems[d],e.fired&&b<=e.position)e.fired=!1,c._onPositionFired--;return!0};this._onTimer=function(c){var b={};if(a._hasTimer||c)return a._a&&(c||(a.playState>0||a.readyState===1)&&!a.paused)?(a.duration=a._get_html5_duration(),a.durationEstimate=a.duration,c=a._a.currentTime?a._a.currentTime*1E3:0,a._whileplaying(c,b,b,b,b),!0):!1};this._get_html5_duration=
-function(){var c=a._a?a._a.duration*1E3:a._iO?a._iO.duration:void 0;return c&&!isNaN(c)&&c!==Infinity?c:a._iO?a._iO.duration:null};d=function(){a.isHTML5&&wa(a)};f=function(){a.isHTML5&&xa(a)};e=function(){a._onPositionItems=[];a._onPositionFired=0;a._hasTimer=null;a._onplay_called=!1;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.position=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.failures=0;a.loaded=!1;a.playState=0;a.paused=!1;a.readyState=
-0;a.muted=!1;a.didBeforeFinish=!1;a.didJustBeforeFinish=!1;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.eqData=[];a.eqData.left=[];a.eqData.right=[]};e();this._setup_html5=function(b){var b=o(a._iO,b),d=K?c._global_a:a._a;decodeURI(b.url);var f=d&&d._t?d._t.instanceOptions:null;if(d){if(d._t&&f.url===b.url&&(!a._lastURL||a._lastURL===f.url))return d;K&&d._t&&d._t.playState&&b.url!==f.url&&d._t.stop();e();d.src=b.url;a.url=
-b.url;a._lastURL=b.url;d._called_load=!1}else if(d=new Audio(b.url),d._called_load=!1,K)c._global_a=d;a.isHTML5=!0;a._a=d;d._t=a;a._add_html5_events();d.loop=b.loops>1?"loop":"";b.autoLoad||b.autoPlay?(d.autobuffer="auto",d.preload="auto",a.load(),d._called_load=!0):(d.autobuffer=!1,d.preload="none");d.loop=b.loops>1?"loop":"";return d};this._add_html5_events=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,
-c._html5_events[b],!1);return!0};this._remove_html5_events=function(){a._a._added_events=!1;for(var b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,c._html5_events[b],!1)};this._whileloading=function(c,b,d,e){a.bytesLoaded=c;a.bytesTotal=b;a.duration=Math.floor(d);a.bufferLength=e;if(a._iO.isMovieStar)a.durationEstimate=a.duration;else if(a.durationEstimate=a._iO.duration?a.duration>a._iO.duration?a.duration:a._iO.duration:parseInt(a.bytesTotal/a.bytesLoaded*
-a.duration,10),a.durationEstimate===void 0)a.durationEstimate=a.duration;a.readyState!==3&&a._iO.whileloading&&a._iO.whileloading.apply(a)};this._onid3=function(c,b){var d=[],e,f;e=0;for(f=c.length;e<f;e++)d[c[e]]=b[e];a.id3=o(a.id3,d);a._iO.onid3&&a._iO.onid3.apply(a)};this._whileplaying=function(b,d,e,f,g){if(isNaN(b)||b===null)return!1;a.playState===0&&b>0&&(b=0);a.position=b;a.processOnPosition();if(k>8&&!a.isHTML5){if(a._iO.usePeakData&&typeof d!=="undefined"&&d)a.peakData={left:d.leftPeak,right:d.rightPeak};
-if(a._iO.useWaveformData&&typeof e!=="undefined"&&e)a.waveformData={left:e.split(","),right:f.split(",")};if(a._iO.useEQData&&typeof g!=="undefined"&&g&&g.leftEQ&&(b=g.leftEQ.split(","),a.eqData=b,a.eqData.left=b,typeof g.rightEQ!=="undefined"&&g.rightEQ))a.eqData.right=g.rightEQ.split(",")}a.playState===1&&(!a.isHTML5&&c.flashVersion===8&&!a.position&&a.isBuffering&&a._onbufferchange(0),a._iO.whileplaying&&a._iO.whileplaying.apply(a),(a.loaded||!a.loaded&&a._iO.isMovieStar)&&a._iO.onbeforefinish&&
-a._iO.onbeforefinishtime&&!a.didBeforeFinish&&a.duration-a.position<=a._iO.onbeforefinishtime&&a._onbeforefinish());return!0};this._onconnect=function(b){b=b===1;if(a.connected=b)a.failures=0,j(a.sID)&&(a.getAutoPlay()?a.play(void 0,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._onload=function(b){b=b?!0:!1;a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0);a._iO.onload&&a._iO.onload.apply(a,[b]);return!0};this._onfailure=function(b,c,d){a.failures++;
-if(a._iO.onfailure&&a.failures===1)a._iO.onfailure(a,b,c,d)};this._onbeforefinish=function(){if(!a.didBeforeFinish)a.didBeforeFinish=!0,a._iO.onbeforefinish&&a._iO.onbeforefinish.apply(a)};this._onjustbeforefinish=function(){if(!a.didJustBeforeFinish)a.didJustBeforeFinish=!0,a._iO.onjustbeforefinish&&a._iO.onjustbeforefinish.apply(a)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a.resetOnPosition(0);a._iO.onbeforefinishcomplete&&a._iO.onbeforefinishcomplete.apply(a);a.didBeforeFinish=
-!1;a.didJustBeforeFinish=!1;if(a.instanceCount){a.instanceCount--;if(!a.instanceCount)a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},f();(!a.instanceCount||a._iO.multiShotEvents)&&b&&b.apply(a)}};this._onbufferchange=function(b){if(a.playState===0)return!1;if(b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=b===1;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return!0};this._ondataerror=function(){a.playState>0&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}};
-ea=function(){return g.body?g.body:g._docElement?g.documentElement:g.getElementsByTagName("div")[0]};y=function(b){return g.getElementById(b)};o=function(b,a){var e={},f,d;for(f in b)b.hasOwnProperty(f)&&(e[f]=b[f]);f=typeof a==="undefined"?c.defaultOptions:a;for(d in f)f.hasOwnProperty(d)&&typeof e[d]==="undefined"&&(e[d]=f[d]);return e};l=function(){function b(a){var a=Da.call(a),b=a.length;c?(a[1]="on"+a[1],b>3&&a.pop()):b===3&&a.push(!1);return a}function a(a,b){var g=a.shift(),h=[f[b]];if(c)g[h](a[0],
-a[1]);else g[h].apply(g,a)}var c=h.attachEvent,f={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){a(b(arguments),"add")},remove:function(){a(b(arguments),"remove")}}}();V=function(b){return!b.serverURL&&(b.type?J({type:b.type}):J(b.url)||p)};J=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var a,e=c.audioFormats;if(!s){s=[];for(a in e)e.hasOwnProperty(a)&&(s.push(a),e[a].related&&(s=s.concat(e[a].related)));s=RegExp("\\.("+s.join("|")+
-")","i")}a=typeof b.type!=="undefined"?b.type:null;b=typeof b==="string"?b.toLowerCase().match(s):null;if(!b||!b.length)if(a)b=a.indexOf(";"),b=(b!==-1?a.substr(0,b):a).substr(6);else return!1;else b=b[0].substr(1);if(b&&typeof c.html5[b]!=="undefined")return c.html5[b];else{if(!a)if(b&&c.html5[b])return c.html5[b];else a="audio/"+b;a=c.html5.canPlayType(a);return c.html5[b]=a}};za=function(){function b(b){var d,e,f=!1;if(!a||typeof a.canPlayType!=="function")return!1;if(b instanceof Array){d=0;for(e=
-b.length;d<e&&!f;d++)if(c.html5[b[d]]||a.canPlayType(b[d]).match(c.html5Test))f=!0,c.html5[b[d]]=!0;return f}else return(b=a&&typeof a.canPlayType==="function"?a.canPlayType(b):!1)&&(b.match(c.html5Test)?!0:!1)}if(!c.useHTML5Audio||typeof Audio==="undefined")return!1;var a=typeof Audio!=="undefined"?Ga?new Audio(null):new Audio:null,e,f={},d,g;C();d=c.audioFormats;for(e in d)if(d.hasOwnProperty(e)&&(f[e]=b(d[e].type),d[e]&&d[e].related))for(g=d[e].related.length;g--;)c.html5[d[e].related[g]]=f[e];
-f.canPlayType=a?b:null;c.html5=o(c.html5,f);return!0};w=function(){};S=function(b){if(k===8&&b.loops>1&&b.stream)b.stream=!1;return b};T=function(b){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))b.usePolicyFile=!0;return b};ia=function(b){typeof console!=="undefined"&&typeof console.warn!=="undefined"&&console.warn(b)};$=function(){return!1};ua=function(b){for(var a in b)b.hasOwnProperty(a)&&typeof b[a]==="function"&&(b[a]=$)};R=function(b){typeof b==="undefined"&&
-(b=!1);(t||b)&&c.disable(b)};va=function(b){var a=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(a=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");return(b&&b.lastIndexOf("/")!==-1?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL};ca=function(){if(k!==8&&k!==9)c.flashVersion=8;var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";if(c.useHTML5Audio&&!p&&c.audioFormats.mp4.required&&c.flashVersion<9)c.flashVersion=9;k=c.flashVersion;c.version=c.versionNumber+
-(p?" (HTML5-only mode)":k===9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(k>8)c.defaultOptions=o(c.defaultOptions,c.flash9Options),c.features.buffering=!0;k>8&&c.useMovieStar?(c.defaultOptions=o(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+c.netStreamTypes.join("|")+")(\\?.*)?$","i"),c.mimePattern=c.netStreamMimeTypes,c.features.movieStar=!0):(c.useMovieStar=!1,c.features.movieStar=!1);c.filePattern=c.filePatterns[k!==8?"flash9":"flash8"];c.movieURL=(k===8?"soundmanager2.swf":
-"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=k>8};ta=function(b,a){if(!c.o||!c.allowPolling)return!1;c.o._setPolling(b,a)};Q=function(b,a){var e=a?a:c.url,f=c.altURL?c.altURL:e,d;d=ea();var h,k,i=B(),j,l=null,l=(l=g.getElementsByTagName("html")[0])&&l.dir&&l.dir.match(/rtl/i),b=typeof b==="undefined"?c.id:b;if(E&&F)return!1;if(p)return ca(),c.oMC=y(c.movieID),O(),F=E=!0,!1;E=!0;ca();c.url=va(c._overHTTP?e:f);a=c.url;c.wmode=!c.wmode&&
-c.useHighPerformance&&!c.useMovieStar?"transparent":c.wmode;if(c.wmode!==null&&(n.match(/msie 8/i)||!q&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.specialWmodeCase=!0,c.wmode=null;d={name:b,id:b,src:a,width:"100%",height:"100%",quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:c._http+"//www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)d.FlashVars="debug=1";c.wmode||
-delete d.wmode;if(q)e=g.createElement("div"),k='<object id="'+b+'" data="'+a+'" type="'+d.type+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+c._http+'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="'+d.width+'" height="'+d.height+'"><param name="movie" value="'+a+'" /><param name="AllowScriptAccess" value="'+c.allowScriptAccess+'" /><param name="quality" value="'+d.quality+'" />'+(c.wmode?'<param name="wmode" value="'+c.wmode+'" /> ':"")+
-'<param name="bgcolor" value="'+c.bgColor+'" />'+(c.debugFlash?'<param name="FlashVars" value="'+d.FlashVars+'" />':"")+"</object>";else for(h in e=g.createElement("embed"),d)d.hasOwnProperty(h)&&e.setAttribute(h,d[h]);pa();i=B();if(d=ea())if(c.oMC=y(c.movieID)?y(c.movieID):g.createElement("div"),c.oMC.id){j=c.oMC.className;c.oMC.className=(j?j+" ":c.swfCSS.swfDefault)+(i?" "+i:"");c.oMC.appendChild(e);if(q)h=c.oMC.appendChild(g.createElement("div")),h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}else{c.oMC.id=
-c.movieID;c.oMC.className=c.swfCSS.swfDefault+" "+i;h=i=null;if(!c.useFlashBlock)if(c.useHighPerformance)i={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(i={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},l)i.left=Math.abs(parseInt(i.left,10))+"px";if(Fa)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(j in i)i.hasOwnProperty(j)&&(c.oMC.style[j]=i[j]);try{q||c.oMC.appendChild(e);d.appendChild(c.oMC);if(q)h=c.oMC.appendChild(g.createElement("div")),
-h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}catch(m){throw Error(w("appXHTML"));}}return!0};j=this.getSoundById;H=function(){if(p)return Q(),!1;if(c.o)return!1;c.o=c.getMovie(c.id);if(!c.o)I?(q?c.oMC.innerHTML=ga:c.oMC.appendChild(I),I=null,E=!0):Q(c.id,c.url),c.o=c.getMovie(c.id);c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return!0};ba=function(b){if(b)c.url=b;H()};P=function(){setTimeout(ra,500)};ra=function(){if(U)return!1;U=!0;l.remove(h,"load",P);if(D&&!na)return!1;var b;
-m||(b=c.getMoviePercent());setTimeout(function(){b=c.getMoviePercent();!m&&Ca&&(b===null?c.useFlashBlock||c.flashLoadTimeout===0?c.useFlashBlock&&ha():R(!0):c.flashLoadTimeout!==0&&R(!0))},c.flashLoadTimeout)};ba=function(b){if(b)c.url=b;H()};B=function(){var b=[];c.debugMode&&b.push(c.swfCSS.sm2Debug);c.debugFlash&&b.push(c.swfCSS.flashDebug);c.useHighPerformance&&b.push(c.swfCSS.highPerf);return b.join(" ")};ha=function(){w("fbHandler");var b=c.getMoviePercent(),a=c.swfCSS;if(c.ok()){if(c.oMC)c.oMC.className=
-[B(),a.swfDefault,a.swfLoaded+(c.didFlashBlock?" "+a.swfUnblocked:"")].join(" ")}else{if(x)c.oMC.className=B()+" "+a.swfDefault+" "+(b===null?a.swfTimedout:a.swfError);c.didFlashBlock=!0;u({type:"ontimeout",ignoreInit:!0});c.onerror instanceof Function&&c.onerror.apply(h)}};v=function(){function b(){l.remove(h,"focus",v);l.remove(h,"load",v)}if(na||!D)return b(),!0;na=Ca=!0;L&&D&&l.remove(h,"mousemove",v);U=!1;b();return!0};G=function(b){if(m)return!1;if(p)return m=!0,u(),z(),!0;c.useFlashBlock&&
-c.flashLoadTimeout&&!c.getMoviePercent()||(m=!0);if(t||b){if(c.useFlashBlock)c.oMC.className=B()+" "+(c.getMoviePercent()===null?c.swfCSS.swfTimedout:c.swfCSS.swfError);u({type:"ontimeout"});c.onerror instanceof Function&&c.onerror.apply(h);return!1}l.add(h,"unload",$);if(c.waitForWindowLoad&&!qa)return l.add(h,"load",z),!1;else z();return!0};aa=function(b,a,c){typeof r[b]==="undefined"&&(r[b]=[]);r[b].push({method:a,scope:c||null,fired:!1})};u=function(b){b||(b={type:"onready"});if(!m&&b&&!b.ignoreInit)return!1;
-var a={success:b&&b.ignoreInit?c.ok():!t},e=b&&b.type?r[b.type]||[]:[],b=[],f,d=x&&c.useFlashBlock&&!c.ok();for(f=0;f<e.length;f++)e[f].fired!==!0&&b.push(e[f]);if(b.length){f=0;for(e=b.length;f<e;f++)if(b[f].scope?b[f].method.apply(b[f].scope,[a]):b[f].method(a),!d)b[f].fired=!0}return!0};z=function(){h.setTimeout(function(){c.useFlashBlock&&ha();u();c.onload instanceof Function&&c.onload.apply(h);c.waitForWindowLoad&&l.add(h,"load",z)},1)};C=function(){if(la!==void 0)return la;var b=!1,a=navigator,
-c=a.plugins,f,d=h.ActiveXObject;if(c&&c.length)(a=a.mimeTypes)&&a["application/x-shockwave-flash"]&&a["application/x-shockwave-flash"].enabledPlugin&&a["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(typeof d!=="undefined"){try{f=new d("ShockwaveFlash.ShockwaveFlash")}catch(g){}b=!!f}return la=b};ya=function(){var b,a;if(n.match(/iphone os (1|2|3_0|3_1)/i)){c.hasHTML5=!1;p=!0;if(c.oMC)c.oMC.style.display="none";return!1}if(c.useHTML5Audio){if(!c.html5||!c.html5.canPlayType)return c.hasHTML5=
-!1,!0;else c.hasHTML5=!0;if(ma&&C())return!0}else return!0;for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&&c.audioFormats[a].required&&!c.html5.canPlayType(c.audioFormats[a].type)&&(b=!0);c.ignoreFlash&&(b=!1);p=c.useHTML5Audio&&c.hasHTML5&&!b&&!c.requireFlash;return C()&&b};O=function(){var b,a=[];if(m)return!1;if(c.hasHTML5)for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&a.push(b+": "+c.html5[b]);if(p){if(!m)l.remove(h,"load",c.beginDelayedInit),c.enabled=!0,G();return!0}H();
-try{c.o._externalInterfaceTest(!1),c.allowPolling&&ta(!0,c.flashPollingInterval?c.flashPollingInterval:c.useFastPolling?10:50),c.debugMode||c.o._disableDebug(),c.enabled=!0}catch(e){return R(!0),G(),!1}G();l.remove(h,"load",c.beginDelayedInit);return!0};sa=function(){if(ja)return!1;Q();H();return ja=!0};A=function(){if(da)return!1;da=!0;pa();if(!c.useHTML5Audio&&!C())c.useHTML5Audio=!0;za();c.html5.usingFlash=ya();x=c.html5.usingFlash;da=!0;g.removeEventListener&&g.removeEventListener("DOMContentLoaded",
-A,!1);ba();return!0};wa=function(b){if(!b._hasTimer)b._hasTimer=!0};xa=function(b){if(b._hasTimer)b._hasTimer=!1};fa=function(){if(c.onerror instanceof Function)c.onerror();c.disable()};Aa=function(){if(!ma||!C())return!1;var b=c.audioFormats,a,e;for(e in b)if(b.hasOwnProperty(e)&&(e==="mp3"||e==="mp4"))if(c.html5[e]=!1,b[e]&&b[e].related)for(a=b[e].related.length;a--;)c.html5[b[e].related[a]]=!1};this._setSandboxType=function(){};this._externalInterfaceOK=function(){if(c.swfLoaded)return!1;(new Date).getTime();
-c.swfLoaded=!0;D=!1;ma&&Aa();q?setTimeout(O,100):O()};ka=function(){g.readyState==="complete"&&(A(),g.detachEvent("onreadystatechange",ka));return!0};if(!c.hasHTML5||x)l.add(h,"focus",v),l.add(h,"load",v),l.add(h,"load",P),L&&D&&l.add(h,"mousemove",v);g.addEventListener?g.addEventListener("DOMContentLoaded",A,!1):g.attachEvent?g.attachEvent("onreadystatechange",ka):fa();g.readyState==="complete"&&setTimeout(A,100)}var X=null;if(typeof SM2_DEFER==="undefined"||!SM2_DEFER)X=new M;Y.SoundManager=M;Y.soundManager=
-X})(window);
\ No newline at end of file
+++ /dev/null
-/** @license\r
- * SoundManager 2: JavaScript Sound for the Web\r
- * ----------------------------------------------\r
- * http://schillmania.com/projects/soundmanager2/\r
- *\r
- * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
- * Code provided under the BSD License:\r
- * http://schillmania.com/projects/soundmanager2/license.txt\r
- *\r
- * V2.97a.20110424\r
- */\r
-\r
-/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */\r
-/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */\r
-\r
-(function(window) {\r
-\r
-var soundManager = null;\r
-\r
-function SoundManager(smURL, smID) {\r
-\r
- this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9.\r
- this.debugMode = true; // enable debugging output (div#soundmanager-debug, OR console if available+configured)\r
- this.debugFlash = false; // enable debugging output inside SWF, troubleshoot Flash/browser issues\r
- this.useConsole = true; // use firebug/safari console.log()-type debug console if available\r
- this.consoleOnly = false; // if console is being used, do not create/write to #soundmanager-debug\r
- this.waitForWindowLoad = false; // force SM2 to wait for window.onload() before trying to call soundManager.onload()\r
- this.nullURL = 'about:blank'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)\r
- this.allowPolling = true; // allow flash to poll for status update (required for whileplaying() events, peak, sound spectrum functions to work.)\r
- this.useFastPolling = false; // uses lower flash timer interval for higher callback frequency, best combined with useHighPerformance\r
- this.useMovieStar = true; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio formats (AAC, M4V, FLV, MOV etc.)\r
- this.bgColor = '#ffffff'; // movie (.swf) background color, eg. '#000000'\r
- this.useHighPerformance = false; // position:fixed flash movie can help increase js/flash speed, minimize lag\r
- this.flashPollingInterval = null; // msec for polling interval. Defaults to 50 unless useFastPolling = true.\r
- this.flashLoadTimeout = 1000; // msec to wait for flash movie to load before failing (0 = infinity)\r
- this.wmode = null; // string: flash rendering mode - null, transparent, opaque (last two allow layering of HTML on top)\r
- this.allowScriptAccess = 'always'; // for scripting the SWF (object/embed property), either 'always' or 'sameDomain'\r
- this.useFlashBlock = false; // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.\r
- this.useHTML5Audio = false; // Beta feature: Use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible.\r
- this.html5Test = /^probably$/i; // HTML5 Audio().canPlayType() test. /^(probably|maybe)$/i if you want to be more liberal/risky.\r
- this.useGlobalHTML5Audio = true; // (experimental) if true, re-use single HTML5 audio object across all sounds. Enabled by default on mobile devices/iOS.\r
- this.requireFlash = false; // (experimental) if true, prevents "HTML5-only" mode when flash present. Allows flash to handle RTMP/serverURL, but HTML5 for other cases\r
-\r
- this.audioFormats = {\r
- // determines HTML5 support, flash requirements\r
- // eg. if MP3 or MP4 required, Flash fallback is used if HTML5 can't play it\r
- // shotgun approach to MIME testing due to browser variance\r
- 'mp3': {\r
- 'type': ['audio/mpeg; codecs="mp3"','audio/mpeg','audio/mp3','audio/MPA','audio/mpa-robust'],\r
- 'required': true\r
- },\r
- 'mp4': {\r
- 'related': ['aac','m4a'], // additional formats under the MP4 container\r
- 'type': ['audio/mp4; codecs="mp4a.40.2"','audio/aac','audio/x-m4a','audio/MP4A-LATM','audio/mpeg4-generic'],\r
- 'required': true\r
- },\r
- 'ogg': {\r
- 'type': ['audio/ogg; codecs=vorbis'],\r
- 'required': false\r
- },\r
- 'wav': {\r
- 'type': ['audio/wav; codecs="1"','audio/wav','audio/wave','audio/x-wav'],\r
- 'required': false\r
- }\r
- };\r
-\r
- this.defaultOptions = {\r
- 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)\r
- 'stream': true, // allows playing before entire file has loaded (recommended)\r
- 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)\r
- 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)\r
- 'onid3': null, // callback function for "ID3 data is added/available"\r
- 'onload': null, // callback function for "load finished"\r
- 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)\r
- 'onplay': null, // callback for "play" start\r
- 'onpause': null, // callback for "pause"\r
- 'onresume': null, // callback for "resume" (pause toggle)\r
- 'whileplaying': null, // callback during play (position update)\r
- 'onstop': null, // callback for "user stop"\r
- 'onfailure': null, // callback function for when playing fails\r
- 'onfinish': null, // callback function for "sound finished playing"\r
- 'onbeforefinish': null, // callback for "before sound finished playing (at [time])"\r
- 'onbeforefinishtime': 5000, // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)\r
- 'onbeforefinishcomplete': null,// function to call when said sound finishes playing\r
- 'onjustbeforefinish': null, // callback for [n] msec before end of current sound\r
- 'onjustbeforefinishtime': 200, // [n] - if not using, set to 0 (or null handler) and event will not fire.\r
- 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time\r
- 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled\r
- 'position': null, // offset (milliseconds) to seek to within loaded sound data.\r
- 'pan': 0, // "pan" settings, left-to-right, -100 to 100\r
- 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3\r
- 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)\r
- 'volume': 100 // self-explanatory. 0-100, the latter being the max.\r
- };\r
-\r
- this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used\r
- 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL\r
- 'usePeakData': false, // enable left/right channel peak (level) data\r
- 'useWaveformData': false, // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.\r
- 'useEQData': false, // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.\r
- 'onbufferchange': null, // callback for "isBuffering" property change\r
- 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)\r
- };\r
-\r
- this.movieStarOptions = { // flash 9.0r115+ MPEG4 audio options, merged into defaultOptions if flash 9+movieStar mode is enabled\r
- 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)\r
- 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants\r
- 'onconnect': null, // rtmp: callback for connection to flash media server\r
- 'duration': null // rtmp: song duration (msec)\r
- };\r
-\r
- this.version = null;\r
- this.versionNumber = 'V2.97a.20110424';\r
- this.movieURL = null;\r
- this.url = (smURL || null);\r
- this.altURL = null;\r
- this.swfLoaded = false;\r
- this.enabled = false;\r
- this.o = null;\r
- this.movieID = 'sm2-container';\r
- this.id = (smID || 'sm2movie');\r
- this.swfCSS = {\r
- 'swfBox': 'sm2-object-box',\r
- 'swfDefault': 'movieContainer',\r
- 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)\r
- 'swfTimedout': 'swf_timedout',\r
- 'swfLoaded': 'swf_loaded',\r
- 'swfUnblocked': 'swf_unblocked', // or loaded OK\r
- 'sm2Debug': 'sm2_debug',\r
- 'highPerf': 'high_performance',\r
- 'flashDebug': 'flash_debug'\r
- };\r
- this.oMC = null;\r
- this.sounds = {};\r
- this.soundIDs = [];\r
- this.muted = false;\r
- this.debugID = 'soundmanager-debug';\r
- this.debugURLParam = /([#?&])debug=1/i;\r
- this.specialWmodeCase = false;\r
- this.didFlashBlock = false;\r
-\r
- this.filePattern = null;\r
- this.filePatterns = {\r
- 'flash8': /\.mp3(\?.*)?$/i,\r
- 'flash9': /\.mp3(\?.*)?$/i\r
- };\r
-\r
- this.baseMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3\r
- this.netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3, mp4, aac etc.\r
- this.netStreamTypes = ['aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2']; // Flash v9.0r115+ "moviestar" formats\r
- this.netStreamPattern = new RegExp('\\.(' + this.netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
- this.mimePattern = this.baseMimeTypes;\r
-\r
- this.features = {\r
- 'buffering': false,\r
- 'peakData': false,\r
- 'waveformData': false,\r
- 'eqData': false,\r
- 'movieStar': false\r
- };\r
-\r
- this.sandbox = {\r
- // <d>\r
- 'type': null,\r
- 'types': {\r
- 'remote': 'remote (domain-based) rules',\r
- 'localWithFile': 'local with file access (no internet access)',\r
- 'localWithNetwork': 'local with network (internet access only, no local access)',\r
- 'localTrusted': 'local, trusted (local+internet access)'\r
- },\r
- 'description': null,\r
- 'noRemote': null,\r
- 'noLocal': null\r
- // </d>\r
- };\r
-\r
- this.hasHTML5 = null; // switch for handling logic\r
- this.html5 = { // stores canPlayType() results, etc. treat as read-only.\r
- // mp3: boolean\r
- // mp4: boolean\r
- 'usingFlash': null // set if/when flash fallback is needed\r
- };\r
- this.ignoreFlash = false; // used for special cases (eg. iPad/iPhone/palm OS?)\r
-\r
- // --- private SM2 internals ---\r
-\r
- var SMSound,\r
- _s = this, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _fV = this.flashVersion, _doc = document, _doNothing, _init, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _addOnEvent, _processOnEvents, _initUserOnload, _go, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _beginInit, _strings, _initMovie, _dcLoaded, _didDCLoaded, _getDocument, _createMovie, _die, _setPolling, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _smTimer, _onTimer, _startTimer, _stopTimer, _needsFlash = null, _featureCheck, _html5OK, _html5Only = false, _html5CanPlay, _html5Ext, _dcIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix,\r
- _is_pre = _ua.match(/pre\//i), _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isMobile = (_ua.match(/mobile/i) || _is_pre || _is_iDevice), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), \r
- _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && _ua.match(/OS X 10_6_([3-9])/i)), // Safari 4 and 5 occasionally fail to load/play HTML5 audio on Snow Leopard due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Known Apple "radar" bug. https://bugs.webkit.org/show_bug.cgi?id=32159\r
- _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (typeof _doc.hasFocus === 'undefined' && _isSafari), _okToDisable = !_tryInitOnFocus;\r
-\r
- this._use_maybe = (_wl.match(/sm2\-useHTML5Maybe\=1/i)); // temporary feature: #sm2-useHTML5Maybe=1 forces loose canPlay() check\r
- this._overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null);\r
- this._http = (!this._overHTTP ? 'http:' : '');\r
- this.useAltURL = !this._overHTTP; // use altURL if not "online"\r
- this._global_a = null;\r
-\r
- if (_is_iDevice || _is_pre) {\r
- // during HTML5 beta period (off by default), may as well force it on Apple + Palm, flash support unlikely\r
- _s.useHTML5Audio = true;\r
- _s.ignoreFlash = true;\r
- if (_s.useGlobalHTML5Audio) {\r
- _useGlobalHTML5Audio = true;\r
- }\r
- }\r
-\r
- if (_is_pre || this._use_maybe) {\r
- // less-strict canPlayType() checking option\r
- _s.html5Test = /^(probably|maybe)$/i;\r
- }\r
-\r
- // Temporary feature: allow force of HTML5 via URL: #sm2-usehtml5audio=0 or 1\r
- // <d>\r
- (function(){\r
- var a = '#sm2-usehtml5audio=', l = _wl, b = null;\r
- if (l.indexOf(a) !== -1) {\r
- b = (l.charAt(l.indexOf(a)+a.length) === '1');\r
- if (typeof console !== 'undefined' && typeof console.log !== 'undefined') {\r
- console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter');\r
- }\r
- _s.useHTML5Audio = b;\r
- }\r
- }());\r
- // </d>\r
-\r
- // --- public API methods ---\r
-\r
- this.ok = function() {\r
- return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5));\r
- };\r
-\r
- this.supported = this.ok; // legacy\r
-\r
- this.getMovie = function(smID) {\r
- return _isIE?_win[smID]:(_isSafari?_id(smID) || _doc[smID]:_id(smID));\r
- };\r
-\r
- this.createSound = function(oOptions) {\r
- var _cs = _sm+'.createSound(): ',\r
- thisOptions = null, oSound = null, _tO = null;\r
- if (!_didInit || !_s.ok()) {\r
- _complain(_cs + _str(!_didInit?'notReady':'notOK'));\r
- return false;\r
- }\r
- if (arguments.length === 2) {\r
- // function overloading in JS! :) ..assume simple createSound(id,url) use case\r
- oOptions = {\r
- 'id': arguments[0],\r
- 'url': arguments[1]\r
- };\r
- }\r
- thisOptions = _mixin(oOptions); // inherit from defaultOptions\r
- _tO = thisOptions; // alias\r
- // <d>\r
- if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) {\r
- _s._wD(_cs + _str('badID', _tO.id), 2);\r
- }\r
- _s._wD(_cs + _tO.id + ' (' + _tO.url + ')', 1);\r
- // </d>\r
- if (_idCheck(_tO.id, true)) {\r
- _s._wD(_cs + _tO.id + ' exists', 1);\r
- return _s.sounds[_tO.id];\r
- }\r
-\r
- function make() {\r
- thisOptions = _loopFix(thisOptions);\r
- _s.sounds[_tO.id] = new SMSound(_tO);\r
- _s.soundIDs.push(_tO.id);\r
- return _s.sounds[_tO.id];\r
- }\r
-\r
- if (_html5OK(_tO)) {\r
- oSound = make();\r
- _s._wD('Loading sound '+_tO.id+' via HTML5');\r
- oSound._setup_html5(_tO);\r
- } else {\r
- if (_fV > 8 && _s.useMovieStar) {\r
- if (_tO.isMovieStar === null) {\r
- _tO.isMovieStar = ((_tO.serverURL || (_tO.type?_tO.type.match(_s.netStreamPattern):false)||_tO.url.match(_s.netStreamPattern))?true:false);\r
- }\r
- if (_tO.isMovieStar) {\r
- _s._wD(_cs + 'using MovieStar handling');\r
- }\r
- if (_tO.isMovieStar) {\r
- if (_tO.usePeakData) {\r
- _wDS('noPeak');\r
- _tO.usePeakData = false;\r
- }\r
- if (_tO.loops > 1) {\r
- _wDS('noNSLoop');\r
- }\r
- }\r
- }\r
- _tO = _policyFix(_tO, _cs);\r
- oSound = make();\r
- if (_fV === 8) {\r
- _s.o._createSound(_tO.id, _tO.onjustbeforefinishtime, _tO.loops||1, _tO.usePolicyFile);\r
- } else {\r
- _s.o._createSound(_tO.id, _tO.url, _tO.onjustbeforefinishtime, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile);\r
- if (!_tO.serverURL) {\r
- // We are connected immediately\r
- oSound.connected = true;\r
- if (_tO.onconnect) {\r
- _tO.onconnect.apply(oSound);\r
- }\r
- }\r
- }\r
-\r
- if ((_tO.autoLoad || _tO.autoPlay) && !_tO.serverURL) {\r
- oSound.load(_tO); // call load for non-rtmp streams\r
- }\r
- }\r
-\r
- if (_tO.autoPlay && !_tO.serverURL) { // rtmp will play in onconnect\r
- oSound.play();\r
- }\r
- return oSound;\r
- };\r
-\r
- this.destroySound = function(sID, _bFromSound) {\r
- // explicitly destroy a sound before normal page unload, etc.\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- var oS = _s.sounds[sID], i;\r
- oS._iO = {}; // Disable all callbacks while the sound is being destroyed\r
- oS.stop();\r
- oS.unload();\r
- for (i = 0; i < _s.soundIDs.length; i++) {\r
- if (_s.soundIDs[i] === sID) {\r
- _s.soundIDs.splice(i, 1);\r
- break;\r
- }\r
- }\r
- if (!_bFromSound) {\r
- // ignore if being called from SMSound instance\r
- oS.destruct(true);\r
- }\r
- oS = null;\r
- delete _s.sounds[sID];\r
- return true;\r
- };\r
-\r
- this.load = function(sID, oOptions) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].load(oOptions);\r
- };\r
-\r
- this.unload = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].unload();\r
- };\r
-\r
- this.play = function(sID, oOptions) {\r
- var fN = _sm+'.play(): ';\r
- if (!_didInit || !_s.ok()) {\r
- _complain(fN + _str(!_didInit?'notReady':'notOK'));\r
- return false;\r
- }\r
- if (!_idCheck(sID)) {\r
- if (!(oOptions instanceof Object)) {\r
- oOptions = {\r
- url: oOptions\r
- }; // overloading use case: play('mySound','/path/to/some.mp3');\r
- }\r
- if (oOptions && oOptions.url) {\r
- // overloading use case, create+play: .play('someID',{url:'/path/to.mp3'});\r
- _s._wD(fN + 'attempting to create "' + sID + '"', 1);\r
- oOptions.id = sID;\r
- return _s.createSound(oOptions).play();\r
- } else {\r
- return false;\r
- }\r
- }\r
- return _s.sounds[sID].play(oOptions);\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.setPosition = function(sID, nMsecOffset) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].setPosition(nMsecOffset);\r
- };\r
-\r
- this.stop = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD(_sm+'.stop(' + sID + ')', 1);\r
- return _s.sounds[sID].stop();\r
- };\r
-\r
- this.stopAll = function() {\r
- _s._wD(_sm+'.stopAll()', 1);\r
- for (var oSound in _s.sounds) {\r
- if (_s.sounds[oSound] instanceof SMSound) {\r
- _s.sounds[oSound].stop(); // apply only to sound objects\r
- }\r
- }\r
- };\r
-\r
- this.pause = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].pause();\r
- };\r
-\r
- this.pauseAll = function() {\r
- for (var i = _s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].pause();\r
- }\r
- };\r
-\r
- this.resume = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].resume();\r
- };\r
-\r
- this.resumeAll = function() {\r
- for (var i = _s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].resume();\r
- }\r
- };\r
-\r
- this.togglePause = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].togglePause();\r
- };\r
-\r
- this.setPan = function(sID, nPan) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].setPan(nPan);\r
- };\r
-\r
- this.setVolume = function(sID, nVol) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].setVolume(nVol);\r
- };\r
-\r
- this.mute = function(sID) {\r
- var fN = _sm+'.mute(): ',\r
- i = 0;\r
- if (typeof sID !== 'string') {\r
- sID = null;\r
- }\r
- if (!sID) {\r
- _s._wD(fN + 'Muting all sounds');\r
- for (i = _s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].mute();\r
- }\r
- _s.muted = true;\r
- } else {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD(fN + 'Muting "' + sID + '"');\r
- return _s.sounds[sID].mute();\r
- }\r
- return true;\r
- };\r
-\r
- this.muteAll = function() {\r
- _s.mute();\r
- };\r
-\r
- this.unmute = function(sID) {\r
- var fN = _sm+'.unmute(): ', i;\r
- if (typeof sID !== 'string') {\r
- sID = null;\r
- }\r
- if (!sID) {\r
- _s._wD(fN + 'Unmuting all sounds');\r
- for (i = _s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].unmute();\r
- }\r
- _s.muted = false;\r
- } else {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD(fN + 'Unmuting "' + sID + '"');\r
- return _s.sounds[sID].unmute();\r
- }\r
- return true;\r
- };\r
-\r
- this.unmuteAll = function() {\r
- _s.unmute();\r
- };\r
-\r
- this.toggleMute = function(sID) {\r
- if (!_idCheck(sID)) {\r
- return false;\r
- }\r
- return _s.sounds[sID].toggleMute();\r
- };\r
-\r
- this.getMemoryUse = function() {\r
- if (_fV === 8) {\r
- return 0;\r
- }\r
- if (_s.o) {\r
- return parseInt(_s.o._getMemoryUse(), 10);\r
- }\r
- };\r
-\r
- this.disable = function(bNoDisable) {\r
- // destroy all functions\r
- if (typeof bNoDisable === 'undefined') {\r
- bNoDisable = false;\r
- }\r
- if (_disabled) {\r
- return false;\r
- }\r
- _disabled = true;\r
- _wDS('shutdown', 1);\r
- for (var i = _s.soundIDs.length; i--;) {\r
- _disableObject(_s.sounds[_s.soundIDs[i]]);\r
- }\r
- _initComplete(bNoDisable); // fire "complete", despite fail\r
- _event.remove(_win, 'load', _initUserOnload);\r
- return true;\r
- };\r
-\r
- this.canPlayMIME = function(sMIME) {\r
- var result;\r
- if (_s.hasHTML5) {\r
- result = _html5CanPlay({type:sMIME});\r
- }\r
- if (!_needsFlash || result) {\r
- // no flash, or OK\r
- return result;\r
- } else {\r
- return (sMIME?(sMIME.match(_s.mimePattern)?true:false):null);\r
- }\r
- };\r
-\r
- this.canPlayURL = function(sURL) {\r
- var result;\r
- if (_s.hasHTML5) {\r
- result = _html5CanPlay(sURL);\r
- }\r
- if (!_needsFlash || result) {\r
- // no flash, or OK\r
- return result;\r
- } else {\r
- return (sURL?(sURL.match(_s.filePattern)?true:false):null);\r
- }\r
- };\r
-\r
- this.canPlayLink = function(oLink) {\r
- if (typeof oLink.type !== 'undefined' && oLink.type) {\r
- if (_s.canPlayMIME(oLink.type)) {\r
- return true;\r
- }\r
- }\r
- return _s.canPlayURL(oLink.href);\r
- };\r
-\r
- this.getSoundById = function(sID, suppressDebug) {\r
- if (!sID) {\r
- throw new Error(_sm+'.getSoundById(): sID is null/undefined');\r
- }\r
- var result = _s.sounds[sID];\r
- if (!result && !suppressDebug) {\r
- _s._wD('"' + sID + '" is an invalid sound ID.', 2);\r
- }\r
- return result;\r
- };\r
-\r
- this.onready = function(oMethod, oScope) {\r
- var sType = 'onready';\r
- if (oMethod && oMethod instanceof Function) {\r
- if (_didInit) {\r
- _wDS('queue', sType);\r
- }\r
- if (!oScope) {\r
- oScope = _win;\r
- }\r
- _addOnEvent(sType, oMethod, oScope);\r
- _processOnEvents();\r
- return true;\r
- } else {\r
- throw _str('needFunction', sType);\r
- }\r
- };\r
-\r
- this.ontimeout = function(oMethod, oScope) {\r
- var sType = 'ontimeout';\r
- if (oMethod && oMethod instanceof Function) {\r
- if (_didInit) {\r
- _wDS('queue');\r
- }\r
- if (!oScope) {\r
- oScope = _win;\r
- }\r
- _addOnEvent(sType, oMethod, oScope);\r
- _processOnEvents({type:sType});\r
- return true;\r
- } else {\r
- throw _str('needFunction', sType);\r
- }\r
- };\r
-\r
- this.getMoviePercent = function() {\r
- return (_s.o && typeof _s.o.PercentLoaded !== 'undefined'?_s.o.PercentLoaded():null);\r
- };\r
-\r
- this._writeDebug = function(sText, sType, bTimestamp) {\r
- // pseudo-private console.log()-style output\r
- // <d>\r
- var sDID = 'soundmanager-debug', o, oItem, sMethod;\r
- if (!_s.debugMode) {\r
- return false;\r
- }\r
- if (typeof bTimestamp !== 'undefined' && bTimestamp) {\r
- sText = sText + ' | ' + new Date().getTime();\r
- }\r
- if (_hasConsole && _s.useConsole) {\r
- sMethod = _debugLevels[sType];\r
- if (typeof console[sMethod] !== 'undefined') {\r
- console[sMethod](sText);\r
- } else {\r
- console.log(sText);\r
- }\r
- if (_s.useConsoleOnly) {\r
- return true;\r
- }\r
- }\r
- try {\r
- o = _id(sDID);\r
- if (!o) {\r
- return false;\r
- }\r
- oItem = _doc.createElement('div');\r
- if (++_wdCount % 2 === 0) {\r
- oItem.className = 'sm2-alt';\r
- }\r
- if (typeof sType === 'undefined') {\r
- sType = 0;\r
- } else {\r
- sType = parseInt(sType, 10);\r
- }\r
- oItem.appendChild(_doc.createTextNode(sText));\r
- if (sType) {\r
- if (sType >= 2) {\r
- oItem.style.fontWeight = 'bold';\r
- }\r
- if (sType === 3) {\r
- oItem.style.color = '#ff3333';\r
- }\r
- }\r
- // o.appendChild(oItem); // top-to-bottom\r
- o.insertBefore(oItem, o.firstChild); // bottom-to-top\r
- } catch(e) {\r
- // oh well\r
- }\r
- o = null;\r
- // </d>\r
- return true;\r
- };\r
- this._wD = this._writeDebug; // alias\r
-\r
- this._debug = function() {\r
- // <d>\r
- _wDS('currentObj', 1);\r
- for (var i = 0, j = _s.soundIDs.length; i < j; i++) {\r
- _s.sounds[_s.soundIDs[i]]._debug();\r
- }\r
- // </d>\r
- };\r
-\r
- this.reboot = function() {\r
- // attempt to reset and init SM2\r
- _s._wD(_sm+'.reboot()');\r
- if (_s.soundIDs.length) {\r
- _s._wD('Destroying ' + _s.soundIDs.length + ' SMSound objects...');\r
- }\r
- var i, j;\r
- for (i = _s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].destruct();\r
- }\r
- // trash ze flash\r
- try {\r
- if (_isIE) {\r
- _oRemovedHTML = _s.o.innerHTML;\r
- }\r
- _oRemoved = _s.o.parentNode.removeChild(_s.o);\r
- _s._wD('Flash movie removed.');\r
- } catch(e) {\r
- // uh-oh.\r
- _wDS('badRemove', 2);\r
- }\r
- // actually, force recreate of movie.\r
- _oRemovedHTML = _oRemoved = null;\r
- _s.enabled = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false;\r
- _s.soundIDs = _s.sounds = [];\r
- _s.o = null;\r
- for (i in _on_queue) {\r
- if (_on_queue.hasOwnProperty(i)) {\r
- for (j = _on_queue[i].length; j--;) {\r
- _on_queue[i][j].fired = false;\r
- }\r
- }\r
- }\r
- _s._wD(_sm + ': Rebooting...');\r
- _win.setTimeout(function() {\r
- _s.beginDelayedInit();\r
- }, 20);\r
- };\r
-\r
- this.destruct = function() {\r
- _s._wD(_sm+'.destruct()');\r
- _s.disable(true);\r
- };\r
-\r
- this.beginDelayedInit = function() {\r
- // _s._wD(_sm+'.beginDelayedInit()');\r
- _windowLoaded = true;\r
- _dcLoaded();\r
- setTimeout(_beginInit, 20);\r
- _delayWaitForEI();\r
- };\r
-\r
-\r
- // Wrap html5 event handlers so we don't call them on destroyed sounds\r
- function _html5_event(oFn) {\r
- return function(e) {\r
- if (!this._t || !this._t._a) {\r
- if (this._t && this._t.sID) {\r
- _s._wD(_h5+'ignoring '+e.type+': '+this._t.sID);\r
- } else {\r
- _s._wD(_h5+'ignoring '+e.type);\r
- }\r
- return null;\r
- } else {\r
- return oFn.call(this, e);\r
- }\r
- };\r
- }\r
-\r
- this._html5_events = {\r
-\r
- // HTML5 event-name-to-handler map\r
- abort: _html5_event(function(e) {\r
- _s._wD(_h5+'abort: '+this._t.sID);\r
- }),\r
-\r
- // enough has loaded to play\r
- canplay: _html5_event(function(e) {\r
- _s._wD(_h5+'canplay: '+this._t.sID+', '+this._t.url);\r
- this._t._onbufferchange(0);\r
- var position1K = (!isNaN(this._t.position)?this._t.position/1000:null);\r
- // set the position if position was set before the sound loaded\r
- this._t._html5_canplay = true;\r
- if (this._t.position && this.currentTime !== position1K) {\r
- _s._wD(_h5+'canplay: setting position to '+position1K+'');\r
- try {\r
- this.currentTime = position1K;\r
- } catch(ee) {\r
- _s._wD(_h5+'setting position failed: '+ee.message, 2);\r
- }\r
- }\r
- }),\r
-\r
- load: _html5_event(function(e) {\r
- if (!this._t.loaded) {\r
- this._t._onbufferchange(0);\r
- // should be 1, and the same\r
- this._t._whileloading(this._t.bytesTotal, this._t.bytesTotal, this._t._get_html5_duration());\r
- this._t._onload(true);\r
- }\r
- }),\r
-\r
- emptied: _html5_event(function(e) {\r
- _s._wD(_h5+'emptied: '+this._t.sID);\r
- }),\r
-\r
- ended: _html5_event(function(e) {\r
- _s._wD(_h5+'ended: '+this._t.sID);\r
- this._t._onfinish();\r
- }),\r
-\r
- error: _html5_event(function(e) {\r
- _s._wD(_h5+'error: '+this.error.code);\r
- // call load with error state?\r
- this._t._onload(false);\r
- }),\r
-\r
- loadeddata: _html5_event(function(e) {\r
- _s._wD(_h5+'loadeddata: '+this._t.sID);\r
- }),\r
-\r
- loadedmetadata: _html5_event(function(e) {\r
- _s._wD(_h5+'loadedmetadata: '+this._t.sID);\r
- }),\r
-\r
- loadstart: _html5_event(function(e) {\r
- _s._wD(_h5+'loadstart: '+this._t.sID);\r
- // assume buffering at first\r
- this._t._onbufferchange(1);\r
- }),\r
-\r
- play: _html5_event(function(e) {\r
- _s._wD(_h5+'play: '+this._t.sID+', '+this._t.url);\r
- // once play starts, no buffering\r
- this._t._onbufferchange(0);\r
- }),\r
-\r
- // TODO: verify if this is actually implemented anywhere yet.\r
- playing: _html5_event(function(e) {\r
- _s._wD(_h5+'playing: '+this._t.sID+', '+this._t.url);\r
- // once play starts, no buffering\r
- this._t._onbufferchange(0);\r
- }),\r
-\r
- progress: _html5_event(function(e) {\r
-\r
- if (this._t.loaded) {\r
- return false;\r
- }\r
-\r
- var i, j, str, loadSum = 0, buffered = 0,\r
- isProgress = (e.type === 'progress'),\r
- ranges = e.target.buffered,\r
- loaded = (e.loaded||0), // firefox 3.6 implements e.loaded/total (bytes)\r
- total = (e.total||1);\r
-\r
- if (ranges && ranges.length) {\r
-\r
- // if loaded is 0, try TimeRanges implementation as % of load\r
- // https://developer.mozilla.org/en/DOM/TimeRanges\r
- for (i=ranges.length; i--;) {\r
- buffered = (ranges.end(i) - ranges.start(i));\r
- }\r
-\r
- // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges\r
- loaded = buffered/e.target.duration;\r
-\r
- // <d>\r
- if (isProgress && ranges.length > 1) {\r
- str = [];\r
- j = ranges.length;\r
- for (i=0; i<j; i++) {\r
- str.push(e.target.buffered.start(i) +'-'+ e.target.buffered.end(i));\r
- }\r
- _s._wD(_h5+'progress: timeRanges: '+str.join(', '));\r
- }\r
- // </d>\r
-\r
- if (isProgress && !isNaN(loaded)) {\r
- _s._wD(_h5+'progress: '+this._t.sID+': ' + Math.floor(loaded*100)+'% loaded');\r
- }\r
-\r
- }\r
-\r
- if (!isNaN(loaded)) {\r
-\r
- this._t._onbufferchange(0); // if progress, likely not buffering\r
- this._t._whileloading(loaded, total, this._t._get_html5_duration());\r
-\r
- if (loaded && total && loaded === total) {\r
- // in case "onload" doesn't fire (eg. gecko 1.9.2)\r
- _s._html5_events.load.call(this, e);\r
- }\r
-\r
- }\r
-\r
- }),\r
-\r
- ratechange: _html5_event(function(e) {\r
- _s._wD(_h5+'ratechange: '+this._t.sID);\r
- }),\r
-\r
- suspend: _html5_event(function(e) {\r
- // download paused/stopped, may have finished (eg. onload)\r
- _s._wD(_h5+'suspend: '+this._t.sID);\r
- _s._html5_events.progress.call(this, e);\r
- }),\r
-\r
- stalled: _html5_event(function(e) {\r
- _s._wD(_h5+'stalled: '+this._t.sID);\r
- }),\r
-\r
- timeupdate: _html5_event(function(e) {\r
- this._t._onTimer();\r
- }),\r
-\r
- waiting: _html5_event(function(e) { // see also: seeking\r
- _s._wD(_h5+'waiting: '+this._t.sID);\r
- // playback faster than download rate, etc.\r
- this._t._onbufferchange(1);\r
- })\r
-\r
- };\r
-\r
- // --- SMSound (sound object) instance ---\r
-\r
- SMSound = function(oOptions) {\r
- var _t = this, _resetProperties, _stop_html5_timer, _start_html5_timer;\r
- this.sID = oOptions.id;\r
- this.url = oOptions.url;\r
- this.options = _mixin(oOptions);\r
- this.instanceOptions = this.options; // per-play-instance-specific options\r
- this._iO = this.instanceOptions; // short alias\r
- // assign property defaults\r
- this.pan = this.options.pan;\r
- this.volume = this.options.volume;\r
- this._lastURL = null;\r
- this.isHTML5 = false;\r
- this._a = null;\r
-\r
- // --- public methods ---\r
-\r
- this.id3 = {};\r
-\r
- this._debug = function() {\r
- // <d>\r
- // pseudo-private console.log()-style output\r
- if (_s.debugMode) {\r
- var stuff = null, msg = [], sF, sfBracket, maxLength = 64;\r
- for (stuff in _t.options) {\r
- if (_t.options[stuff] !== null) {\r
- if (_t.options[stuff] instanceof Function) {\r
- // handle functions specially\r
- sF = _t.options[stuff].toString();\r
- sF = sF.replace(/\s\s+/g, ' '); // normalize spaces\r
- sfBracket = sF.indexOf('{');\r
- msg.push(' ' + stuff + ': {' + sF.substr(sfBracket + 1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '') + '... }');\r
- } else {\r
- msg.push(' ' + stuff + ': ' + _t.options[stuff]);\r
- }\r
- }\r
- }\r
- _s._wD('SMSound() merged options: {\n' + msg.join(', \n') + '\n}');\r
- }\r
- // </d>\r
- };\r
-\r
- this._debug();\r
-\r
- this.load = function(oOptions) {\r
- var oS = null;\r
- if (typeof oOptions !== 'undefined') {\r
- _t._iO = _mixin(oOptions, _t.options);\r
- _t.instanceOptions = _t._iO;\r
- } else {\r
- oOptions = _t.options;\r
- _t._iO = oOptions;\r
- _t.instanceOptions = _t._iO;\r
- if (_t._lastURL && _t._lastURL !== _t.url) {\r
- _wDS('manURL');\r
- _t._iO.url = _t.url;\r
- _t.url = null;\r
- }\r
- }\r
- if (!_t._iO.url) {\r
- _t._iO.url = _t.url;\r
- }\r
- _s._wD('SMSound.load(): ' + _t._iO.url, 1);\r
- if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) {\r
- _wDS('onURL', 1);\r
- return _t;\r
- }\r
- _t._lastURL = _t.url;\r
- _t.loaded = false;\r
- _t.readyState = 1;\r
- _t.playState = 0;\r
- if (_html5OK(_t._iO)) {\r
- oS = _t._setup_html5(_t._iO);\r
- if (!oS._called_load) {\r
- _s._wD(_h5+'load: '+_t.sID);\r
- oS.load();\r
- oS._called_load = true;\r
- if (_t._iO.autoPlay) {\r
- _t.play();\r
- }\r
- } else {\r
- _s._wD('HTML5 ignoring request to load again: '+_t.sID);\r
- }\r
- } else {\r
- try {\r
- _t.isHTML5 = false;\r
- _t._iO = _policyFix(_loopFix(_t._iO));\r
- if (_fV === 8) {\r
- _s.o._load(_t.sID, _t._iO.url, _t._iO.stream, _t._iO.autoPlay, (_t._iO.whileloading?1:0), _t._iO.loops||1, _t._iO.usePolicyFile);\r
- } else {\r
- _s.o._load(_t.sID, _t._iO.url, _t._iO.stream?true:false, _t._iO.autoPlay?true:false, _t._iO.loops||1, _t._iO.autoLoad?true:false, _t._iO.usePolicyFile);\r
- }\r
- } catch(e) {\r
- _wDS('smError', 2);\r
- _debugTS('onload', false);\r
- _die();\r
- }\r
- }\r
- return _t;\r
- };\r
-\r
- this.unload = function() {\r
- // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3\r
- // Flash 9/AS3: Close stream, preventing further load\r
- if (_t.readyState !== 0) {\r
- _s._wD('SMSound.unload(): "' + _t.sID + '"');\r
- if (!_t.isHTML5) {\r
- if (_fV === 8) {\r
- _s.o._unload(_t.sID, _s.nullURL);\r
- } else {\r
- _s.o._unload(_t.sID);\r
- }\r
- } else {\r
- _stop_html5_timer();\r
- if (_t._a) {\r
- // abort()-style method here, stop loading? (doesn't exist?)\r
- _t._a.pause();\r
-// if (!_useGlobalHTML5Audio || (_useGlobalHTML5Audio && _t.playState)) { // if global audio, only unload if actively playing\r
- _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
-// }\r
- }\r
- }\r
- // reset load/status flags\r
- _resetProperties();\r
- }\r
- return _t;\r
- };\r
-\r
- this.destruct = function(_bFromSM) {\r
- _s._wD('SMSound.destruct(): "' + _t.sID + '"');\r
- if (!_t.isHTML5) {\r
- // kill sound within Flash\r
- // Disable the onfailure handler\r
- _t._iO.onfailure = null;\r
- _s.o._destroySound(_t.sID);\r
- } else {\r
- _stop_html5_timer();\r
- if (_t._a) {\r
- // abort()-style method here, stop loading? (doesn't exist?)\r
- _t._a.pause();\r
- _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
- if (!_useGlobalHTML5Audio) {\r
- _t._remove_html5_events();\r
- }\r
- }\r
- }\r
- if (!_bFromSM) {\r
- _s.destroySound(_t.sID, true); // ensure deletion from controller\r
- }\r
- };\r
-\r
- this.play = function(oOptions, _updatePlayState) {\r
- var fN = 'SMSound.play(): ', allowMulti;\r
- _updatePlayState = _updatePlayState === undefined ? true : _updatePlayState; // default true\r
- if (!oOptions) {\r
- oOptions = {};\r
- }\r
- _t._iO = _mixin(oOptions, _t._iO);\r
- _t._iO = _mixin(_t._iO, _t.options);\r
- _t.instanceOptions = _t._iO;\r
- if (_t._iO.serverURL) {\r
- if (!_t.connected) {\r
- if (!_t.getAutoPlay()) {\r
- _s._wD(fN+' Netstream not connected yet - setting autoPlay');\r
- _t.setAutoPlay(true);\r
- }\r
- return _t; // play will be called in _onconnect()\r
- }\r
- }\r
- if (_html5OK(_t._iO)) {\r
- _t._setup_html5(_t._iO);\r
- _start_html5_timer();\r
- }\r
- if (_t.playState === 1 && !_t.paused) {\r
- allowMulti = _t._iO.multiShot;\r
- if (!allowMulti) {\r
- _s._wD(fN + '"' + _t.sID + '" already playing (one-shot)', 1);\r
- return _t;\r
- } else {\r
- _s._wD(fN + '"' + _t.sID + '" already playing (multi-shot)', 1);\r
- if (_t.isHTML5) {\r
- // TODO: BUG?\r
- _t.setPosition(_t._iO.position);\r
- }\r
- }\r
- }\r
- if (!_t.loaded) {\r
- if (_t.readyState === 0) {\r
- _s._wD(fN + 'Attempting to load "' + _t.sID + '"', 1);\r
- // try to get this sound playing ASAP\r
- if (!_t.isHTML5) {\r
- _t._iO.autoPlay = true; // assign directly because setAutoPlay() increments the instanceCount\r
- _t.load(_t._iO);\r
- } else {\r
- _t.load(_t._iO);\r
- // _t.readyState = 1; // redundant\r
- }\r
- } else if (_t.readyState === 2) {\r
- _s._wD(fN + 'Could not load "' + _t.sID + '" - exiting', 2);\r
- return _t;\r
- } else {\r
- _s._wD(fN + '"' + _t.sID + '" is loading - attempting to play..', 1);\r
- }\r
- } else {\r
- _s._wD(fN + '"' + _t.sID + '"');\r
- }\r
- // Streams will pause when their buffer is full if they are being loaded.\r
- // In this case paused is true, but the song hasn't started playing yet. If\r
- // we just call resume() the onplay() callback will never be called. So\r
- // only call resume() if the position is > 0.\r
- // Another reason is because options like volume won't have been applied yet.\r
- if (_t.paused && _t.position && _t.position > 0) { // https://gist.github.com/37b17df75cc4d7a90bf6\r
- _s._wD(fN + '"' + _t.sID + '" is resuming from paused state',1);\r
- _t.resume();\r
- } else {\r
- _s._wD(fN+'"'+ _t.sID+'" is starting to play');\r
- _t.playState = 1;\r
- _t.paused = false;\r
- if (!_t.instanceCount || _t._iO.multiShotEvents || (_fV > 8 && !_t.isHTML5 && !_t.getAutoPlay())) {\r
- _t.instanceCount++;\r
- }\r
- _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);\r
- if (!_t.isHTML5) {\r
- _t._iO = _policyFix(_loopFix(_t._iO));\r
- }\r
- if (_t._iO.onplay && _updatePlayState) {\r
- _t._iO.onplay.apply(_t);\r
- _t._onplay_called = true;\r
- }\r
- _t.setVolume(_t._iO.volume, true);\r
- _t.setPan(_t._iO.pan, true);\r
- if (!_t.isHTML5) {\r
- _s.o._start(_t.sID, _t._iO.loops || 1, (_fV === 9?_t.position:_t.position / 1000));\r
- } else {\r
- _start_html5_timer();\r
- _t._setup_html5().play();\r
- }\r
- }\r
- return _t;\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.stop = function(bAll) {\r
- if (_t.playState === 1) {\r
- _t._onbufferchange(0);\r
- _t.resetOnPosition(0);\r
- if (!_t.isHTML5) {\r
- _t.playState = 0;\r
- }\r
- _t.paused = false;\r
- if (_t._iO.onstop) {\r
- _t._iO.onstop.apply(_t);\r
- }\r
- if (!_t.isHTML5) {\r
- _s.o._stop(_t.sID, bAll);\r
- // hack for netStream: just unload\r
- if (_t._iO.serverURL) {\r
- _t.unload();\r
- }\r
- } else {\r
- if (_t._a) {\r
- _t.setPosition(0); // act like Flash, though\r
- _t._a.pause(); // html5 has no stop()\r
- _t.playState = 0;\r
- _t._onTimer(); // and update UI\r
- _stop_html5_timer();\r
- _t.unload();\r
- }\r
- }\r
- _t.instanceCount = 0;\r
- _t._iO = {};\r
- }\r
- return _t;\r
- };\r
-\r
- this.setAutoPlay = function(autoPlay) {\r
- _s._wD('sound '+_t.sID+' turned autoplay ' + (autoPlay ? 'on' : 'off'));\r
- _t._iO.autoPlay = autoPlay;\r
- if (_t.isHTML5) {\r
- if (_t._a && autoPlay) {\r
- _t.play(); // HTML5 onload isn't reliable\r
- }\r
- } else {\r
- _s.o._setAutoPlay(_t.sID, autoPlay);\r
- }\r
- if (autoPlay) {\r
- // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP)\r
- if (!_t.instanceCount && _t.readyState === 1) {\r
- _t.instanceCount++;\r
- _s._wD('sound '+_t.sID+' incremented instance count to '+_t.instanceCount);\r
- }\r
- }\r
- };\r
-\r
- this.getAutoPlay = function() {\r
- return _t._iO.autoPlay;\r
- };\r
-\r
- this.setPosition = function(nMsecOffset, bNoDebug) {\r
- if (nMsecOffset === undefined) {\r
- nMsecOffset = 0;\r
- }\r
- // Use the duration from the instance options, if we don't have a track duration yet.\r
- var original_pos, position, position1K, offset = (_t.isHTML5 ? Math.max(nMsecOffset,0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); // position >= 0 and <= current available (loaded) duration\r
- original_pos = _t.position;\r
- _t.position = offset;\r
- position1K = _t.position/1000;\r
- _t.resetOnPosition(_t.position);\r
- _t._iO.position = offset;\r
- if (!_t.isHTML5) {\r
- position = _fV === 9 ? _t.position : position1K;\r
- if (_t.readyState && _t.readyState !== 2) {\r
- _s.o._setPosition(_t.sID, position, (_t.paused || !_t.playState)); // if paused or not playing, will not resume (by playing)\r
- }\r
- } else if (_t._a) {\r
- // Set the position in the canplay handler if the sound is not ready yet\r
- if (_t._html5_canplay) {\r
- if (_t._a.currentTime !== position1K) {\r
- // Only set the position if we need to.\r
- // DOM/JS errors/exceptions to watch out for:\r
- // if seek is beyond (loaded?) position, "DOM exception 11"\r
- // "INDEX_SIZE_ERR": DOM exception 1\r
- _s._wD('setPosition('+position1K+'): setting position');\r
- try {\r
- _t._a.currentTime = position1K;\r
- } catch(e) {\r
- _s._wD('setPosition('+position1K+'): setting position failed: '+e.message, 2);\r
- }\r
- }\r
- } else {\r
- _s._wD('setPosition('+position1K+'): delaying, sound not ready');\r
- }\r
- }\r
- if (_t.isHTML5) {\r
- if (_t.paused) { // if paused, refresh UI right away\r
- _t._onTimer(true); // force update\r
- }\r
- }\r
- return _t;\r
- };\r
-\r
- this.pause = function(bCallFlash) {\r
- if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) {\r
- return _t;\r
- }\r
- _s._wD('SMSound.pause()');\r
- _t.paused = true;\r
- if (!_t.isHTML5) {\r
- if (bCallFlash || bCallFlash === undefined) {\r
- _s.o._pause(_t.sID);\r
- }\r
- } else {\r
- _t._setup_html5().pause();\r
- _stop_html5_timer();\r
- }\r
- if (_t._iO.onpause) {\r
- _t._iO.onpause.apply(_t);\r
- }\r
- return _t;\r
- };\r
-\r
- // When auto-loaded streams pause on buffer full they have a playState of 0.\r
- // We need to make sure that the playState is set to 1 when these streams "resume".\r
- //\r
- // When a paused stream is resumed, we need to trigger the onplay() callback if it\r
- // hasn't been called already. In this case since the sound is being played for the\r
- // first time, I think it's more appropriate to call onplay() rather than onresume().\r
- this.resume = function() {\r
- if (!_t.paused) {\r
- return _t;\r
- }\r
- _s._wD('SMSound.resume()');\r
- _t.paused = false;\r
- _t.playState = 1;\r
- if (!_t.isHTML5) {\r
- if (_t._iO.isMovieStar) {\r
- // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.\r
- _t.setPosition(_t.position);\r
- }\r
- _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)\r
- } else {\r
- _t._setup_html5().play();\r
- _start_html5_timer();\r
- }\r
- if (!_t._onplay_called && _t._iO.onplay) {\r
- _t._iO.onplay.apply(_t);\r
- _t._onplay_called = true;\r
- } else if (_t._iO.onresume) {\r
- _t._iO.onresume.apply(_t);\r
- }\r
- return _t;\r
- };\r
-\r
- this.togglePause = function() {\r
- _s._wD('SMSound.togglePause()');\r
- if (_t.playState === 0) {\r
- _t.play({\r
- position: (_fV === 9 && !_t.isHTML5 ? _t.position:_t.position / 1000)\r
- });\r
- return _t;\r
- }\r
- if (_t.paused) {\r
- _t.resume();\r
- } else {\r
- _t.pause();\r
- }\r
- return _t;\r
- };\r
-\r
- this.setPan = function(nPan, bInstanceOnly) {\r
- if (typeof nPan === 'undefined') {\r
- nPan = 0;\r
- }\r
- if (typeof bInstanceOnly === 'undefined') {\r
- bInstanceOnly = false;\r
- }\r
- if (!_t.isHTML5) {\r
- _s.o._setPan(_t.sID, nPan);\r
- } // else { no HTML5 pan? }\r
- _t._iO.pan = nPan;\r
- if (!bInstanceOnly) {\r
- _t.pan = nPan;\r
- _t.options.pan = nPan;\r
- }\r
- return _t;\r
- };\r
-\r
- this.setVolume = function(nVol, bInstanceOnly) {\r
- if (typeof nVol === 'undefined') {\r
- nVol = 100;\r
- }\r
- if (typeof bInstanceOnly === 'undefined') {\r
- bInstanceOnly = false;\r
- }\r
- if (!_t.isHTML5) {\r
- _s.o._setVolume(_t.sID, (_s.muted && !_t.muted) || _t.muted?0:nVol);\r
- } else if (_t._a) {\r
- _t._a.volume = Math.max(0, Math.min(1, nVol/100)); // valid range: 0-1\r
- }\r
- _t._iO.volume = nVol;\r
- if (!bInstanceOnly) {\r
- _t.volume = nVol;\r
- _t.options.volume = nVol;\r
- }\r
- return _t;\r
- };\r
-\r
- this.mute = function() {\r
- _t.muted = true;\r
- if (!_t.isHTML5) {\r
- _s.o._setVolume(_t.sID, 0);\r
- } else if (_t._a) {\r
- _t._a.muted = true;\r
- }\r
- return _t;\r
- };\r
-\r
- this.unmute = function() {\r
- _t.muted = false;\r
- var hasIO = typeof _t._iO.volume !== 'undefined';\r
- if (!_t.isHTML5) {\r
- _s.o._setVolume(_t.sID, hasIO?_t._iO.volume:_t.options.volume);\r
- } else if (_t._a) {\r
- _t._a.muted = false;\r
- }\r
- return _t;\r
- };\r
-\r
- this.toggleMute = function() {\r
- return (_t.muted?_t.unmute():_t.mute());\r
- };\r
-\r
- this.onposition = function(nPosition, oMethod, oScope) {\r
- // TODO: allow for ranges, too? eg. (nPosition instanceof Array)\r
- _t._onPositionItems.push({\r
- position: nPosition,\r
- method: oMethod,\r
- scope: (typeof oScope !== 'undefined'?oScope:_t),\r
- fired: false\r
- });\r
- return _t;\r
- };\r
-\r
- this.processOnPosition = function() {\r
- var i, item, j = _t._onPositionItems.length;\r
- if (!j || !_t.playState || _t._onPositionFired >= j) {\r
- return false;\r
- }\r
- for (i=j; i--;) {\r
- item = _t._onPositionItems[i];\r
- if (!item.fired && _t.position >= item.position) {\r
- item.method.apply(item.scope,[item.position]);\r
- item.fired = true;\r
- _s._onPositionFired++;\r
- }\r
- }\r
- return true;\r
- };\r
-\r
- this.resetOnPosition = function(nPosition) {\r
- // reset "fired" for items interested in this position\r
- var i, item, j = _t._onPositionItems.length;\r
- if (!j) {\r
- return false;\r
- }\r
- for (i=j; i--;) {\r
- item = _t._onPositionItems[i];\r
- if (item.fired && nPosition <= item.position) {\r
- item.fired = false;\r
- _s._onPositionFired--;\r
- }\r
- }\r
- return true;\r
- };\r
-\r
- // pseudo-private soundManager reference\r
-\r
- this._onTimer = function(bForce) {\r
- // HTML5-only _whileplaying() etc.\r
- var time, x = {};\r
- if (_t._hasTimer || bForce) {\r
- if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { // TODO: May not need to track readyState (1 = loading)\r
- _t.duration = _t._get_html5_duration();\r
- _t.durationEstimate = _t.duration;\r
- time = _t._a.currentTime?_t._a.currentTime*1000:0;\r
- _t._whileplaying(time,x,x,x,x);\r
- return true;\r
- } else {\r
- _s._wD('_onTimer: Warn for "'+_t.sID+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK'));\r
- return false;\r
- }\r
- }\r
- };\r
-\r
- // --- private internals ---\r
-\r
- this._get_html5_duration = function() {\r
- var d = (_t._a ? _t._a.duration*1000 : (_t._iO ? _t._iO.duration : undefined));\r
- return (d && !isNaN(d) && d !== Infinity ? d : (_t._iO ? _t._iO.duration : null));\r
- };\r
-\r
- _start_html5_timer = function() {\r
- if (_t.isHTML5) {\r
- _startTimer(_t);\r
- }\r
- };\r
-\r
- _stop_html5_timer = function() {\r
- if (_t.isHTML5) {\r
- _stopTimer(_t);\r
- }\r
- };\r
-\r
- _resetProperties = function(bLoaded) {\r
- _t._onPositionItems = [];\r
- _t._onPositionFired = 0;\r
- _t._hasTimer = null;\r
- _t._onplay_called = false;\r
- _t._a = null;\r
- _t._html5_canplay = false;\r
- _t.bytesLoaded = null;\r
- _t.bytesTotal = null;\r
- _t.position = null;\r
- _t.duration = (_t._iO && _t._iO.duration?_t._iO.duration:null);\r
- _t.durationEstimate = null;\r
- _t.failures = 0;\r
- _t.loaded = false;\r
- _t.playState = 0;\r
- _t.paused = false;\r
- _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success\r
- _t.muted = false;\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- _t.isBuffering = false;\r
- _t.instanceOptions = {};\r
- _t.instanceCount = 0;\r
- _t.peakData = {\r
- left: 0,\r
- right: 0\r
- };\r
- _t.waveformData = {\r
- left: [],\r
- right: []\r
- };\r
- _t.eqData = []; // legacy: 1D array\r
- _t.eqData.left = [];\r
- _t.eqData.right = [];\r
- };\r
-\r
- _resetProperties();\r
-\r
- // pseudo-private methods used by soundManager\r
-\r
- this._setup_html5 = function(oOptions) {\r
- var _iO = _mixin(_t._iO, oOptions), d = decodeURI,\r
- _a = _useGlobalHTML5Audio ? _s._global_a : _t._a,\r
- _dURL = d(_iO.url),\r
- _oldIO = (_a && _a._t ? _a._t.instanceOptions : null);\r
- if (_a) {\r
- if (_a._t && _oldIO.url === _iO.url && (!_t._lastURL || (_t._lastURL === _oldIO.url))) {\r
- return _a; // same url, ignore request\r
- }\r
- _s._wD('setting new URL on existing object: ' + _dURL + (_t._lastURL ? ', old URL: ' + _t._lastURL : ''));\r
- /*\r
- * "First things first, I, Poppa.." (reset the previous state of the old sound, if playing)\r
- * Fixes case with devices that can only play one sound at a time\r
- * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state\r
- */\r
- if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) {\r
- _a._t.stop();\r
- }\r
- _resetProperties(); // new URL, so reset load/playstate and so on\r
- _a.src = _iO.url;\r
- _t.url = _iO.url;\r
- _t._lastURL = _iO.url;\r
- _a._called_load = false;\r
- } else {\r
- _s._wD('creating HTML5 Audio() element with URL: '+_dURL);\r
- _a = new Audio(_iO.url);\r
- _a._called_load = false;\r
- if (_useGlobalHTML5Audio) {\r
- _s._global_a = _a;\r
- }\r
- }\r
- _t.isHTML5 = true;\r
- _t._a = _a; // store a ref on the track\r
- _a._t = _t; // store a ref on the audio\r
- _t._add_html5_events();\r
- _a.loop = (_iO.loops>1?'loop':'');\r
- if (_iO.autoLoad || _iO.autoPlay) {\r
- _a.autobuffer = 'auto'; // early HTML5 implementation (non-standard)\r
- _a.preload = 'auto'; // standard\r
- _t.load();\r
- _a._called_load = true;\r
- } else {\r
- _a.autobuffer = false; // early HTML5 implementation (non-standard)\r
- _a.preload = 'none'; // standard\r
- }\r
- _a.loop = (_iO.loops>1?'loop':''); // boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop\r
- return _a;\r
- };\r
-\r
- // related private methods\r
-\r
- this._add_html5_events = function() {\r
- if (_t._a._added_events) {\r
- return false;\r
- }\r
-\r
- var f;\r
-\r
- function add(oEvt, oFn, bCapture) {\r
- return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null;\r
- }\r
-\r
- _s._wD(_h5+'adding event listeners: '+_t.sID);\r
- _t._a._added_events = true;\r
-\r
- for (f in _s._html5_events) {\r
- if (_s._html5_events.hasOwnProperty(f)) {\r
- add(f, _s._html5_events[f]);\r
- }\r
- }\r
-\r
- return true;\r
- };\r
-\r
- // Keep this externally accessible\r
- this._remove_html5_events = function() {\r
- // Remove event listeners\r
- function remove(oEvt, oFn, bCapture) {\r
- return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null);\r
- }\r
- _s._wD(_h5+'removing event listeners: '+_t.sID);\r
- _t._a._added_events = false;\r
-\r
- for (var f in _s._html5_events) {\r
- if (_s._html5_events.hasOwnProperty(f)) {\r
- remove(f, _s._html5_events[f]);\r
- }\r
- }\r
- };\r
-\r
- // --- "private" methods called by Flash ---\r
-\r
- this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) {\r
- _t.bytesLoaded = nBytesLoaded;\r
- _t.bytesTotal = nBytesTotal;\r
- _t.duration = Math.floor(nDuration);\r
- _t.bufferLength = nBufferLength;\r
- if (!_t._iO.isMovieStar) {\r
- if (_t._iO.duration) {\r
- // use options, if specified and larger\r
- _t.durationEstimate = (_t.duration > _t._iO.duration) ? _t.duration : _t._iO.duration;\r
- } else {\r
- _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10);\r
- }\r
- if (_t.durationEstimate === undefined) {\r
- _t.durationEstimate = _t.duration;\r
- }\r
- if (_t.readyState !== 3 && _t._iO.whileloading) {\r
- _t._iO.whileloading.apply(_t);\r
- }\r
- } else {\r
- _t.durationEstimate = _t.duration;\r
- if (_t.readyState !== 3 && _t._iO.whileloading) {\r
- _t._iO.whileloading.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onid3 = function(oID3PropNames, oID3Data) {\r
- // oID3PropNames: string array (names)\r
- // ID3Data: string array (data)\r
- _s._wD('SMSound._onid3(): "' + this.sID + '" ID3 data received.');\r
- var oData = [], i, j;\r
- for (i = 0, j = oID3PropNames.length; i < j; i++) {\r
- oData[oID3PropNames[i]] = oID3Data[i];\r
- }\r
- _t.id3 = _mixin(_t.id3, oData);\r
- if (_t._iO.onid3) {\r
- _t._iO.onid3.apply(_t);\r
- }\r
- };\r
-\r
- this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {\r
- if (isNaN(nPosition) || nPosition === null) {\r
- return false; // flash safety net\r
- }\r
- if (_t.playState === 0 && nPosition > 0) {\r
- // invalid position edge case for end/stop\r
- nPosition = 0;\r
- }\r
- _t.position = nPosition;\r
- _t.processOnPosition();\r
- if (_fV > 8 && !_t.isHTML5) {\r
- if (_t._iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) {\r
- _t.peakData = {\r
- left: oPeakData.leftPeak,\r
- right: oPeakData.rightPeak\r
- };\r
- }\r
- if (_t._iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) {\r
- _t.waveformData = {\r
- left: oWaveformDataLeft.split(','),\r
- right: oWaveformDataRight.split(',')\r
- };\r
- }\r
- if (_t._iO.useEQData) {\r
- if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) {\r
- var eqLeft = oEQData.leftEQ.split(',');\r
- _t.eqData = eqLeft;\r
- _t.eqData.left = eqLeft;\r
- if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) {\r
- _t.eqData.right = oEQData.rightEQ.split(',');\r
- }\r
- }\r
- }\r
- }\r
- if (_t.playState === 1) {\r
- // special case/hack: ensure buffering is false if loading from cache (and not yet started)\r
- if (!_t.isHTML5 && _s.flashVersion === 8 && !_t.position && _t.isBuffering) {\r
- _t._onbufferchange(0);\r
- }\r
- if (_t._iO.whileplaying) {\r
- _t._iO.whileplaying.apply(_t); // flash may call after actual finish\r
- }\r
- if ((_t.loaded || (!_t.loaded && _t._iO.isMovieStar)) && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration - _t.position <= _t._iO.onbeforefinishtime) {\r
- _t._onbeforefinish();\r
- }\r
- }\r
- return true;\r
- };\r
-\r
- // Only applies to RTMP\r
- this._onconnect = function(bSuccess) {\r
- var fN = 'SMSound._onconnect(): ';\r
- bSuccess = (bSuccess === 1);\r
- _s._wD(fN+'"'+_t.sID+'"'+(bSuccess?' connected.':' failed to connect? - '+_t.url), (bSuccess?1:2));\r
- _t.connected = bSuccess;\r
- if (bSuccess) {\r
- _t.failures = 0;\r
- if (_idCheck(_t.sID)) {\r
- if (_t.getAutoPlay()) {\r
- _t.play(undefined, _t.getAutoPlay()); // only update the play state if auto playing\r
- } else if (_t._iO.autoLoad) {\r
- _t.load();\r
- }\r
- }\r
- if (_t._iO.onconnect) {\r
- _t._iO.onconnect.apply(_t,[bSuccess]);\r
- }\r
- }\r
- };\r
-\r
- this._onload = function(nSuccess) {\r
- var fN = 'SMSound._onload(): ', loadOK = (nSuccess?true:false);\r
- _s._wD(fN + '"' + _t.sID + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2));\r
- // <d>\r
- if (!loadOK && !_t.isHTML5) {\r
- if (_s.sandbox.noRemote === true) {\r
- _s._wD(fN + _str('noNet'), 1);\r
- }\r
- if (_s.sandbox.noLocal === true) {\r
- _s._wD(fN + _str('noLocal'), 1);\r
- }\r
- }\r
- // </d>\r
- _t.loaded = loadOK;\r
- _t.readyState = loadOK?3:2;\r
- _t._onbufferchange(0);\r
- if (_t._iO.onload) {\r
- _t._iO.onload.apply(_t, [loadOK]);\r
- }\r
- return true;\r
- };\r
-\r
- // fire onfailure() only once at most\r
- // at this point we just recreate failed sounds rather than trying to reconnect.\r
- this._onfailure = function(msg, level, code) {\r
- _t.failures++;\r
- _s._wD('SMSound._onfailure(): "'+_t.sID+'" count '+_t.failures);\r
- if (_t._iO.onfailure && _t.failures === 1) {\r
- _t._iO.onfailure(_t, msg, level, code);\r
- } else {\r
- _s._wD('SMSound._onfailure(): ignoring');\r
- }\r
- };\r
-\r
- this._onbeforefinish = function() {\r
- if (!_t.didBeforeFinish) {\r
- _t.didBeforeFinish = true;\r
- if (_t._iO.onbeforefinish) {\r
- _s._wD('SMSound._onbeforefinish(): "' + _t.sID + '"');\r
- _t._iO.onbeforefinish.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onjustbeforefinish = function(msOffset) {\r
- if (!_t.didJustBeforeFinish) {\r
- _t.didJustBeforeFinish = true;\r
- if (_t._iO.onjustbeforefinish) {\r
- _s._wD('SMSound._onjustbeforefinish(): "' + _t.sID + '"');\r
- _t._iO.onjustbeforefinish.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onfinish = function() {\r
- // _s._wD('SMSound._onfinish(): "' + _t.sID + '" got instanceCount '+_t.instanceCount);\r
- var _io_onfinish = _t._iO.onfinish; // store local copy before it gets trashed..\r
- _t._onbufferchange(0);\r
- _t.resetOnPosition(0);\r
- if (_t._iO.onbeforefinishcomplete) {\r
- _t._iO.onbeforefinishcomplete.apply(_t);\r
- }\r
- // reset some state items\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- if (_t.instanceCount) {\r
- _t.instanceCount--;\r
- if (!_t.instanceCount) {\r
- // reset instance options\r
- _t.playState = 0;\r
- _t.paused = false;\r
- _t.instanceCount = 0;\r
- _t.instanceOptions = {};\r
- _t._iO = {};\r
- _stop_html5_timer();\r
- }\r
- if (!_t.instanceCount || _t._iO.multiShotEvents) {\r
- // fire onfinish for last, or every instance\r
- if (_io_onfinish) {\r
- _s._wD('SMSound._onfinish(): "' + _t.sID + '"');\r
- _io_onfinish.apply(_t);\r
- }\r
- }\r
- }\r
- };\r
-\r
- this._onbufferchange = function(nIsBuffering) {\r
- var fN = 'SMSound._onbufferchange()';\r
- if (_t.playState === 0) {\r
- // ignore if not playing\r
- return false;\r
- }\r
- if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) {\r
- return false;\r
- }\r
- _t.isBuffering = (nIsBuffering === 1);\r
- if (_t._iO.onbufferchange) {\r
- _s._wD(fN + ': ' + nIsBuffering);\r
- _t._iO.onbufferchange.apply(_t);\r
- }\r
- return true;\r
- };\r
-\r
- this._ondataerror = function(sError) {\r
- // flash 9 wave/eq data handler\r
- if (_t.playState > 0) { // hack: called at start, and end from flash at/after onfinish()\r
- _s._wD('SMSound._ondataerror(): ' + sError);\r
- if (_t._iO.ondataerror) {\r
- _t._iO.ondataerror.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- }; // SMSound()\r
-\r
- // --- private SM2 internals ---\r
-\r
- _getDocument = function() {\r
- return (_doc.body?_doc.body:(_doc._docElement?_doc.documentElement:_doc.getElementsByTagName('div')[0]));\r
- };\r
-\r
- _id = function(sID) {\r
- return _doc.getElementById(sID);\r
- };\r
-\r
- _mixin = function(oMain, oAdd) {\r
- // non-destructive merge\r
- var o1 = {}, i, o2, o;\r
- for (i in oMain) { // clone c1\r
- if (oMain.hasOwnProperty(i)) {\r
- o1[i] = oMain[i];\r
- }\r
- }\r
- o2 = (typeof oAdd === 'undefined'?_s.defaultOptions:oAdd);\r
- for (o in o2) {\r
- if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') {\r
- o1[o] = o2[o];\r
- }\r
- }\r
- return o1;\r
- };\r
-\r
- _event = (function() {\r
-\r
- var old = (_win.attachEvent),\r
- evt = {\r
- add: (old?'attachEvent':'addEventListener'),\r
- remove: (old?'detachEvent':'removeEventListener')\r
- };\r
-\r
- function getArgs(oArgs) {\r
- var args = _slice.call(oArgs), len = args.length;\r
- if (old) {\r
- args[1] = 'on' + args[1]; // prefix\r
- if (len > 3) {\r
- args.pop(); // no capture\r
- }\r
- } else if (len === 3) {\r
- args.push(false);\r
- }\r
- return args;\r
- }\r
-\r
- function apply(args, sType) {\r
- var element = args.shift(),\r
- method = [evt[sType]];\r
- if (old) {\r
- element[method](args[0], args[1]);\r
- } else {\r
- element[method].apply(element, args);\r
- }\r
- }\r
-\r
- function add() {\r
- apply(getArgs(arguments), 'add');\r
- }\r
-\r
- function remove() {\r
- apply(getArgs(arguments), 'remove');\r
- }\r
-\r
- return {\r
- 'add': add,\r
- 'remove': remove\r
- };\r
-\r
- }());\r
-\r
- _html5OK = function(iO) {\r
- return (!iO.serverURL && (iO.type?_html5CanPlay({type:iO.type}):_html5CanPlay(iO.url)||_html5Only)); // Use type, if specified. If HTML5-only mode, no other options, so just give 'er\r
- };\r
-\r
- _html5CanPlay = function(sURL) {\r
- // try to find MIME, test and return truthiness\r
- if (!_s.useHTML5Audio || !_s.hasHTML5) {\r
- return false;\r
- }\r
- var result, mime, offset, fileExt, item, aF = _s.audioFormats;\r
- if (!_html5Ext) {\r
- _html5Ext = [];\r
- for (item in aF) {\r
- if (aF.hasOwnProperty(item)) {\r
- _html5Ext.push(item);\r
- if (aF[item].related) {\r
- _html5Ext = _html5Ext.concat(aF[item].related);\r
- }\r
- }\r
- }\r
- _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')','i');\r
- }\r
- mime = (typeof sURL.type !== 'undefined'?sURL.type:null);\r
- fileExt = (typeof sURL === 'string'?sURL.toLowerCase().match(_html5Ext):null); // TODO: Strip URL queries, etc.\r
- if (!fileExt || !fileExt.length) {\r
- if (!mime) {\r
- return false;\r
- } else {\r
- // audio/mp3 -> mp3, result should be known\r
- offset = mime.indexOf(';');\r
- fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); // strip "audio/X; codecs.."\r
- }\r
- } else {\r
- fileExt = fileExt[0].substr(1); // "mp3", for example\r
- }\r
- if (fileExt && typeof _s.html5[fileExt] !== 'undefined') {\r
- // result known\r
- return _s.html5[fileExt];\r
- } else {\r
- if (!mime) {\r
- if (fileExt && _s.html5[fileExt]) {\r
- return _s.html5[fileExt];\r
- } else {\r
- // best-case guess, audio/whatever-dot-filename-format-you're-playing\r
- mime = 'audio/'+fileExt;\r
- }\r
- }\r
- result = _s.html5.canPlayType(mime);\r
- _s.html5[fileExt] = result;\r
- // _s._wD('canPlayType, found result: '+result);\r
- return result;\r
- }\r
- };\r
-\r
- _testHTML5 = function() {\r
- if (!_s.useHTML5Audio || typeof Audio === 'undefined') {\r
- return false;\r
- }\r
- // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/\r
- var a = (typeof Audio !== 'undefined' ? (_isOpera ? new Audio(null) : new Audio()) : null), item, support = {}, aF, i, _hasFlash = _detectFlash();\r
- function _cp(m) {\r
- var canPlay, i, j, isOK = false;\r
- if (!a || typeof a.canPlayType !== 'function') {\r
- return false;\r
- }\r
- if (m instanceof Array) {\r
- // iterate through all mime types, return any successes\r
- for (i=0, j=m.length; i<j && !isOK; i++) {\r
- if (_s.html5[m[i]] || a.canPlayType(m[i]).match(_s.html5Test)) {\r
- isOK = true;\r
- _s.html5[m[i]] = true;\r
- }\r
- }\r
- return isOK;\r
- } else {\r
- canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);\r
- return (canPlay && (canPlay.match(_s.html5Test)?true:false));\r
- }\r
- }\r
- // test all registered formats + codecs\r
- aF = _s.audioFormats;\r
- for (item in aF) {\r
- if (aF.hasOwnProperty(item)) {\r
- support[item] = _cp(aF[item].type);\r
- // assign result to related formats, too\r
- if (aF[item] && aF[item].related) {\r
- for (i=aF[item].related.length; i--;) {\r
- _s.html5[aF[item].related[i]] = support[item];\r
- }\r
- }\r
- }\r
- }\r
- support.canPlayType = (a?_cp:null);\r
- _s.html5 = _mixin(_s.html5, support);\r
- return true;\r
- };\r
-\r
- _strings = {\r
- // <d>\r
- notReady: 'Not loaded yet - wait for soundManager.onload()/onready()',\r
- notOK: 'Audio support is not available.',\r
- appXHTML: _smc + 'createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.',\r
- spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)',\r
- swf404: _sm + ': Verify that %s is a valid path.',\r
- tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)',\r
- checkSWF: 'See SWF output for more debug info.',\r
- localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/',\r
- waitFocus: _sm + ': Special case: Waiting for focus-related event..',\r
- waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...',\r
- waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...',\r
- needFunction: _sm + ': Function object expected for %s',\r
- badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',\r
- noMS: 'MovieStar mode not enabled. Exiting.',\r
- currentObj: '--- ' + _sm + '._debug(): Current sound objects ---',\r
- waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash..',\r
- waitOnload: _sm + ': Waiting for window.onload()',\r
- docLoaded: _sm + ': Document already loaded',\r
- onload: _smc + 'initComplete(): calling soundManager.onload()',\r
- onloadOK: _sm + '.onload() complete',\r
- init: '-- ' + _smc + 'init() --',\r
- didInit: _smc + 'init(): Already called?',\r
- flashJS: _sm + ': Attempting to call Flash from JS..',\r
- noPolling: _sm + ': Polling (whileloading()/whileplaying() support) is disabled.',\r
- secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html',\r
- badRemove: 'Warning: Failed to remove flash movie.',\r
- noPeak: 'Warning: peakData features unsupported for movieStar formats',\r
- shutdown: _sm + '.disable(): Shutting down',\r
- queue: _sm + ': Queueing %s handler',\r
- smFail: _sm + ': Failed to initialise.',\r
- smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',\r
- fbTimeout: 'No flash response, applying .'+_s.swfCSS.swfTimedout+' CSS..',\r
- fbLoaded: 'Flash loaded',\r
- fbHandler: _smc+'flashBlockHandler()',\r
- manURL: 'SMSound.load(): Using manually-assigned URL',\r
- onURL: _sm + '.load(): current URL already assigned.',\r
- badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',\r
- as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)',\r
- noNSLoop: 'Note: Looping not implemented for MovieStar formats',\r
- needfl9: 'Note: Switching to flash 9, required for MP4 formats.',\r
- mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case',\r
- mfOn: 'mobileFlash::enabling on-screen flash repositioning',\r
- policy: 'Enabling usePolicyFile for data access'\r
- // </d>\r
- };\r
-\r
- _str = function() { // o [,items to replace]\r
- // <d>\r
- var args = _slice.call(arguments), // real array, please\r
- o = args.shift(), // first arg\r
- str = (_strings && _strings[o]?_strings[o]:''), i, j;\r
- if (str && args && args.length) {\r
- for (i = 0, j = args.length; i < j; i++) {\r
- str = str.replace('%s', args[i]);\r
- }\r
- }\r
- return str;\r
- // </d>\r
- };\r
-\r
- _loopFix = function(sOpt) {\r
- // flash 8 requires stream = false for looping to work\r
- if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) {\r
- _wDS('as2loop');\r
- sOpt.stream = false;\r
- }\r
- return sOpt;\r
- };\r
-\r
- _policyFix = function(sOpt, sPre) {\r
- if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) {\r
- _s._wD((sPre?sPre+':':'') + _str('policy'));\r
- sOpt.usePolicyFile = true;\r
- }\r
- return sOpt;\r
- };\r
-\r
- _complain = function(sMsg) {\r
- if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') {\r
- console.warn(sMsg);\r
- } else {\r
- _s._wD(sMsg);\r
- }\r
- };\r
-\r
- _doNothing = function() {\r
- return false;\r
- };\r
-\r
- _disableObject = function(o) {\r
- for (var oProp in o) {\r
- if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') {\r
- o[oProp] = _doNothing;\r
- }\r
- }\r
- oProp = null;\r
- };\r
-\r
- _failSafely = function(bNoDisable) {\r
- // general failure exception handler\r
- if (typeof bNoDisable === 'undefined') {\r
- bNoDisable = false;\r
- }\r
- if (_disabled || bNoDisable) {\r
- _wDS('smFail', 2);\r
- _s.disable(bNoDisable);\r
- }\r
- };\r
-\r
- _normalizeMovieURL = function(smURL) {\r
- var urlParams = null;\r
- if (smURL) {\r
- if (smURL.match(/\.swf(\?.*)?$/i)) {\r
- urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);\r
- if (urlParams) {\r
- return smURL; // assume user knows what they're doing\r
- }\r
- } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {\r
- smURL = smURL + '/';\r
- }\r
- }\r
- return (smURL && smURL.lastIndexOf('/') !== - 1?smURL.substr(0, smURL.lastIndexOf('/') + 1):'./') + _s.movieURL;\r
- };\r
-\r
- _setVersionInfo = function() {\r
- if (_fV !== 8 && _fV !== 9) {\r
- _s._wD(_str('badFV', _fV, _defaultFlashVersion));\r
- _s.flashVersion = _defaultFlashVersion;\r
- }\r
- var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); // debug flash movie, if applicable\r
- if (_s.useHTML5Audio && !_html5Only && _s.audioFormats.mp4.required && _s.flashVersion < 9) {\r
- _s._wD(_str('needfl9'));\r
- _s.flashVersion = 9;\r
- }\r
- _fV = _s.flashVersion; // short-hand for internal use\r
- _s.version = _s.versionNumber + (_html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)'));\r
- // set up default options\r
- if (_fV > 8) {\r
- _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options);\r
- _s.features.buffering = true;\r
- }\r
- if (_fV > 8 && _s.useMovieStar) {\r
- // flash 9+ support for movieStar formats as well as MP3\r
- _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions);\r
- _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _s.netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
- _s.mimePattern = _s.netStreamMimeTypes;\r
- _s.features.movieStar = true;\r
- } else {\r
- _s.useMovieStar = false;\r
- _s.features.movieStar = false;\r
- }\r
- _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')];\r
- _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf',isDebug);\r
- _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8);\r
- };\r
-\r
- _setPolling = function(bPolling, bHighPerformance) {\r
- if (!_s.o || !_s.allowPolling) {\r
- return false;\r
- }\r
- _s.o._setPolling(bPolling, bHighPerformance);\r
- };\r
-\r
- function _initDebug() {\r
- if (_s.debugURLParam.test(_wl)) {\r
- _s.debugMode = true; // allow force of debug mode via URL\r
- }\r
- // <d>\r
- if (_id(_s.debugID)) {\r
- return false;\r
- }\r
- var oD, oDebug, oTarget, oToggle, tmp;\r
- if (_s.debugMode && !_id(_s.debugID) && ((!_hasConsole || !_s.useConsole) || (_s.useConsole && _hasConsole && !_s.consoleOnly))) {\r
- oD = _doc.createElement('div');\r
- oD.id = _s.debugID + '-toggle';\r
- oToggle = {\r
- 'position': 'fixed',\r
- 'bottom': '0px',\r
- 'right': '0px',\r
- 'width': '1.2em',\r
- 'height': '1.2em',\r
- 'lineHeight': '1.2em',\r
- 'margin': '2px',\r
- 'textAlign': 'center',\r
- 'border': '1px solid #999',\r
- 'cursor': 'pointer',\r
- 'background': '#fff',\r
- 'color': '#333',\r
- 'zIndex': 10001\r
- };\r
- oD.appendChild(_doc.createTextNode('-'));\r
- oD.onclick = _toggleDebug;\r
- oD.title = 'Toggle SM2 debug console';\r
- if (_ua.match(/msie 6/i)) {\r
- oD.style.position = 'absolute';\r
- oD.style.cursor = 'hand';\r
- }\r
- for (tmp in oToggle) {\r
- if (oToggle.hasOwnProperty(tmp)) {\r
- oD.style[tmp] = oToggle[tmp];\r
- }\r
- }\r
- oDebug = _doc.createElement('div');\r
- oDebug.id = _s.debugID;\r
- oDebug.style.display = (_s.debugMode?'block':'none');\r
- if (_s.debugMode && !_id(oD.id)) {\r
- try {\r
- oTarget = _getDocument();\r
- oTarget.appendChild(oD);\r
- } catch(e2) {\r
- throw new Error(_str('appXHTML'));\r
- }\r
- oTarget.appendChild(oDebug);\r
- }\r
- }\r
- oTarget = null;\r
- // </d>\r
- }\r
-\r
- _createMovie = function(smID, smURL) {\r
-\r
- var specialCase = null,\r
- remoteURL = (smURL?smURL:_s.url),\r
- localURL = (_s.altURL?_s.altURL:remoteURL),\r
- oEmbed, oMovie, oTarget = _getDocument(), tmp, movieHTML, oEl, extraClass = _getSWFCSS(), s, x, sClass, side = '100%', isRTL = null, html = _doc.getElementsByTagName('html')[0];\r
- isRTL = (html && html.dir && html.dir.match(/rtl/i));\r
- smID = (typeof smID === 'undefined'?_s.id:smID);\r
-\r
- if (_didAppend && _appendSuccess) {\r
- return false; // ignore if already succeeded\r
- }\r
-\r
- function _initMsg() {\r
- _s._wD('-- SoundManager 2 ' + _s.version + (!_html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_html5Only ? (_s.useMovieStar?', MovieStar mode':'') + (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : (_s.useFastPolling?'fast':'normal')) + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1);\r
- }\r
-\r
- if (_html5Only) {\r
- _setVersionInfo();\r
- _initMsg();\r
- _s.oMC = _id(_s.movieID);\r
- _init();\r
- // prevent multiple init attempts\r
- _didAppend = true;\r
- _appendSuccess = true;\r
- return false;\r
- }\r
-\r
- _didAppend = true;\r
-\r
- // safety check for legacy (change to Flash 9 URL)\r
- _setVersionInfo();\r
- _s.url = _normalizeMovieURL(_s._overHTTP?remoteURL:localURL);\r
- smURL = _s.url;\r
-\r
- _s.wmode = (!_s.wmode && _s.useHighPerformance && !_s.useMovieStar?'transparent':_s.wmode);\r
-\r
- if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) {\r
- _s.specialWmodeCase = true;\r
- // extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here\r
- // does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout\r
- // wmode breaks IE 8 on Vista + Win7 too in some cases, as of Jan.2011 (?)\r
- _wDS('spcWmode');\r
- _s.wmode = null;\r
- }\r
-\r
- oEmbed = {\r
- 'name': smID,\r
- 'id': smID,\r
- 'src': smURL,\r
- 'width': side,\r
- 'height': side,\r
- 'quality': 'high',\r
- 'allowScriptAccess': _s.allowScriptAccess,\r
- 'bgcolor': _s.bgColor,\r
- 'pluginspage': _s._http+'//www.macromedia.com/go/getflashplayer',\r
- 'type': 'application/x-shockwave-flash',\r
- 'wmode': _s.wmode,\r
- 'hasPriority': 'true' // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html\r
- };\r
-\r
- if (_s.debugFlash) {\r
- oEmbed.FlashVars = 'debug=1';\r
- }\r
-\r
- if (!_s.wmode) {\r
- delete oEmbed.wmode; // don't write empty attribute\r
- }\r
-\r
- if (_isIE) {\r
- // IE is "special".\r
- oMovie = _doc.createElement('div');\r
- movieHTML = '<object id="' + smID + '" data="' + smURL + '" type="' + oEmbed.type + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+_s._http+'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="' + oEmbed.width + '" height="' + oEmbed.height + '"><param name="movie" value="' + smURL + '" /><param name="AllowScriptAccess" value="' + _s.allowScriptAccess + '" /><param name="quality" value="' + oEmbed.quality + '" />' + (_s.wmode?'<param name="wmode" value="' + _s.wmode + '" /> ':'') + '<param name="bgcolor" value="' + _s.bgColor + '" />' + (_s.debugFlash?'<param name="FlashVars" value="' + oEmbed.FlashVars + '" />':'') + '</object>';\r
- } else {\r
- oMovie = _doc.createElement('embed');\r
- for (tmp in oEmbed) {\r
- if (oEmbed.hasOwnProperty(tmp)) {\r
- oMovie.setAttribute(tmp, oEmbed[tmp]);\r
- }\r
- }\r
- }\r
-\r
- _initDebug();\r
- extraClass = _getSWFCSS();\r
- oTarget = _getDocument();\r
-\r
- if (oTarget) {\r
- _s.oMC = _id(_s.movieID)?_id(_s.movieID):_doc.createElement('div');\r
- if (!_s.oMC.id) {\r
- _s.oMC.id = _s.movieID;\r
- _s.oMC.className = _s.swfCSS.swfDefault + ' ' + extraClass;\r
- // "hide" flash movie\r
- s = null;\r
- oEl = null;\r
- if (!_s.useFlashBlock) {\r
- if (_s.useHighPerformance) {\r
- s = {\r
- 'position': 'fixed',\r
- 'width': '8px',\r
- 'height': '8px',\r
- // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.\r
- 'bottom': '0px',\r
- 'left': '0px',\r
- 'overflow': 'hidden'\r
- };\r
- } else {\r
- s = {\r
- 'position': 'absolute',\r
- 'width': '6px',\r
- 'height': '6px',\r
- 'top': '-9999px',\r
- 'left': '-9999px'\r
- };\r
- if (isRTL) {\r
- s.left = Math.abs(parseInt(s.left,10))+'px';\r
- }\r
- }\r
- }\r
- if (_isWebkit) {\r
- _s.oMC.style.zIndex = 10000; // soundcloud-reported render/crash fix, safari 5\r
- }\r
- if (!_s.debugFlash) {\r
- for (x in s) {\r
- if (s.hasOwnProperty(x)) {\r
- _s.oMC.style[x] = s[x];\r
- }\r
- }\r
- }\r
- try {\r
- if (!_isIE) {\r
- _s.oMC.appendChild(oMovie);\r
- }\r
- oTarget.appendChild(_s.oMC);\r
- if (_isIE) {\r
- oEl = _s.oMC.appendChild(_doc.createElement('div'));\r
- oEl.className = _s.swfCSS.swfBox;\r
- oEl.innerHTML = movieHTML;\r
- }\r
- _appendSuccess = true;\r
- } catch(e) {\r
- throw new Error(_str('appXHTML'));\r
- }\r
- } else {\r
- // it's already in the document.\r
- sClass = _s.oMC.className;\r
- _s.oMC.className = (sClass?sClass+' ':_s.swfCSS.swfDefault) + (extraClass?' '+extraClass:'');\r
- _s.oMC.appendChild(oMovie);\r
- if (_isIE) {\r
- oEl = _s.oMC.appendChild(_doc.createElement('div'));\r
- oEl.className = _s.swfCSS.swfBox;\r
- oEl.innerHTML = movieHTML;\r
- }\r
- _appendSuccess = true;\r
- }\r
- }\r
-\r
- if (specialCase) {\r
- _s._wD(specialCase);\r
- }\r
-\r
- _initMsg();\r
- _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_s._overHTTP && _s.altURL?' (alternate URL)':''), 1);\r
-\r
- return true;\r
- };\r
-\r
- _idCheck = this.getSoundById;\r
-\r
- _initMovie = function() {\r
- if (_html5Only) {\r
- _createMovie();\r
- return false;\r
- }\r
- // attempt to get, or create, movie\r
- if (_s.o) {\r
- return false; // may already exist\r
- }\r
- _s.o = _s.getMovie(_s.id); // inline markup\r
- if (!_s.o) {\r
- if (!_oRemoved) {\r
- // try to create\r
- _createMovie(_s.id, _s.url);\r
- } else {\r
- // try to re-append removed movie after reboot()\r
- if (!_isIE) {\r
- _s.oMC.appendChild(_oRemoved);\r
- } else {\r
- _s.oMC.innerHTML = _oRemovedHTML;\r
- }\r
- _oRemoved = null;\r
- _didAppend = true;\r
- }\r
- _s.o = _s.getMovie(_s.id);\r
- }\r
- if (_s.o) {\r
- _s._wD(_smc+'initMovie(): Got '+_s.o.nodeName+' element ('+(_didAppend?'created via JS':'static HTML')+')');\r
- _wDS('waitEI');\r
- }\r
- if (_s.oninitmovie instanceof Function) {\r
- setTimeout(_s.oninitmovie, 1);\r
- }\r
- return true;\r
- };\r
-\r
- _go = function(sURL) {\r
- // where it all begins.\r
- if (sURL) {\r
- _s.url = sURL;\r
- }\r
- _initMovie();\r
- };\r
-\r
- _delayWaitForEI = function() {\r
- setTimeout(_waitForEI, 500);\r
- };\r
-\r
- _waitForEI = function() {\r
- if (_waitingForEI) {\r
- return false;\r
- }\r
- _waitingForEI = true;\r
- _event.remove(_win, 'load', _delayWaitForEI);\r
- if (_tryInitOnFocus && !_isFocused) {\r
- _wDS('waitFocus');\r
- return false;\r
- }\r
- var p;\r
- if (!_didInit) {\r
- p = _s.getMoviePercent();\r
- _s._wD(_str('waitImpatient', (p === 100?' (SWF loaded)':(p > 0?' (SWF ' + p + '% loaded)':''))));\r
- }\r
- setTimeout(function() {\r
- p = _s.getMoviePercent();\r
- if (!_didInit) {\r
- _s._wD(_sm + ': No Flash response within expected time.\nLikely causes: ' + (p === 0?'Loading ' + _s.movieURL + ' may have failed (and/or Flash ' + _fV + '+ not present?), ':'') + 'Flash blocked or JS-Flash security error.' + (_s.debugFlash?' ' + _str('checkSWF'):''), 2);\r
- if (!_s._overHTTP && p) {\r
- _wDS('localFail', 2);\r
- if (!_s.debugFlash) {\r
- _wDS('tryDebug', 2);\r
- }\r
- }\r
- if (p === 0) {\r
- // if 0 (not null), probably a 404.\r
- _s._wD(_str('swf404', _s.url));\r
- }\r
- _debugTS('flashtojs', false, ': Timed out' + _s._overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)');\r
- }\r
- // give up / time-out, depending\r
- if (!_didInit && _okToDisable) {\r
- if (p === null) {\r
- // SWF failed. Maybe blocked.\r
- if (_s.useFlashBlock || _s.flashLoadTimeout === 0) {\r
- if (_s.useFlashBlock) {\r
- _flashBlockHandler();\r
- }\r
- _wDS('waitForever');\r
- } else {\r
- // old SM2 behaviour, simply fail\r
- _failSafely(true);\r
- }\r
- } else {\r
- // flash loaded? Shouldn't be a blocking issue, then.\r
- if (_s.flashLoadTimeout === 0) {\r
- _wDS('waitForever');\r
- } else {\r
- _failSafely(true);\r
- }\r
- }\r
- }\r
- }, _s.flashLoadTimeout);\r
- };\r
-\r
- _go = function(sURL) {\r
- // where it all begins.\r
- if (sURL) {\r
- _s.url = sURL;\r
- }\r
- _initMovie();\r
- };\r
-\r
- // <d>\r
- _wDS = function(o, errorLevel) {\r
- if (!o) {\r
- return '';\r
- } else {\r
- return _s._wD(_str(o), errorLevel);\r
- }\r
- };\r
-\r
- if (_wl.indexOf('debug=alert') + 1 && _s.debugMode) {\r
- _s._wD = function(sText) {window.alert(sText);};\r
- }\r
-\r
- _toggleDebug = function() {\r
- var o = _id(_s.debugID),\r
- oT = _id(_s.debugID + '-toggle');\r
- if (!o) {\r
- return false;\r
- }\r
- if (_debugOpen) {\r
- // minimize\r
- oT.innerHTML = '+';\r
- o.style.display = 'none';\r
- } else {\r
- oT.innerHTML = '-';\r
- o.style.display = 'block';\r
- }\r
- _debugOpen = !_debugOpen;\r
- };\r
-\r
- _debugTS = function(sEventType, bSuccess, sMessage) {\r
- // troubleshooter debug hooks\r
- if (typeof sm2Debugger !== 'undefined') {\r
- try {\r
- sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);\r
- } catch(e) {\r
- // oh well\r
- }\r
- }\r
- return true;\r
- };\r
- // </d>\r
-\r
- _getSWFCSS = function() {\r
- var css = [];\r
- if (_s.debugMode) {\r
- css.push(_s.swfCSS.sm2Debug);\r
- }\r
- if (_s.debugFlash) {\r
- css.push(_s.swfCSS.flashDebug);\r
- }\r
- if (_s.useHighPerformance) {\r
- css.push(_s.swfCSS.highPerf);\r
- }\r
- return css.join(' ');\r
- };\r
-\r
- _flashBlockHandler = function() {\r
- // *possible* flash block situation.\r
- var name = _str('fbHandler'), p = _s.getMoviePercent(), css = _s.swfCSS;\r
- if (!_s.ok()) {\r
- if (_needsFlash) {\r
- // make the movie more visible, so user can fix\r
- _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError);\r
- _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':''));\r
- }\r
- _s.didFlashBlock = true;\r
- _processOnEvents({type:'ontimeout',ignoreInit:true}); // fire onready(), complain lightly\r
- if (_s.onerror instanceof Function) {\r
- _s.onerror.apply(_win);\r
- }\r
- } else {\r
- // SM2 loaded OK (or recovered)\r
- if (_s.didFlashBlock) {\r
- _s._wD(name+': Unblocked');\r
- }\r
- if (_s.oMC) {\r
- _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' ');\r
- }\r
- }\r
- };\r
-\r
- _handleFocus = function() {\r
- function cleanup() {\r
- _event.remove(_win, 'focus', _handleFocus);\r
- _event.remove(_win, 'load', _handleFocus);\r
- }\r
- if (_isFocused || !_tryInitOnFocus) {\r
- cleanup();\r
- return true;\r
- }\r
- _okToDisable = true;\r
- _isFocused = true;\r
- _s._wD(_smc+'handleFocus()');\r
- if (_isSafari && _tryInitOnFocus) {\r
- // giant Safari 3.1 hack - assume mousemove = focus given lack of focus event\r
- _event.remove(_win, 'mousemove', _handleFocus);\r
- }\r
- // allow init to restart\r
- _waitingForEI = false;\r
- cleanup();\r
- return true;\r
- };\r
-\r
- _initComplete = function(bNoDisable) {\r
- if (_didInit) {\r
- return false;\r
- }\r
- if (_html5Only) {\r
- // all good.\r
- _s._wD('-- SoundManager 2: loaded --');\r
- _didInit = true;\r
- _processOnEvents();\r
- _initUserOnload();\r
- return true;\r
- }\r
- var sClass = _s.oMC.className,\r
- wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent());\r
- if (!wasTimeout) {\r
- _didInit = true;\r
- }\r
- _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'security/load error':'OK') + ') --', 1);\r
- if (_disabled || bNoDisable) {\r
- if (_s.useFlashBlock) {\r
- _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_s.swfCSS.swfTimedout:_s.swfCSS.swfError);\r
- }\r
- _processOnEvents({type:'ontimeout'});\r
- _debugTS('onload', false);\r
- if (_s.onerror instanceof Function) {\r
- _s.onerror.apply(_win);\r
- }\r
- return false;\r
- } else {\r
- _debugTS('onload', true);\r
- }\r
- _event.add(_win, 'unload', _doNothing); // prevent browser from showing cached state via back button, because flash will be dead\r
- if (_s.waitForWindowLoad && !_windowLoaded) {\r
- _wDS('waitOnload');\r
- _event.add(_win, 'load', _initUserOnload);\r
- return false;\r
- } else {\r
- if (_s.waitForWindowLoad && _windowLoaded) {\r
- _wDS('docLoaded');\r
- }\r
- _initUserOnload();\r
- }\r
- return true;\r
- };\r
-\r
- _addOnEvent = function(sType, oMethod, oScope) {\r
- if (typeof _on_queue[sType] === 'undefined') {\r
- _on_queue[sType] = [];\r
- }\r
- _on_queue[sType].push({\r
- 'method': oMethod,\r
- 'scope': (oScope || null),\r
- 'fired': false\r
- });\r
- };\r
-\r
- _processOnEvents = function(oOptions) {\r
- if (!oOptions) { // assume onready, if unspecified\r
- oOptions = {\r
- type: 'onready'\r
- };\r
- }\r
- if (!_didInit && oOptions && !oOptions.ignoreInit) {\r
- // not ready yet.\r
- return false;\r
- }\r
- var status = {\r
- success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled)\r
- },\r
- srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), // queue specified by type, or none\r
- queue = [], i, j,\r
- canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok());\r
- for (i = 0; i < srcQueue.length; i++) {\r
- if (srcQueue[i].fired !== true) {\r
- queue.push(srcQueue[i]);\r
- }\r
- }\r
- if (queue.length) {\r
- _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s'));\r
- for (i = 0, j = queue.length; i < j; i++) {\r
- if (queue[i].scope) {\r
- queue[i].method.apply(queue[i].scope, [status]);\r
- } else {\r
- queue[i].method(status);\r
- }\r
- if (!canRetry) { // flashblock case doesn't count here\r
- queue[i].fired = true;\r
- }\r
- }\r
- }\r
- return true;\r
- };\r
-\r
- _initUserOnload = function() {\r
- _win.setTimeout(function() {\r
- if (_s.useFlashBlock) {\r
- _flashBlockHandler();\r
- }\r
- _processOnEvents();\r
- // call user-defined "onload", scoped to window\r
- if (_s.onload instanceof Function) {\r
- _wDS('onload', 1);\r
- _s.onload.apply(_win);\r
- _wDS('onloadOK', 1);\r
- }\r
- if (_s.waitForWindowLoad) {\r
- _event.add(_win, 'load', _initUserOnload);\r
- }\r
- },1);\r
- };\r
-\r
- _detectFlash = function() {\r
-\r
- // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt\r
-\r
- if (_hasFlash !== undefined) {\r
- // this work has already been done.\r
- return _hasFlash;\r
- }\r
-\r
- var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject;\r
-\r
- if (nP && nP.length) {\r
-\r
- type = 'application/x-shockwave-flash';\r
- types = n.mimeTypes;\r
- if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
- hasPlugin = true;\r
- }\r
-\r
- } else if (typeof AX !== 'undefined') {\r
-\r
- try {\r
- obj = new AX('ShockwaveFlash.ShockwaveFlash');\r
- } catch(e) {\r
- // oh well\r
- }\r
- hasPlugin = (!!obj);\r
-\r
- }\r
-\r
- _hasFlash = hasPlugin;\r
-\r
- return hasPlugin;\r
-\r
- };\r
-\r
- _featureCheck = function() {\r
- var needsFlash, item,\r
- isSpecial = (_ua.match(/iphone os (1|2|3_0|3_1)/i)?true:false); // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (iPad) + iOS4 works.\r
- if (isSpecial) {\r
- _s.hasHTML5 = false; // has Audio(), but is broken; let it load links directly.\r
- _html5Only = true; // ignore flash case, however\r
- if (_s.oMC) {\r
- _s.oMC.style.display = 'none';\r
- }\r
- return false;\r
- }\r
- if (_s.useHTML5Audio) {\r
- if (!_s.html5 || !_s.html5.canPlayType) {\r
- _s._wD('SoundManager: No HTML5 Audio() support detected.');\r
- _s.hasHTML5 = false;\r
- return true;\r
- } else {\r
- _s.hasHTML5 = true;\r
- }\r
- if (_isBadSafari) {\r
- _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1);\r
- if (_detectFlash()) {\r
- return true;\r
- }\r
- }\r
- } else {\r
- // flash required.\r
- return true;\r
- }\r
- for (item in _s.audioFormats) {\r
- if (_s.audioFormats.hasOwnProperty(item) && _s.audioFormats[item].required && !_s.html5.canPlayType(_s.audioFormats[item].type)) {\r
- // may need flash for this format?\r
- needsFlash = true;\r
- }\r
- }\r
- // sanity check..\r
- if (_s.ignoreFlash) {\r
- needsFlash = false;\r
- }\r
- _html5Only = (_s.useHTML5Audio && _s.hasHTML5 && !needsFlash && !_s.requireFlash);\r
- return (_detectFlash() && needsFlash);\r
- };\r
-\r
- _init = function() {\r
- var item, tests = [];\r
- _wDS('init');\r
-\r
- // called after onload()\r
- if (_didInit) {\r
- _wDS('didInit');\r
- return false;\r
- }\r
-\r
- function _cleanup() {\r
- _event.remove(_win, 'load', _s.beginDelayedInit);\r
- }\r
-\r
- if (_s.hasHTML5) {\r
- for (item in _s.audioFormats) {\r
- if (_s.audioFormats.hasOwnProperty(item)) {\r
- tests.push(item+': '+_s.html5[item]);\r
- }\r
- }\r
- _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1);\r
- }\r
-\r
- if (_html5Only) {\r
- if (!_didInit) {\r
- // we don't need no steenking flash!\r
- _cleanup();\r
- _s.enabled = true;\r
- _initComplete();\r
- }\r
- return true;\r
- }\r
-\r
- // flash path\r
- _initMovie();\r
- try {\r
- _wDS('flashJS');\r
- _s.o._externalInterfaceTest(false); // attempt to talk to Flash\r
- if (!_s.allowPolling) {\r
- _wDS('noPolling', 1);\r
- } else {\r
- _setPolling(true, _s.flashPollingInterval ? _s.flashPollingInterval : (_s.useFastPolling ? 10 : 50));\r
- }\r
- if (!_s.debugMode) {\r
- _s.o._disableDebug();\r
- }\r
- _s.enabled = true;\r
- _debugTS('jstoflash', true);\r
- } catch(e) {\r
- _s._wD('js/flash exception: ' + e.toString());\r
- _debugTS('jstoflash', false);\r
- _failSafely(true); // don't disable, for reboot()\r
- _initComplete();\r
- return false;\r
- }\r
- _initComplete();\r
- // event cleanup\r
- _cleanup();\r
- return true;\r
- };\r
-\r
- _beginInit = function() {\r
- if (_initPending) {\r
- return false;\r
- }\r
- _createMovie();\r
- _initMovie();\r
- _initPending = true;\r
- return true;\r
- };\r
-\r
- _dcLoaded = function() {\r
- if (_didDCLoaded) {\r
- return false;\r
- }\r
- _didDCLoaded = true;\r
- _initDebug();\r
- if (!_s.useHTML5Audio) {\r
- if (!_detectFlash()) {\r
- _s._wD('SoundManager: No Flash detected, trying HTML5');\r
- _s.useHTML5Audio = true;\r
- }\r
- }\r
- _testHTML5();\r
- _s.html5.usingFlash = _featureCheck();\r
- _needsFlash = _s.html5.usingFlash;\r
- _didDCLoaded = true;\r
- if (_doc.removeEventListener) {\r
- _doc.removeEventListener('DOMContentLoaded', _dcLoaded, false);\r
- }\r
- _go();\r
- return true;\r
- };\r
-\r
- _startTimer = function(oSound) {\r
- if (!oSound._hasTimer) {\r
- oSound._hasTimer = true;\r
- }\r
- };\r
-\r
- _stopTimer = function(oSound) {\r
- if (oSound._hasTimer) {\r
- oSound._hasTimer = false;\r
- }\r
- };\r
-\r
- _die = function() {\r
- if (_s.onerror instanceof Function) {\r
- _s.onerror();\r
- }\r
- _s.disable();\r
- };\r
-\r
- _badSafariFix = function() {\r
- // special case: "bad" Safari can fall back to flash for MP3/MP4\r
- if (!_isBadSafari || !_detectFlash()) {\r
- return false; // doesn't apply\r
- }\r
- var aF = _s.audioFormats, i, item;\r
- for (item in aF) {\r
- if (aF.hasOwnProperty(item)) {\r
- // special case: "bad" Safari can fall back to flash for MP3/MP4\r
- if (item === 'mp3' || item === 'mp4') {\r
- _s._wD(_sm+': Using flash fallback for '+item+' format');\r
- _s.html5[item] = false;\r
- // assign result to related formats, too\r
- if (aF[item] && aF[item].related) {\r
- for (i = aF[item].related.length; i--;) {\r
- _s.html5[aF[item].related[i]] = false;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- };\r
-\r
- // pseudo-private methods called by Flash\r
-\r
- this._setSandboxType = function(sandboxType) {\r
- // <d>\r
- var sb = _s.sandbox;\r
- sb.type = sandboxType;\r
- sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')];\r
- _s._wD('Flash security sandbox type: ' + sb.type);\r
- if (sb.type === 'localWithFile') {\r
- sb.noRemote = true;\r
- sb.noLocal = false;\r
- _wDS('secNote', 2);\r
- } else if (sb.type === 'localWithNetwork') {\r
- sb.noRemote = false;\r
- sb.noLocal = true;\r
- } else if (sb.type === 'localTrusted') {\r
- sb.noRemote = false;\r
- sb.noLocal = false;\r
- }\r
- // </d>\r
- };\r
-\r
- this._externalInterfaceOK = function(flashDate) {\r
- // flash callback confirming flash loaded, EI working etc.\r
- // flashDate = approx. timing/delay info for JS/flash bridge\r
- if (_s.swfLoaded) {\r
- return false;\r
- }\r
- var eiTime = new Date().getTime();\r
- _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':''));\r
- _debugTS('swf', true);\r
- _debugTS('flashtojs', true);\r
- _s.swfLoaded = true;\r
- _tryInitOnFocus = false;\r
- if (_isBadSafari) {\r
- _badSafariFix();\r
- }\r
- if (_isIE) {\r
- // IE needs a timeout OR delay until window.onload - may need TODO: investigating\r
- setTimeout(_init, 100);\r
- } else {\r
- _init();\r
- }\r
- };\r
-\r
- _dcIE = function() {\r
- if (_doc.readyState === 'complete') {\r
- _dcLoaded();\r
- _doc.detachEvent('onreadystatechange', _dcIE);\r
- }\r
- return true;\r
- };\r
-\r
- // focus and window load, init\r
- if (!_s.hasHTML5 || _needsFlash) {\r
- // only applies to Flash mode\r
- _event.add(_win, 'focus', _handleFocus);\r
- _event.add(_win, 'load', _handleFocus);\r
- _event.add(_win, 'load', _delayWaitForEI);\r
- if (_isSafari && _tryInitOnFocus) {\r
- _event.add(_win, 'mousemove', _handleFocus); // massive Safari focus hack\r
- }\r
- }\r
-\r
- if (_doc.addEventListener) {\r
- _doc.addEventListener('DOMContentLoaded', _dcLoaded, false);\r
- } else if (_doc.attachEvent) {\r
- _doc.attachEvent('onreadystatechange', _dcIE);\r
- } else {\r
- // no add/attachevent support - safe to assume no JS -> Flash either\r
- _debugTS('onload', false);\r
- _die();\r
- }\r
-\r
- if (_doc.readyState === 'complete') {\r
- setTimeout(_dcLoaded,100);\r
- }\r
-\r
-} // SoundManager()\r
-\r
-// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading\r
-if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) {\r
- soundManager = new SoundManager();\r
-}\r
-\r
-// public interfaces\r
-window.SoundManager = SoundManager; // constructor\r
-window.soundManager = soundManager; // public API, flash callbacks etc\r
-\r
-}(window));\r
+++ /dev/null
-/* This notice must be untouched at all times.\r
-\r
-wz_jsgraphics.js v. 3.03\r
-The latest version is available at\r
-http://www.walterzorn.com\r
-or http://www.devira.com\r
-or http://www.walterzorn.de\r
-\r
-Copyright (c) 2002-2004 Walter Zorn. All rights reserved.\r
-Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )\r
-Last modified: 28. 1. 2008\r
-\r
-Performance optimizations for Internet Explorer\r
-by Thomas Frank and John Holdsworth.\r
-fillPolygon method implemented by Matthieu Haller.\r
-\r
-High Performance JavaScript Graphics Library.\r
-Provides methods\r
-- to draw lines, rectangles, ellipses, polygons\r
- with specifiable line thickness,\r
-- to fill rectangles, polygons, ellipses and arcs\r
-- to draw text.\r
-NOTE: Operations, functions and branching have rather been optimized\r
-to efficiency and speed than to shortness of source code.\r
-\r
-LICENSE: LGPL\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License (LGPL) as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,\r
-or see http://www.gnu.org/copyleft/lesser.html\r
-*/\r
-\r
-\r
-var jg_ok, jg_ie, jg_fast, jg_dom, jg_moz;\r
-\r
-\r
-function _chkDHTM(x, i)\r
-{\r
- x = document.body || null;\r
- jg_ie = x && typeof x.insertAdjacentHTML != "undefined" && document.createElement;\r
- jg_dom = (x && !jg_ie &&\r
- typeof x.appendChild != "undefined" &&\r
- typeof document.createRange != "undefined" &&\r
- typeof (i = document.createRange()).setStartBefore != "undefined" &&\r
- typeof i.createContextualFragment != "undefined");\r
- jg_fast = jg_ie && document.all && !window.opera;\r
- jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";\r
- jg_ok = !!(jg_ie || jg_dom);\r
-}\r
-\r
-function _pntCnvDom()\r
-{\r
- var x = this.wnd.document.createRange();\r
- x.setStartBefore(this.cnv);\r
- x = x.createContextualFragment(jg_fast? this._htmRpc() : this.htm);\r
- if(this.cnv) this.cnv.appendChild(x);\r
- this.htm = "";\r
-}\r
-\r
-function _pntCnvIe()\r
-{\r
- if(this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this._htmRpc() : this.htm);\r
- this.htm = "";\r
-}\r
-\r
-function _pntDoc()\r
-{\r
- this.wnd.document.write(jg_fast? this._htmRpc() : this.htm);\r
- this.htm = '';\r
-}\r
-\r
-function _pntN()\r
-{\r
- ;\r
-}\r
-\r
-function _mkDiv(x, y, w, h)\r
-{\r
- this.htm += '<div style="position:absolute;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:' + w + 'px;'+\r
- 'height:' + h + 'px;'+\r
- 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
- 'background-color:' + this.color +\r
- (!jg_moz? ';overflow:hidden' : '')+\r
- ';"><\/div>';\r
-}\r
-\r
-function _mkDivIe(x, y, w, h)\r
-{\r
- this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';\r
-}\r
-\r
-function _mkDivPrt(x, y, w, h)\r
-{\r
- this.htm += '<div style="position:absolute;'+\r
- 'border-left:' + w + 'px solid ' + this.color + ';'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:0px;'+\r
- 'height:' + h + 'px;'+\r
- 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
- 'background-color:' + this.color +\r
- (!jg_moz? ';overflow:hidden' : '')+\r
- ';"><\/div>';\r
-}\r
-\r
-var _regex = /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;\r
-function _htmRpc()\r
-{\r
- return this.htm.replace(\r
- _regex,\r
- '<div style="overflow:hidden;position:absolute;background-color:'+\r
- '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');\r
-}\r
-\r
-function _htmPrtRpc()\r
-{\r
- return this.htm.replace(\r
- _regex,\r
- '<div style="overflow:hidden;position:absolute;background-color:'+\r
- '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');\r
-}\r
-\r
-function _mkLin(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1;\r
-\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx,\r
- ox = x;\r
- while(dx > 0)\r
- {--dx;\r
- ++x;\r
- if(p > 0)\r
- {\r
- this._mkDiv(ox, y, x-ox, 1);\r
- y += yIncr;\r
- p += pru;\r
- ox = x;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(ox, y, x2-ox+1, 1);\r
- }\r
-\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy,\r
- oy = y;\r
- if(y2 <= y1)\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, y, 1, oy-y+1);\r
- y += yIncr;\r
- p += pru;\r
- oy = y;\r
- }\r
- else\r
- {\r
- y += yIncr;\r
- p += pr;\r
- }\r
- }\r
- this._mkDiv(x2, y2, 1, oy-y2+1);\r
- }\r
- else\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, oy, 1, y-oy);\r
- p += pru;\r
- oy = y;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(x2, oy, 1, y2-oy+1);\r
- }\r
- }\r
-}\r
-\r
-function _mkLin2D(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1;\r
-\r
- var s = this.stroke;\r
- if(dx >= dy)\r
- {\r
- if(dx > 0 && s-3 > 0)\r
- {\r
- var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;\r
- _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
- }\r
- else var _s = s;\r
- var ad = Math.ceil(s/2);\r
-\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx,\r
- ox = x;\r
- while(dx > 0)\r
- {--dx;\r
- ++x;\r
- if(p > 0)\r
- {\r
- this._mkDiv(ox, y, x-ox+ad, _s);\r
- y += yIncr;\r
- p += pru;\r
- ox = x;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(ox, y, x2-ox+ad+1, _s);\r
- }\r
-\r
- else\r
- {\r
- if(s-3 > 0)\r
- {\r
- var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;\r
- _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
- }\r
- else var _s = s;\r
- var ad = Math.round(s/2);\r
-\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy,\r
- oy = y;\r
- if(y2 <= y1)\r
- {\r
- ++ad;\r
- while(dy > 0)\r
- {--dy;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, y, _s, oy-y+ad);\r
- y += yIncr;\r
- p += pru;\r
- oy = y;\r
- }\r
- else\r
- {\r
- y += yIncr;\r
- p += pr;\r
- }\r
- }\r
- this._mkDiv(x2, y2, _s, oy-y2+ad);\r
- }\r
- else\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, oy, _s, y-oy+ad);\r
- p += pru;\r
- oy = y;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(x2, oy, _s, y2-oy+ad+1);\r
- }\r
- }\r
-}\r
-\r
-function _mkLinDott(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1,\r
- drw = true;\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx;\r
- while(dx > 0)\r
- {--dx;\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
- drw = !drw;\r
- if(p > 0)\r
- {\r
- y += yIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- ++x;\r
- }\r
- }\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy;\r
- while(dy > 0)\r
- {--dy;\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
- drw = !drw;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- ++x;\r
- p += pru;\r
- }\r
- else p += pr;\r
- }\r
- }\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
-}\r
-\r
-function _mkOv(left, top, width, height)\r
-{\r
- var a = (++width)>>1, b = (++height)>>1,\r
- wod = width&1, hod = height&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- ox = 0, oy = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- w, h;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- w = x-ox;\r
- h = oy-y;\r
- if((w&2) && (h&2))\r
- {\r
- this._mkOvQds(cx, cy, x-2, y+2, 1, 1, wod, hod);\r
- this._mkOvQds(cx, cy, x-1, y+1, 1, 1, wod, hod);\r
- }\r
- else this._mkOvQds(cx, cy, x-1, oy, w, h, wod, hod);\r
- ox = x;\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- w = a-ox+1;\r
- h = (oy<<1)+hod;\r
- y = cy-oy;\r
- this._mkDiv(cx-a, y, w, h);\r
- this._mkDiv(cx+ox+wod-1, y, w, h);\r
-}\r
-\r
-function _mkOv2D(left, top, width, height)\r
-{\r
- var s = this.stroke;\r
- width += s+1;\r
- height += s+1;\r
- var a = width>>1, b = height>>1,\r
- wod = width&1, hod = height&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1);\r
-\r
- if(s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))\r
- {\r
- var ox = 0, oy = b,\r
- w, h,\r
- pxw;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- w = x-ox;\r
- h = oy-y;\r
-\r
- if(w-1)\r
- {\r
- pxw = w+1+(s&1);\r
- h = s;\r
- }\r
- else if(h-1)\r
- {\r
- pxw = s;\r
- h += 1+(s&1);\r
- }\r
- else pxw = h = s;\r
- this._mkOvQds(cx, cy, x-1, oy, pxw, h, wod, hod);\r
- ox = x;\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);\r
- this._mkDiv(cx+a+wod-s, cy-oy, s, (oy<<1)+hod);\r
- }\r
-\r
- else\r
- {\r
- var _a = (width-(s<<1))>>1,\r
- _b = (height-(s<<1))>>1,\r
- _x = 0, _y = _b,\r
- _aa2 = (_a*_a)<<1, _aa4 = _aa2<<1, _bb2 = (_b*_b)<<1, _bb4 = _bb2<<1,\r
- _st = (_aa2>>1)*(1-(_b<<1)) + _bb2,\r
- _tt = (_bb2>>1) - _aa2*((_b<<1)-1),\r
-\r
- pxl = new Array(),\r
- pxt = new Array(),\r
- _pxb = new Array();\r
- pxl[0] = 0;\r
- pxt[0] = b;\r
- _pxb[0] = _b-1;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- pxl[pxl.length] = x;\r
- pxt[pxt.length] = y;\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- pxl[pxl.length] = x;\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- pxt[pxt.length] = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
-\r
- if(_y > 0)\r
- {\r
- if(_st < 0)\r
- {\r
- _st += _bb2*((_x<<1)+3);\r
- _tt += _bb4*(++_x);\r
- _pxb[_pxb.length] = _y-1;\r
- }\r
- else if(_tt < 0)\r
- {\r
- _st += _bb2*((_x<<1)+3) - _aa4*(_y-1);\r
- _tt += _bb4*(++_x) - _aa2*(((_y--)<<1)-3);\r
- _pxb[_pxb.length] = _y-1;\r
- }\r
- else\r
- {\r
- _tt -= _aa2*((_y<<1)-3);\r
- _st -= _aa4*(--_y);\r
- _pxb[_pxb.length-1]--;\r
- }\r
- }\r
- }\r
-\r
- var ox = -wod, oy = b,\r
- _oy = _pxb[0],\r
- l = pxl.length,\r
- w, h;\r
- for(var i = 0; i < l; i++)\r
- {\r
- if(typeof _pxb[i] != "undefined")\r
- {\r
- if(_pxb[i] < _oy || pxt[i] < oy)\r
- {\r
- x = pxl[i];\r
- this._mkOvQds(cx, cy, x, oy, x-ox, oy-_oy, wod, hod);\r
- ox = x;\r
- oy = pxt[i];\r
- _oy = _pxb[i];\r
- }\r
- }\r
- else\r
- {\r
- x = pxl[i];\r
- this._mkDiv(cx-x, cy-oy, 1, (oy<<1)+hod);\r
- this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
- ox = x;\r
- oy = pxt[i];\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);\r
- this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
- }\r
-}\r
-\r
-function _mkOvDott(left, top, width, height)\r
-{\r
- var a = (++width)>>1, b = (++height)>>1,\r
- wod = width&1, hod = height&1, hodu = hod^1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- drw = true;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- if(drw && y >= hodu) this._mkOvQds(cx, cy, x, y, 1, 1, wod, hod);\r
- drw = !drw;\r
- }\r
-}\r
-\r
-function _mkRect(x, y, w, h)\r
-{\r
- var s = this.stroke;\r
- this._mkDiv(x, y, w, s);\r
- this._mkDiv(x+w, y, s, h);\r
- this._mkDiv(x, y+h, w+s, s);\r
- this._mkDiv(x, y+s, s, h-s);\r
-}\r
-\r
-function _mkRectDott(x, y, w, h)\r
-{\r
- this.drawLine(x, y, x+w, y);\r
- this.drawLine(x+w, y, x+w, y+h);\r
- this.drawLine(x, y+h, x+w, y+h);\r
- this.drawLine(x, y, x, y+h);\r
-}\r
-\r
-function jsgFont()\r
-{\r
- this.PLAIN = 'font-weight:normal;';\r
- this.BOLD = 'font-weight:bold;';\r
- this.ITALIC = 'font-style:italic;';\r
- this.ITALIC_BOLD = this.ITALIC + this.BOLD;\r
- this.BOLD_ITALIC = this.ITALIC_BOLD;\r
-}\r
-var Font = new jsgFont();\r
-\r
-function jsgStroke()\r
-{\r
- this.DOTTED = -1;\r
-}\r
-var Stroke = new jsgStroke();\r
-\r
-function jsGraphics(cnv, wnd)\r
-{\r
- this.setColor = function(x)\r
- {\r
- this.color = x.toLowerCase();\r
- };\r
-\r
- this.setStroke = function(x)\r
- {\r
- this.stroke = x;\r
- if(!(x+1))\r
- {\r
- this.drawLine = _mkLinDott;\r
- this._mkOv = _mkOvDott;\r
- this.drawRect = _mkRectDott;\r
- }\r
- else if(x-1 > 0)\r
- {\r
- this.drawLine = _mkLin2D;\r
- this._mkOv = _mkOv2D;\r
- this.drawRect = _mkRect;\r
- }\r
- else\r
- {\r
- this.drawLine = _mkLin;\r
- this._mkOv = _mkOv;\r
- this.drawRect = _mkRect;\r
- }\r
- };\r
-\r
- this.setPrintable = function(arg)\r
- {\r
- this.printable = arg;\r
- if(jg_fast)\r
- {\r
- this._mkDiv = _mkDivIe;\r
- this._htmRpc = arg? _htmPrtRpc : _htmRpc;\r
- }\r
- else this._mkDiv = arg? _mkDivPrt : _mkDiv;\r
- };\r
-\r
- this.setFont = function(fam, sz, sty)\r
- {\r
- this.ftFam = fam;\r
- this.ftSz = sz;\r
- this.ftSty = sty || Font.PLAIN;\r
- };\r
-\r
- this.drawPolyline = this.drawPolyLine = function(x, y)\r
- {\r
- for (var i=x.length - 1; i;)\r
- {--i;\r
- this.drawLine(x[i], y[i], x[i+1], y[i+1]);\r
- }\r
- };\r
-\r
- this.fillRect = function(x, y, w, h)\r
- {\r
- this._mkDiv(x, y, w, h);\r
- };\r
-\r
- this.drawPolygon = function(x, y)\r
- {\r
- this.drawPolyline(x, y);\r
- this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);\r
- };\r
-\r
- this.drawEllipse = this.drawOval = function(x, y, w, h)\r
- {\r
- this._mkOv(x, y, w, h);\r
- };\r
-\r
- this.fillEllipse = this.fillOval = function(left, top, w, h)\r
- {\r
- var a = w>>1, b = h>>1,\r
- wod = w&1, hod = h&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b, oy = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- xl, dw, dh;\r
- if(w) while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- xl = cx-x;\r
- dw = (x<<1)+wod;\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- dh = oy-y;\r
- this._mkDiv(xl, cy-oy, dw, dh);\r
- this._mkDiv(xl, cy+y+hod, dw, dh);\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, w, (oy<<1)+hod);\r
- };\r
-\r
- this.fillArc = function(iL, iT, iW, iH, fAngA, fAngZ)\r
- {\r
- var a = iW>>1, b = iH>>1,\r
- iOdds = (iW&1) | ((iH&1) << 16),\r
- cx = iL+a, cy = iT+b,\r
- x = 0, y = b, ox = x, oy = y,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- // Vars for radial boundary lines\r
- xEndA, yEndA, xEndZ, yEndZ,\r
- iSects = (1 << (Math.floor((fAngA %= 360.0)/180.0) << 3))\r
- | (2 << (Math.floor((fAngZ %= 360.0)/180.0) << 3))\r
- | ((fAngA >= fAngZ) << 16),\r
- aBndA = new Array(b+1), aBndZ = new Array(b+1);\r
- \r
- // Set up radial boundary lines\r
- fAngA *= Math.PI/180.0;\r
- fAngZ *= Math.PI/180.0;\r
- xEndA = cx+Math.round(a*Math.cos(fAngA));\r
- yEndA = cy+Math.round(-b*Math.sin(fAngA));\r
- _mkLinVirt(aBndA, cx, cy, xEndA, yEndA);\r
- xEndZ = cx+Math.round(a*Math.cos(fAngZ));\r
- yEndZ = cy+Math.round(-b*Math.sin(fAngZ));\r
- _mkLinVirt(aBndZ, cx, cy, xEndZ, yEndZ);\r
-\r
- while(y > 0)\r
- {\r
- if(st < 0) // Advance x\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0) // Advance x and y\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- ox = x;\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- this._mkArcDiv(ox, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- oy = y;\r
- }\r
- else // Advance y\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- if(y && (aBndA[y] != aBndA[y-1] || aBndZ[y] != aBndZ[y-1]))\r
- {\r
- this._mkArcDiv(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- ox = x;\r
- oy = y;\r
- }\r
- }\r
- }\r
- this._mkArcDiv(x, 0, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- if(iOdds >> 16) // Odd height\r
- {\r
- if(iSects >> 16) // Start-angle > end-angle\r
- {\r
- var xl = (yEndA <= cy || yEndZ > cy)? (cx - x) : cx;\r
- this._mkDiv(xl, cy, x + cx - xl + (iOdds & 0xffff), 1);\r
- }\r
- else if((iSects & 0x01) && yEndZ > cy)\r
- this._mkDiv(cx - x, cy, x, 1);\r
- }\r
- };\r
-\r
-/* fillPolygon method, implemented by Matthieu Haller.\r
-This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.\r
-C source of GD 1.8.4 found at http://www.boutell.com/gd/\r
-\r
-THANKS to Kirsten Schulz for the polygon fixes!\r
-\r
-The intersection finding technique of this code could be improved\r
-by remembering the previous intertersection, and by using the slope.\r
-That could help to adjust intersections to produce a nice\r
-interior_extrema. */\r
- this.fillPolygon = function(array_x, array_y)\r
- {\r
- var i;\r
- var y;\r
- var miny, maxy;\r
- var x1, y1;\r
- var x2, y2;\r
- var ind1, ind2;\r
- var ints;\r
-\r
- var n = array_x.length;\r
- if(!n) return;\r
-\r
- miny = array_y[0];\r
- maxy = array_y[0];\r
- for(i = 1; i < n; i++)\r
- {\r
- if(array_y[i] < miny)\r
- miny = array_y[i];\r
-\r
- if(array_y[i] > maxy)\r
- maxy = array_y[i];\r
- }\r
- for(y = miny; y <= maxy; y++)\r
- {\r
- var polyInts = new Array();\r
- ints = 0;\r
- for(i = 0; i < n; i++)\r
- {\r
- if(!i)\r
- {\r
- ind1 = n-1;\r
- ind2 = 0;\r
- }\r
- else\r
- {\r
- ind1 = i-1;\r
- ind2 = i;\r
- }\r
- y1 = array_y[ind1];\r
- y2 = array_y[ind2];\r
- if(y1 < y2)\r
- {\r
- x1 = array_x[ind1];\r
- x2 = array_x[ind2];\r
- }\r
- else if(y1 > y2)\r
- {\r
- y2 = array_y[ind1];\r
- y1 = array_y[ind2];\r
- x2 = array_x[ind1];\r
- x1 = array_x[ind2];\r
- }\r
- else continue;\r
-\r
- // Modified 11. 2. 2004 Walter Zorn\r
- if((y >= y1) && (y < y2))\r
- polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
-\r
- else if((y == maxy) && (y > y1) && (y <= y2))\r
- polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
- }\r
- polyInts.sort(_CompInt);\r
- for(i = 0; i < ints; i+=2)\r
- this._mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);\r
- }\r
- };\r
-\r
- this.drawString = function(txt, x, y)\r
- {\r
- this.htm += '<div style="position:absolute;white-space:nowrap;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'font-family:' + this.ftFam + ';'+\r
- 'font-size:' + this.ftSz + ';'+\r
- 'color:' + this.color + ';' + this.ftSty + '">'+\r
- txt +\r
- '<\/div>';\r
- };\r
-\r
-/* drawStringRect() added by Rick Blommers.\r
-Allows to specify the size of the text rectangle and to align the\r
-text both horizontally (e.g. right) and vertically within that rectangle */\r
- this.drawStringRect = function(txt, x, y, width, halign)\r
- {\r
- this.htm += '<div style="position:absolute;overflow:hidden;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:'+width +'px;'+\r
- 'text-align:'+halign+';'+\r
- 'font-family:' + this.ftFam + ';'+\r
- 'font-size:' + this.ftSz + ';'+\r
- 'color:' + this.color + ';' + this.ftSty + '">'+\r
- txt +\r
- '<\/div>';\r
- };\r
-\r
- this.drawImage = function(imgSrc, x, y, w, h, a)\r
- {\r
- this.htm += '<div style="position:absolute;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- // w (width) and h (height) arguments are now optional.\r
- // Added by Mahmut Keygubatli, 14.1.2008\r
- (w? ('width:' + w + 'px;') : '') +\r
- (h? ('height:' + h + 'px;'):'')+'">'+\r
- '<img src="' + imgSrc +'"'+ (w ? (' width="' + w + '"'):'')+ (h ? (' height="' + h + '"'):'') + (a? (' '+a) : '') + '>'+\r
- '<\/div>';\r
- };\r
-\r
- this.clear = function()\r
- {\r
- this.htm = "";\r
- if(this.cnv) this.cnv.innerHTML = "";\r
- };\r
-\r
- this._mkOvQds = function(cx, cy, x, y, w, h, wod, hod)\r
- {\r
- var xl = cx - x, xr = cx + x + wod - w, yt = cy - y, yb = cy + y + hod - h;\r
- if(xr > xl+w)\r
- {\r
- this._mkDiv(xr, yt, w, h);\r
- this._mkDiv(xr, yb, w, h);\r
- }\r
- else\r
- w = xr - xl + w;\r
- this._mkDiv(xl, yt, w, h);\r
- this._mkDiv(xl, yb, w, h);\r
- };\r
- \r
- this._mkArcDiv = function(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects)\r
- {\r
- var xrDef = cx + x + (iOdds & 0xffff), y2, h = oy - y, xl, xr, w;\r
-\r
- if(!h) h = 1;\r
- x = cx - x;\r
-\r
- if(iSects & 0xff0000) // Start-angle > end-angle\r
- {\r
- y2 = cy - y - h;\r
- if(iSects & 0x00ff)\r
- {\r
- if(iSects & 0x02)\r
- {\r
- xl = Math.max(x, aBndZ[y]);\r
- w = xrDef - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0x01)\r
- {\r
- xr = Math.min(xrDef, aBndA[y]);\r
- w = xr - x;\r
- if(w > 0) this._mkDiv(x, y2, w, h);\r
- }\r
- }\r
- else\r
- this._mkDiv(x, y2, xrDef - x, h);\r
- y2 = cy + y + (iOdds >> 16);\r
- if(iSects & 0xff00)\r
- {\r
- if(iSects & 0x0100)\r
- {\r
- xl = Math.max(x, aBndA[y]);\r
- w = xrDef - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0x0200)\r
- {\r
- xr = Math.min(xrDef, aBndZ[y]);\r
- w = xr - x;\r
- if(w > 0) this._mkDiv(x, y2, w, h);\r
- }\r
- }\r
- else\r
- this._mkDiv(x, y2, xrDef - x, h);\r
- }\r
- else\r
- {\r
- if(iSects & 0x00ff)\r
- {\r
- if(iSects & 0x02)\r
- xl = Math.max(x, aBndZ[y]);\r
- else\r
- xl = x;\r
- if(iSects & 0x01)\r
- xr = Math.min(xrDef, aBndA[y]);\r
- else\r
- xr = xrDef;\r
- y2 = cy - y - h;\r
- w = xr - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0xff00)\r
- {\r
- if(iSects & 0x0100)\r
- xl = Math.max(x, aBndA[y]);\r
- else\r
- xl = x;\r
- if(iSects & 0x0200)\r
- xr = Math.min(xrDef, aBndZ[y]);\r
- else\r
- xr = xrDef;\r
- y2 = cy + y + (iOdds >> 16);\r
- w = xr - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- }\r
- };\r
-\r
- this.setStroke(1);\r
- this.setFont("verdana,geneva,helvetica,sans-serif", "12px", Font.PLAIN);\r
- this.color = "#000000";\r
- this.htm = "";\r
- this.wnd = wnd || window;\r
-\r
- if(!jg_ok) _chkDHTM();\r
- if(jg_ok)\r
- {\r
- if(cnv)\r
- {\r
- if(typeof(cnv) == "string")\r
- this.cont = document.all? (this.wnd.document.all[cnv] || null)\r
- : document.getElementById? (this.wnd.document.getElementById(cnv) || null)\r
- : null;\r
- else if(cnv == window.document)\r
- this.cont = document.getElementsByTagName("body")[0];\r
- // If cnv is a direct reference to a canvas DOM node\r
- // (option suggested by Andreas Luleich)\r
- else this.cont = cnv;\r
- // Create new canvas inside container DIV. Thus the drawing and clearing\r
- // methods won't interfere with the container's inner html.\r
- // Solution suggested by Vladimir.\r
- this.cnv = this.wnd.document.createElement("div");\r
- this.cnv.style.fontSize=0;\r
- this.cont.appendChild(this.cnv);\r
- this.paint = jg_dom? _pntCnvDom : _pntCnvIe;\r
- }\r
- else\r
- this.paint = _pntDoc;\r
- }\r
- else\r
- this.paint = _pntN;\r
-\r
- this.setPrintable(false);\r
-}\r
-\r
-function _mkLinVirt(aLin, x1, y1, x2, y2)\r
-{\r
- var dx = Math.abs(x2-x1), dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- xIncr = (x1 > x2)? -1 : 1,\r
- yIncr = (y1 > y2)? -1 : 1,\r
- p,\r
- i = 0;\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1);\r
- p = pr-dx;\r
- while(dx > 0)\r
- {--dx;\r
- if(p > 0) // Increment y\r
- {\r
- aLin[i++] = x;\r
- y += yIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- x += xIncr;\r
- }\r
- }\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1);\r
- p = pr-dy;\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- aLin[i++] = x;\r
- if(p > 0) // Increment x\r
- {\r
- x += xIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- }\r
- }\r
- for(var len = aLin.length, i = len-i; i;)\r
- aLin[len-(i--)] = x;\r
-};\r
-\r
-function _CompInt(x, y)\r
-{\r
- return(x - y);\r
-}\r
-\r
--- /dev/null
+/**
+ * TimeSide - Web Audio Components
+ * Copyright (c) 2011 Parisson
+ * Author: Riccardo Zaccarelli
+ * License: GNU General Public License version 2.0
+ */
+
+/**
+ * Class for showing/editing a marker on details.
+ */
+var MarkerMapDiv = TimesideArray.extend({
+ init:function(currentUserName){
+ this._super();
+ this.div = this.$J("#markers_div_id");
+ this.getCurrentUserName = function(){
+ return currentUserName;
+ }
+ },
+ //overridden
+ add: function(marker, index, isNew){
+
+ var div = this.createMarkerDiv(index, marker);
+ if(index==this.length){
+ this.div.append(div);
+ }else{
+ this.$J( this.div.children()[index] ).before(div);
+ }
+ //this.setIndex(this.length-1,d); //length has been increased when calling super
+ this._super(div,index);
+ if(isNew){
+ this.setEditMode(index,true);
+ this.setFocus(index,true);
+ }
+ if(index<this.length){
+ //update indices. Note that this is NOT done at startup as index == this.length ALWAYS
+ var t = this;
+ var setIdx = t.setIndex;
+ this.each(index, function(i, div){
+ setIdx.apply(t,[div,i]);
+ });
+ }
+ this.stretch(div.find('.markersdivTitle'));
+ this.stretch(div.find('.markersdivDescription'));
+ return div;
+ },
+ //overridden
+ move: function(from, to, newOffset){
+
+ //call super method
+ var realIndex = this._super(from,to);
+ //reflect the same changes in the document:
+ var me = this.toArray();
+ if(realIndex!=from){
+ var div = me[realIndex]; //me has already been updated
+ div.detach();
+ var parent = this.div;
+ if(to==this.length){
+ parent.append(div);
+ }else{
+ this.$J( parent.children()[realIndex] ).before(div);
+ }
+ }
+
+ var t = this;
+ var setIdx = t.setIndex;
+
+ this.each(Math.min(from,realIndex),Math.max(from,realIndex)+1, function(i, div){
+ setIdx.apply(t,[div,i]);
+ });
+
+ this.setOffset(me[realIndex],newOffset);
+
+ //TODO: create a function?
+ this.setEditMode(realIndex,true);
+ this.setFocus(realIndex,true);
+ return realIndex;
+ },
+ //overridden
+ remove : function(index){
+ var div = this._super(index);
+ div.remove();
+ var me = this;
+ this.each(index,function(i, div){
+ me.setIndex.apply(me,[div,i]);
+ });
+ },
+ //overridden
+ makeTimeLabel: function(time){
+ return this._super(time,['hh','mm','ss','C']);
+ },
+ //overridden
+ clear: function(){
+ var divs = this._super();
+ for(var i=0; i< divs.length; i++){
+ divs[i].empty().remove();
+ }
+ return divs;
+ },
+ //if value is missing, toggles edit mode
+ //if editbutton is not present (marker not editable), this method does nothing
+ setEditMode: function(index, value){
+
+ var div = this.toArray()[index];
+ var editButton = div.find('.markersdivEdit');
+ if(!((editButton) && (editButton.length))){
+ return;
+ }
+ var visible = editButton.is(':visible');
+
+ if(arguments.length==1){ //toggle
+ value = visible; //if edit visible, editmode = true, otherwise false
+ }else if(value!=visible){
+ //value is defined. if true and edit mode is NOT visible, we return cause we are already in edit mode
+ //same if false (dont edit) and edit mode is visible (not edit mode)
+ return;
+ }
+ var e_okButton = div.find('.markersdivSave');
+ var e_descriptionText = div.find('.markersdivDescription');
+ var e_titleText = div.find('.markersdivTitle');
+ if(value){
+ this.debug('setting editmode');
+ div.css('backgroundColor','#E65911');
+ e_descriptionText.removeAttr('readonly').removeClass('markersdivUneditable');
+ e_titleText.removeAttr('readonly').removeClass('markersdivUneditable');
+ e_okButton.add(e_okButton.parent()).show(); //hiding also the parent div saves space (padding bottom hidden)
+ e_titleText.select(); //TODO: this does NOT set the focus on the div. Why?
+ editButton.hide();
+ //e_titleText.focus();
+ }else{
+ e_descriptionText.attr('readonly','readonly').addClass('markersdivUneditable');
+ e_titleText.attr('readonly','readonly').addClass('markersdivUneditable');
+ consolelog(e_okButton.parent());
+ e_okButton.add(e_okButton.parent()).hide(); //hiding also the parent div saves space (padding bottom hidden)
+ editButton.show();
+ div.css('backgroundColor','');
+ }
+
+ //var e_addplaylistButton = div.find('.markersdivAddPlaylist');
+
+ this.setFocus(index,value);
+ this.stretch(e_titleText);
+ },
+
+
+
+ setFocus: function(index,value){
+ // this.each(function(i,div){
+ // if(i==index && value){
+ // div.css('backgroundColor','#E65911'); //'#f5cf23'
+ // }else{
+ // div.css('backgroundColor','');
+ // }
+ // });
+ },
+
+
+ setIndex: function(div,index){
+ //div.attr('id','_markerdiv'+index);
+ div.find('.ts-marker').html(index+1);
+ var me = this;
+ var e_indexLabel = div.find('.ts-marker');
+ var e_offsetLabel =div.find('.markersdivOffset');
+ e_indexLabel.add(e_offsetLabel).unbind('click').click(function(){
+ me.setFocus(index,true);
+ me.fire('focus', {
+ 'index': index
+ });
+ return false;
+ });
+ div.find('.markersdivEdit').unbind('click').click( function(){
+ me.setEditMode(index);
+ return false; //avoid scrolling of the page on anchor click
+ });
+ },
+ /**
+ * stretches jQueryElm the whole possible width. Note that text nodes are not considered!!!!
+ */
+ stretch: function(jQueryElm){
+ var siblings = jQueryElm.siblings(":visible");
+ siblings = siblings.add(jQueryElm);
+ var spaceStretchable = jQueryElm.parent().width();
+ var $J = this.$J;
+ siblings.each(function(i,elm){
+ spaceStretchable -= $J(elm).outerWidth(true);
+ //consolelog("\t"+spaceStretchable+' elm:'+$J(elm).attr('class')+" left: "+$J(elm).position().left+" outerw:" +$J(elm).outerWidth(true)+" w: "+$J(elm).width());
+ });
+ //consolelog('w'+ jQueryElm.parent().width()+' elm.w: '+jQueryElm.width()+' spacestretchable: '+spaceStretchable);
+ var w = jQueryElm.width() + spaceStretchable;
+ jQueryElm.css('width', w+'px');
+ },
+
+ setOffset: function(div,offset){
+ div.find('.markersdivOffset').html(this.makeTimeLabel(offset));
+ },
+ createMarkerDiv : function(index, marker){
+ //TODO: why class 'ts-marker' does not work?
+ //for the moment we set the style manually, remove
+ //TODO: table width with CSS?
+ var div = this.$J('<div/>').attr('tabindex','0').addClass("markerdiv").html('<div>'+
+ '<a href=# class="ts-marker"></a>'+
+ '<a href=# class="markersdivOffset" type="text"></a>'+
+ '<input class="markersdivTitle" type="text"/>'+
+ '<a class="markersdivAddPlaylist" title="add to playlist"></a>'+
+ '<a class="markersdivEdit" title="edit">EDIT</a>'+
+ '<a class="markersdivDelete" title="delete"></a>'+
+ '</div>'+
+ '<div zero_top_padding><textarea class="markersdivDescription"></textarea></div>'+
+ '<div zero_top_padding><a class="markersdivSave">OK</a></div>'+
+ '<div zero_top_padding><span style="font-size:75%;color:#999">'+gettrans('author')+': '+marker.author+'</span></div>'); //TODO: avoid text nodes
+ div.find('a').attr('href','#');
+ //todo: remove markerlabel from css!!!!!!!
+ //new RulerMarker(div.find('.markerlbl'),div.find('.markercanvas'),'marker',false);
+
+ var e_indexLabel = div.find('.ts-marker');
+ //var e_offsetLabel =div.find('.markersdivOffset');
+ var e_okButton = div.find('.markersdivSave');
+ var e_editButton = div.find('.markersdivEdit');
+ var e_deleteButton = div.find('.markersdivDelete');
+ var e_addplaylistButton = div.find('.markersdivAddPlaylist');
+ var e_descriptionText = div.find('.markersdivDescription');
+ var e_titleText = div.find('.markersdivTitle');
+
+ //set defualt element values regardeless of the marker state
+ e_indexLabel.attr('title',marker.toString());
+ this.setIndex(div, index);
+
+ //e_offsetLabel.html(this.makeTimeLabel(marker.offset));
+ this.setOffset(div,marker.offset);
+ //set visibility and attach events according to the marker state:
+ //first, is editing or not
+ //var isEditing = marker.isEditable && marker.isModified;
+ // (!marker.isSavedOnServer || !(this.e_editButton.is(':visible')));
+
+ //if(!isEditing){
+ e_descriptionText.val(marker.desc ? marker.desc : "");
+ e_titleText.val(marker.title ? marker.title : "");
+ //}
+
+ e_okButton.add(e_okButton.parent()).hide(); //hiding also the parent div saves space (padding bottom hidden)
+ e_editButton.show();
+ e_deleteButton.show();
+ e_addplaylistButton.show();
+ e_descriptionText.attr('readonly','readonly').addClass('markersdivUneditable').unbind('focus');
+ e_titleText.attr('readonly','readonly').addClass('markersdivUneditable').unbind('focus');
+
+ //add to playlist always visible, provided that it is saved on server AND current user is logged
+ //(getCurrentUserName evaluates to true)
+ // if(!marker.isSavedOnServer || !this.getCurrentUserName()){
+ // e_addplaylistButton.hide();
+ // }else{
+ e_addplaylistButton.unbind('click').bind('click',function(evtObj_){
+ if(!marker.isSavedOnServer){
+ return false;
+ }
+ //make a request to the server to get the pk (id)
+ //note that marker.id (client side) is marker.public_id (server side)
+ json([marker.id],"telemeta.get_marker_id", function(data){
+ consolelog('received');
+ consolelog(data);
+ var id = data.result;
+ playlistUtils.showAddResourceToPlaylist(e_addplaylistButton,'marker',""+id,gettrans('marker added to the selected playlist'));
+ });
+ return false;
+ });
+
+ if(!this.getCurrentUserName()){
+ e_addplaylistButton.hide();
+ }
+
+
+ if(!marker.isEditable){ //marker is editable means that author == getCurrentUserName(). addToPlaylist
+ //visibility is skipped because it depends on other circumstances (see above)
+ e_editButton.hide();
+ e_deleteButton.hide();
+ //we unbind events to be sure
+ //e_addplaylistButton.unbind('click').hide();
+ e_okButton.unbind('click')
+ e_deleteButton.unbind('click').hide();
+ e_editButton.remove(); //so that if edit button is not present, we do not edit (safety reasons) see this.setEditMode
+ return div;
+ }
+
+
+
+ var me = this;
+
+ e_deleteButton.unbind('click').click( function(){
+ if(!(marker.isSavedOnServer) || confirm(gettrans('delete the marker permanently?'))){
+ me.fire('remove',{
+ 'marker':marker
+ });
+ }
+ return false; //avoid scrolling of the page on anchor click
+ })
+
+
+
+ //action for ok button
+ e_okButton.unbind('click').click( function(){
+ //if(marker.desc !== descriptionText.val()){ //strict equality needed. See note below
+ marker.desc = e_descriptionText.val();
+ marker.title = e_titleText.val();
+ me.fire('save',{
+ 'marker':marker
+ });
+ return false; //avoid scrolling of the page on anchor click
+ });
+
+
+ e_titleText.keydown(function(event){
+ if(e_okButton.is(':visible')){
+ if (event.keyCode == '13') {
+ event.preventDefault();
+ e_okButton.trigger('click');
+ }
+ }
+ });
+
+ return div;
+ }
+
+});
\ No newline at end of file
--- /dev/null
+/**
+ * TimeSide - Web Audio Components
+ * Copyright (c) 2011 Parisson
+ * Author: Riccardo Zaccarelli
+ * License: GNU General Public License version 2.0
+ */
+
+/**
+ * class fior managing markers in the player. Markers on the ruler (ruler.js) or on the divs (divmarker.js)
+ * are not included here, they are separate classes. See player.js (loadMarkers method) where the bindings
+ * between this class, ruler and divmarker are set
+ */
+var MarkerMap = TimesideArray.extend({
+
+ init: function(itemId, currentUserName) {
+ this._super();
+ var ui = uniqid; //defined in application.js (global vars and functions)
+ this.uniqid = function(){
+ return ui();
+ };
+ this.getItemId = function(){
+ return itemId;
+ }
+ this.getCurrentUserName = function(){
+ return currentUserName;
+ }
+
+ var me = this;
+ var confirmExit = function(){
+ var markerUnsaved=0;
+ me.each(function(i,marker){
+ if(!marker.isSavedOnServer){
+ markerUnsaved++;
+ }
+ });
+ consolelog(markerUnsaved);
+ if(markerUnsaved>0){
+ return gettrans('there is at least one unsaved marker') +' ('+ markerUnsaved+ '). '+
+ gettrans('If you exit the page you will loose your changes');
+ }
+
+ };
+ window.onbeforeunload = confirmExit;
+ },
+
+ //overridden
+ add: function(obj) {
+ //var markers = this.toArray();
+ var marker = this.createMarker(obj);
+ var idx = this.insertionIndex(marker);
+ if(idx>=0){ //it exists? there is a problem....
+ this.debug('adding a marker already existing!!'); //should not happen. however...
+ return -1;
+ }
+
+ idx = -idx-1;
+ //we do not call the super add cause we want to insert at a specified index
+ this._super(marker,idx);
+ //notifies controller.onMarkerMapAdd
+
+ this.fire('add', {
+ marker: marker,
+ index: idx,
+ isNew: (typeof obj == 'number' || typeof obj == 'string')
+ });
+ //var temp = new MarkerDiv();
+ // this.debug(this.createMarkerDiv());
+
+
+ return idx;
+ },
+ //TODO: remove from here
+
+
+ //argument is either an object loaded from server or a number specifying the marker offset
+ createMarker: function(argument){
+ var marker = null;
+ var pFloat = parseFloat;
+ if(typeof argument == 'string'){ //to be sure, it might be that we pass an offset in string format
+ argument = pFloat(argument);
+ }
+ var currentUserName = this.getCurrentUserName();
+ if(typeof argument == 'object'){
+ var editable = currentUserName === argument.author;
+ marker = {
+ id: argument.public_id,
+ offset: pFloat(argument.time), //IMPORTANT: IT IS A STRING!!!!!!
+ desc: argument.description,
+ title: argument.title,
+ author: argument.author,
+ isEditable: editable,
+ isSavedOnServer: true
+ };
+ }else if(typeof argument == 'number'){
+ marker = {
+ id: this.uniqid(),
+ offset: pFloat(argument),
+ desc: "",
+ title: "",
+ author: currentUserName,
+ isEditable: true,
+ isSavedOnServer: false
+ };
+ }
+ marker.toString = function(){
+ var props = [];
+ for(var prop in this){
+ if(!(prop == 'toString')){
+ props.push(prop+': '+this[prop]);
+ }
+ }
+ return props.sort().join("\n");
+ }
+ return marker;
+
+ },
+
+ //overridden
+ //markerOrIndex can be an number (marker index) or a marker (the index will be aearched)
+ remove: function(identifier) {
+ var idx = -1;
+ if(typeof index == 'number'){
+ idx = identifier;
+ }else{
+ idx = this.insertionIndex(identifier);
+ }
+ if(idx<0 || idx>=this.length){
+ this.each(function(i,m){
+ consolelog(m);
+ });
+ consolelog(identifier);
+ //TODO: handle error
+ this.debug('remove: marker not found');
+ return;
+ }
+
+ //build the function to be called if the marker is deleted
+ //if the marker is NOT saved on server, call the function immediately
+ var marker = this.toArray()[idx];
+ var me = this;
+ var superRemove = me._super;
+ var functionOnSuccess = function(){
+ superRemove.apply(me,[idx]);
+ me.fire('remove',{
+ 'index':idx
+ })
+ }
+
+ if(marker.isSavedOnServer){
+ //json(param,method,onSuccessFcn,onErrorFcn){
+ json([marker.id], "telemeta.del_marker",functionOnSuccess);
+ }else{
+ functionOnSuccess();
+ }
+ },
+
+ save: function(marker){
+ var idx = this.insertionIndex(marker);
+ if(idx<0 || idx>=this.length){
+ //TODO: habdle error
+ this.debug('marker not found');
+ }
+
+ //TODO: item public id defined elsewhere up, not here inside
+ var itemid = this.getItemId();
+ var isSavedOnServer = marker.isSavedOnServer;
+ var method = isSavedOnServer ? "telemeta.update_marker" : "telemeta.add_marker";
+ var param = {
+ 'item_id':itemid,
+ 'public_id': marker.id,
+ 'time':marker.offset,
+ 'author': marker.author,
+ 'title':marker.title,
+ 'description':marker.desc
+ };
+
+ //function on success:
+ var me = this;
+ var success = function(){
+ if(!isSavedOnServer){
+ marker.isSavedOnServer = true;
+ marker.isModified = false;
+ }
+ me.fire('save',{
+ 'index':idx
+ });
+ };
+ //json(param,method,onSuccessFcn,onErrorFcn){
+ json([param], method, success);
+
+ },
+
+ //overridden method
+ move: function(markerIndex, newOffset){
+ var newIndex = this.insertionIndex(newOffset);
+ //select the case:
+ if(newIndex<0){
+ //we didn't move the marker on another marker (newOffset does not correspond to any marker)
+ //just return the real insertionIndex
+ newIndex = -newIndex-1;
+ }
+ // var markers = this.getMarkers();
+ // //TODO: remove move from array prototype!!!!
+ var realIndex = this._super(markerIndex,newIndex);
+ // //var realIndex = markers.move(markerIndex,newIndex);
+ // this.debug('fromindex '+markerIndex+' to: '+newIndex+' results in '+realIndex);
+ var markers = this.toArray();
+ var marker = markers[realIndex];
+ marker.offset = newOffset;
+ marker.isModified = true;
+ this.fire('move', {
+ fromIndex: markerIndex,
+ toIndex: newIndex,
+ newOffset: newOffset
+ //,newIndex: realIndex
+ });
+ },
+
+
+ //returns the insertion index of object in this sorted array by means of a binary search algorithm.
+ // A) If object is a marker and:
+ // a1) Is found (ie, there is a marker in this map
+ // with same offset and same id), returns the index of the marker found, in the range [0, this.length-1]. Otherwise, if
+ // a2) Is not found, then returns -(insertionIndex-1), where insertionIndex is the
+ // index at which object would be inserted preserving the array order. Note that this assures that a
+ // number lower than zero means that object is not present in the array, and viceversa
+ // B) If object is a number or a string number (eg, "12.567"), then a marker with offset = object is built and compared
+ // against the markers in the map. Note however that in this case that equality between marker's offset is sufficient,
+ // as object is not provided with an id. THEREFORE, IF THE MAP CONTAINS SEVERAL MARKERS AT INDICES i, i+1, ... i+n
+ // WITH SAME OFFSET == object, THERE IS NO WAY TO DETERMINE WHICH INDEX IN [i, i+1, ... i+n] WILL BE RETURNED.
+ // See player.forward and player.rewind for an example of the B) case.
+ //LAST NOTE: BE SURE object is either a number (float) or object.offset is a number (float).
+ //In case it is not known, If it is a string number such as
+ //"4.562" the comparison falis (eg, "2.567" > "10.544") but obviously, no error is thrown in javascript
+ //
+ insertionIndex: function(object){
+ //default comparator function:
+ //returns 1 as the first argument is greater than the second
+ //returns -1 as the first argument is lower than the second
+ //returns 0 if the arguments are equal
+ var comparatorFunction = function(markerInMap,newMarker){
+ var a = markerInMap.offset;
+ var b = newMarker.offset;
+ if(a<b){
+ return -1;
+ }else if(a >b){
+ return 1;
+ }else{
+ var a1 = markerInMap.id;
+ var b1 = newMarker.id;
+ if(a1<b1){
+ return -1;
+ }else if(a1>b1){
+ return 1;
+ }
+ }
+ return 0;
+ //var ret = a < b ? -1 : (a>b ? 1 : (markerInMap.id === newMarker.id ? 0 : -1));
+ //return ret;
+ };
+ if(!(typeof object == 'object')){
+ var offset;
+ if(typeof object == 'number'){
+ offset = object;
+ }else{ //to be sure...
+ offset = parseFloat(object);
+ }
+ object = {
+ 'offset':offset
+ };
+ //key will never be found, so return either 1 or -1:
+ comparatorFunction = function(markerInMap,newMarker){
+ var a = markerInMap.offset;
+ var b = newMarker.offset;
+ return a < b ? -1 : (a>b ? 1 : 0);
+ };
+ }
+ var pInt = parseInt; //reference to parseInt outside the loop below
+ //(to increase algorithm performances)
+
+ var data = this.toArray();
+ var low = 0;
+ var high = data.length-1;
+
+ while (low <= high) {
+ //int mid = (low + high) >>> 1;
+ var mid = pInt((low + high)/2);
+ var midVal = data[mid];
+ var cmp = comparatorFunction(midVal,object);
+ if (cmp < 0){
+ //the midvalue is lower than the searched index element
+ low = mid + 1;
+ }else if (cmp > 0){
+ //the midvalue is greater than the searched index element
+ high = mid - 1;
+ }else{
+ return mid; // key found
+ }
+ }
+ return -(low + 1); // key not found
+ }
+}
+);
\ No newline at end of file
--- /dev/null
+var Player = TimesideClass.extend({
+
+ //sound duration is in milliseconds because the soundmanager has that unit,
+ //player (according to timeside syntax) has durations in seconds
+ init: function(container, sound, soundDurationInMsec, itemId, visualizers, currentUserName) {
+ this._super();
+ this.ready = false;
+ var player = this;
+
+ //container is the div #player
+
+ if (!container){
+ this.debug('ERROR: container is null in initializing the player')
+ }
+ this.getItemId = function(){
+ return itemId;
+ }
+
+ this.getContainer = function(){
+ return container;
+ }
+ this.getSound = function(){
+ return sound;
+ }
+
+ this.getVisualizers = function(){
+ return visualizers;
+ }
+
+
+ //rpivate functions for converting
+ //soundmanager has milliseconds, we use here seconds
+ var pInt = Math.round; //instantiate once for faster lookup
+ var pFloat = parseFloat; //instantiate once for faster lookup
+ function toMsec(seconds){
+ return pInt(seconds*1000);
+ }
+ function toSec(msec){
+ return pFloat(msec)/1000;
+ }
+
+
+ var sd = toSec(soundDurationInMsec);
+ this.getSoundDuration = function(){
+ return sd;
+ }
+
+ this.isPlaying = function(){
+ /*Numeric value indicating the current playing state of the sound.
+ * 0 = stopped/uninitialised
+ * 1 = playing or buffering sound (play has been called, waiting for data etc.)
+ *Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.*/
+ return sound && sound.playState==1;
+ };
+
+ var currentMarkerIndex=0;
+ this.getCurrentMarkerIndex = function(){
+ return currentMarkerIndex;
+ };
+
+ //setting the position===============================================
+ //if sound is not loaded, position is buggy. Moreover, we have to handle the conversions between units:
+ //seconds (here) and milliseconds (swmanager sound). So we store a private variable
+ //private variable and function
+ var soundPos = sound.position ? toSec(sound.position) : 0.0;
+ //private method: updates just the internal variable (called in whilePlaying below)
+ function setPos(value){
+ soundPos = value;
+ var map = player.getMarkerMap();
+ if(map){
+ currentMarkerIndex = map.insertionIndex(value);
+ if(currentMarkerIndex<0){ //see markermap.insertionindex
+ currentMarkerIndex = -currentMarkerIndex-1;
+ }
+ }
+ }
+ //public methods: calls setPos above AND updates sounbd position
+ this.setSoundPosition = function(newPositionInSeconds){
+ //for some odd reason, if we set sound.setPosition here soundPos
+ //is rounded till the 3rd decimal integer AND WILL BE ROUNDED THIS WAY IN THE FUTURE
+ //don't know why, however we set the sound position before playing (see below)
+ //however, now it works. Even odder....
+ setPos(newPositionInSeconds);
+ if(sound){
+ var s = toMsec(this.getSoundPosition());
+ sound.setPosition(s);
+ }
+ }
+ //public methods: returns the sound position
+ this.getSoundPosition = function(){
+ return soundPos;
+ };
+
+
+ // if(sound.readyState != 3){
+ // /*sound.readyState
+ // * Numeric value indicating a sound's current load status
+ // * 0 = uninitialised
+ // * 1 = loading
+ // * 2 = failed/error
+ // * 3 = loaded/success
+ // */
+ // sound.options.whileloading=function(){
+ //
+ // }
+ // };
+
+ //implement play here: while playing we do not have to update the sound position, so
+ //we call the private variable soundPos
+ this.play = function(){
+ if(!player || player.isPlaying()){ //TODO: remove?, multishot is set to false
+ return false;
+ }
+ var sound = player.getSound();
+ if(!sound){
+ return false;
+ }
+
+ var ruler = player.getRuler();
+
+ var playOptions = {
+ whileplaying: function(){
+ var sPos = toSec(this.position); //this will refer to the sound object (see below)
+ setPos(sPos);
+ if(ruler && !ruler.isPointerMovingFromMouse()){
+ ruler.movePointer(sPos);
+ }
+
+ player.showMarkerPopup(currentMarkerIndex);
+ },
+ onfinish: function() {
+ setPos(0); //reset position, not cursor, so that clicking play restarts from zero
+ }
+ };
+ //internal play function. Set all properties and play:
+ var play_ = function(sound, positionInSec){
+ //consolelog('position is '+positionInSec+' sec');
+ sound.setPosition(toMsec(positionInSec)); //TODO: remove???
+ //consolelog('sound position is '+sound.position+' msec');
+ sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play
+ playOptions.position = toMsec(positionInSec); //apparently THIS IS WORKING
+ sound.play(playOptions);
+ };
+
+ play_(sound, player.getSoundPosition());
+
+ return false;
+ };
+ //now implement also pause here: note that pause has some odd behaviour.
+ //Try this sequence: play stop moveforward moveback play pause
+ //When we press the last pause the sound restarts (??!!!!)
+ this.pause = function(){
+ var sound = this.getSound();
+ //we don't check if it's playing, as the stop must really stop anyway
+ //if(sound && this.isPlaying()){
+ sound.stop();
+ //}
+ return false;
+ };
+
+ //initializing markermap and markerui
+ var map = new MarkerMap(this.getItemId(), currentUserName);
+ this.getMarkerMap = function(){
+ return map;
+ }
+ var mapUI = new MarkerMapDiv(currentUserName);
+ this.getMarkersUI = function(){
+ return mapUI;
+ }
+ this.getCurrentUserName = function(){
+ return currentUserName;
+ }
+ //TODO: define setUpInterface here????
+
+ },
+
+
+
+ setupInterface: function() {
+
+ var sound = this.getSound();
+ consolelog('player _setupInterface sound.readyState:'+sound.readyState); //handle also cases 0 and 2????
+
+ var $J = this.$J; //defined in the super constructor
+ var me=this;
+ //image source (see below) is given a src with a temporary 1x1 pixels transparent image
+ //see http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ and
+ //http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx
+ //for details
+ var html = ["<div class='ts-viewer'>",
+ "<div class='ts-ruler'></div>",
+ "<div class='ts-wave'>",
+ "<div class='ts-image-canvas'></div>",
+ "<div class='ts-image-container'>",
+ "<img class='ts-image' src='/images/transparent.png' alt='' />",
+ "</div>",
+ "</div>",
+ "</div>",
+ "<div class='ts-control'>",
+ "<div class='ts-layout'>",
+ "<div class='ts-playback'>",
+ "<a class='ts-play'></a>",
+ "<a class='ts-pause'></a>",
+ "<a class='ts-rewind'></a>",
+ "<a class='ts-forward'></a>",
+ "<a class='ts-set-marker'></a>",
+ "<a class='ts-volume'></a>",
+ "<img class='ts-wait'/>",
+ "<select class='ts-visualizer'></select>",
+ "</div>",
+ "</div>",
+ "</div>"];
+
+ this.getContainer().html(html.join(''));
+ var container = this.getContainer();
+
+
+ var rewind = container.find('.ts-rewind');
+ var forward = container.find('.ts-forward');
+ var play = container.find('.ts-play');
+ var pause = container.find('.ts-pause');
+ var volume = container.find('.ts-volume');
+
+
+ //hide the wait image and set the src
+ var waitImg = container.find('.ts-wait');
+ waitImg.attr('src','/images/wait_small.gif').attr('title','refreshing image').attr('alt','refreshing image').hide();
+
+ //setting the select option for visualizers:
+ var visualizers = this.getVisualizers();
+ var select = container.find('.ts-visualizer');
+ for(var name in visualizers){
+ //$J('<option/>').val(visualizers[name]).html(name).appendTo(select);
+ $J('<option/>').html(name).appendTo(select);
+ }
+ //assigning event on select:
+ select.change(
+ function (){
+ me.refreshImage.apply(me);
+ });
+
+ var rewind_ = this.rewind;
+ var forward_ = this.forward;
+ rewind.attr('href', '#').click(function(e){
+ rewind_.apply(me);
+ return false;
+ });
+ forward.attr('href', '#').click(function(e){
+ forward_.apply(me);
+ return false;
+ });
+
+ //volume:
+ function setVolume(event){
+ var ticks = [18,26,33,40,47];
+ var vol = event.layerX;
+ for(var i=0; i<ticks.length; i++){
+ if(vol<=ticks[i]){
+ var volume = i*20;
+ me.setSoundVolume(volume);
+ me.debug('setting volume'+volume);
+ return false;
+ }
+ }
+ me.setSoundVolume(100);
+ return false;
+ }
+ volume.attr('href', '#').click(function(event){
+ return setVolume(event);
+ });
+
+ //assigning title to all anchors
+ container.find('a').attr('href', '#')
+ .each(function(i, a){
+ a = $J(a);
+ a.attr('title', a.attr('class').substring(3));
+ });
+
+ //creating the ruler
+ var viewer = container.find('.ts-viewer');
+ var ruler = new Ruler(viewer, this.getSoundDuration(), (this.getCurrentUserName() || false));
+ this.getRuler = function(){
+ return ruler;
+ }
+
+ this.resize(); //which calls also ruler.resize() (see below)
+
+ //TODO: here? maybe in the constructor
+ this.setSoundVolume(this.getSoundVolume());
+
+
+ //bind events to play and pause.
+ //pause:
+ var pause_ = me.pause;
+ pause.attr('href', '#').bind('click', function(){
+ pause_.apply(me);
+ return false;
+ });
+ //play:
+ var play_ = me.play;
+ play.attr('href', '#').bind('click', function(){
+ play_.apply(me);
+ return false;
+ });
+
+ //binds click for the pointer: TODO: change this way of getting the tsviweer!!!!
+ var v = $J('#player').find('.ts-viewer');
+ v.unbind('click').click(function(evt){
+ var w = v.width();
+ var x = evt.pageX - v.offset().left; //using absolute coordinates allows us to
+ //avoid checking whether or not we are clicking on a vertical marker line, on a subdiv etcetera
+ var sd = me.getSoundDuration();
+ me.setSoundPosition(sd*x/w);
+ ruler.movePointer(ruler.toSoundPosition(x));
+ });
+
+
+ //finally, load markers and bind events for markers (see method below):
+ //NOTE: loadMarkers ASYNCHRONOUSLY CALLS THE SERVER, SO METHODS WRITTEN AFTER IT MIGHT BE EXECUTED BEFORE
+ //loadMarkers has finished its job
+ this.loadMarkers();
+
+ //set the marker popup
+ //functions to set the marker popup
+ // var popupMarker = $J('<div/>').addClass('component').css({
+ // 'dislay':'none',
+ // 'position':'absolute',
+ // 'zIndex':1000,
+ // 'overflow':'auto',
+ // 'display':'none' //TODO: remove this
+ // //'backgroundColor':'#666'
+ // });
+ // $J('body').append(popupMarker);
+ // var w = v.width();
+ // var h = v.height();
+ // var offs = v.offset(); //relative to the document
+ // var width = parseInt(w/2);
+ // var height = parseInt(h/2);
+ // var margin = 5;
+ // popupMarker.css({
+ // 'left':(margin+offs.left+width)+'px',
+ // 'top': parseInt(margin+offs.top)+'px',
+ // 'width':width+'px',
+ // 'height':height+'px'
+ // });
+ // popupMarker.html("<table style='width:100%'><tr><td>"+gettrans('title')+"</td><td class='title'></td></tr><tr><td>"+
+ // gettrans('description')+"</td><td class='description'></td></tr></table>");
+ // this.getMarkerPopup = function(){
+ // return popupMarker;
+ // }
+ },
+
+ showMarkerPopup: function(markerIndex){
+ // var popup = this.getMarkerPopup();
+ //
+ // if(popup.attr('id') != 'markerpopup'+markerIndex){
+ //
+ // var marker = this.getMarkerMap().toArray()[markerIndex];
+ // var pos = this.getSoundPosition();
+ // var mPos = marker.offset;
+ // var span = 0.3;
+ //
+ // if(pos>=mPos-span && pos<=mPos+span){
+ // consolelog('songpos: '+pos+' nextmarkerpos:'+mPos);
+ // popup.attr('id','markerpopup'+markerIndex);
+ // popup.find('.title').html(marker.title);
+ // popup.find('.description').html(marker.desc);
+ // if(!popup.is(':visible')){
+ // popup.show('fast');
+ // }
+ // }
+ // }
+ },
+
+ /**
+ * sets whether or not window resize resizes also this player. When true, a variable _dynamicResize =setInterval(...) is attached to
+ * this class. When false, if _dynamicResize is in this class, clearInterval(_dynamicResize) is called and then the key is deleted
+ */
+ setDynamicResize: function(value){
+ var key = '_dynamicResize';
+ if(!value && key in this){
+ clearInterval(this[key]);
+ delete this[key];
+ return;
+ }
+ var wdw = this.$J(window);
+ var w = wdw.width();
+ //var h = wdw.height();
+ var me = this;
+ this.dynamicResize = setInterval(function(){
+ var newW = wdw.width();
+ if(w!=newW){
+ w = newW;
+ //still wait a second: are we still adjusting the window? (call resize just once):
+ setTimeout(function(){
+ if(wdw.width()==newW){
+ me.resize.apply(me);
+ }
+ },200);
+ }
+ },100);
+ },
+
+ resize: function() {
+ this.debug("resizing");
+ var height;
+ var container = this.getContainer();
+
+ var wave = container.find('.ts-wave');
+ var image = container.find('.ts-image');
+ height = wave.height();
+ this.debug("wave height:" + height);
+ if (!height) {
+ //this.debug('ERROR: image height is zero in player.,resize!!!!')
+ height = image.height();
+ }
+ //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css
+ var elements = image
+ .add(container.find('.ts-image-container'))
+ .add(container.find('.ts-image-canvas'));
+
+ elements.css('width', 'auto'); // for IE6
+
+ if (!height){
+ height = 200;
+ }
+ var style = {
+ width: wave.width(),
+ height: height
+ }
+ elements.css(style);
+
+
+ //refreshing images:
+ this.refreshImage(image);
+ this.getRuler().resize();
+
+
+ //adjusting select size:
+ var select = container.find('.ts-visualizer');
+ var imgWait = container.find('.ts-wait');
+
+ //NOTE: some buttons might be hidden AFTER THIS METHOD HAS BEEN INVOKED
+ //Therefore, setting the width of select or imgWait is skipped for the moment.
+ select.css('fontSize','90%'); //this is to increase probability that the select width will fit the available space
+
+ var control = container.find('.ts-control');
+ var maxHeight = control.height();
+ select.add(imgWait).css('maxHeight',(maxHeight-2)+'px'); //at least a margin left and top of 1 px (see below)
+
+ var span = (maxHeight-select.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
+ select.css({'margin':'0px', 'marginTop':span+'px','marginLeft':span+'px'});
+ var span2 = (maxHeight - imgWait.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
+ imgWait.css({'margin':'0px', 'marginTop':span2+'px','marginLeft':span+'px'})
+
+
+ return this;
+ },
+
+ // getImageUrl: function(){
+ // return this.$J('#visualizer_id').get(0).value;
+ // },
+ refreshImage: function(optionalImgJQueryElm){
+ var image;
+ var container = this.getContainer();
+ if(optionalImgJQueryElm){
+ image = optionalImgJQueryElm;
+ }else{
+ image = container.find('.ts-image');
+ }
+ var select = container.find('.ts-visualizer');
+ var funcImg = function(player_image_url, width, height){
+ var _src_ = null;
+ if (player_image_url && (width || height)) {
+ _src_ = player_image_url.replace('WIDTH', width + '').replace('HEIGHT', height + '');
+ }
+ return _src_;
+ };
+ var imageUrl = this.getVisualizers()[""+select.val()];
+ //consolelog(this.getVisualizers());
+ //alert(imageUrl);
+ var imgSrc = funcImg(imageUrl, image.width(),image.height());
+ if(image.attr('src')==imgSrc){
+ // consolelog('setting attrt');
+ return;
+ }
+ var w =select.width();
+ var h = select.height();
+ select.hide();
+ var progressBar = container.find('.ts-wait').css({
+ 'width':w+'px',
+ 'height':h+'px'
+ }).show();
+
+ image.load(function(){
+ progressBar.hide();
+ select.show();
+ image.unbind('load');
+ });
+ //this timeout is set in order to leave the time to hide show components above:
+ //setTimeout(function(){
+ image.attr('src', imgSrc);
+ //},100);
+
+ },
+
+ getSoundVolume :function(){
+ var s = this.getSound();
+ return s ? s.volume : 0;
+ },
+ //moves the pointer (and sound position) forward till the next marker or the end of sound
+ forward: function() {
+ var map = this.getMarkerMap();
+ var markers = map.toArray();
+ var len = markers.length;
+ var offset = this.getSoundDuration();
+ var position = this.getSoundPosition(); //parseFloat(this.getSoundPosition());
+ var idx = map.insertionIndex(position);
+ //consolelog('current pointer position: '+position+' '+(typeof position));
+ if(idx<0){
+ idx = -idx-1; //cursor is not on a a marker, get the insertion index
+ }else{
+ //cursor is on a marker. As there might be several markers with the same offset
+ //(see MarkerMap.insertionIndex), move to the outmost right
+ while(idx<len && markers[idx].offset == position){
+ idx++;
+ }
+ }
+
+ if(idx< len){
+ offset = markers[idx].offset;
+ }
+ this.setSoundPosition(offset);
+ this.getRuler().movePointer(offset);
+ return false;
+ },
+ //moves the pointer (and sound position) backward till the previous marker or the start of sound
+ rewind: function() {
+ var map = this.getMarkerMap();
+ var markers = map.toArray();
+ var offset = 0;
+ var position = this.getSoundPosition(); //parseFloat(this.getSoundPosition());
+ var idx = map.insertionIndex(position);
+ if(idx<0){
+ idx = -idx-1; //cursor is not on a a marker, get the insertion index
+ }else{
+ //cursor is on a marker. As there might be several markers with the same offset
+ //(see MarkerMap.insertionIndex), move to the outmost left
+ while(idx>0 && markers[idx-1].offset == position){
+ idx--;
+ }
+ }
+ idx--; //move backward (rewind)
+ if(idx>=0){
+ offset = markers[idx].offset;
+ }
+ this.setSoundPosition(offset);
+ this.getRuler().movePointer(offset)
+ return false;
+ },
+
+ setSoundVolume: function(volume){
+
+ if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest
+ //see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number
+ volume = 100;
+ }
+ if(volume<0){
+ volume = 0;
+ }else if(volume>100){
+ volume = 100;
+ }
+ var sound = this.getSound();
+ // if(sound.volume == volume){
+ // return;
+ // }
+ sound.setVolume(volume);
+ //update the anchor image:
+ var indices = [20,40,60,80,100,100000];
+
+ var volumeElm = this.getContainer().find('.ts-volume');
+ for(var i=0; i <indices.length; i++){
+ if(volume<indices[i]){
+ var pos = -28*i;
+ pos = '0px '+ pos+ 'px'; //DO NOT SET !important as in FF3 DOES NOT WORK!!!!!
+ volumeElm.css('backgroundPosition',pos);
+ return;
+ }
+ }
+ // this.elements.volume.css('backgroundPosition','0px 0px !important')
+
+ },
+
+ loadMarkers: function(){
+ //ruler.bind('markermoved',this.markerMoved,this);
+ var $J = this.$J; //reference to jQuery
+ var isInteractive_ = this.getCurrentUserName() || false;
+ var itemId = this.getItemId();
+
+ var player = this;
+ //initialize the map.
+ var map = this.getMarkerMap();
+ var mapUI = this.getMarkersUI();
+ var ruler = this.getRuler();
+ map.clear();
+ mapUI.clear();
+ ruler.clear();
+
+ //building the onSuccess function
+ var onSuccess = function(data) {
+ var tabIndex = 0;
+ var mapuiAdd = mapUI.add;
+ var rulerAdd = ruler.add;
+
+ if(data && data.result && data.result.length>0){
+ var result = data.result;
+ //add markers to the map. No listeners associated to it (for the moment)
+ var mapAdd = map.add;
+ for(var i =0; i< result.length; i++){
+ mapAdd.apply(map,[result[i]]);
+ }
+ //add markers to ruler and div
+ map.each(function(i,marker){
+ rulerAdd.apply(ruler,[marker, i]);
+ mapuiAdd.apply(mapUI,[marker, i]);
+ });
+
+ tabIndex = result.length>0 ? 1 : 0;
+ }
+ //BINDINGS:
+ //
+ //1) ADD
+ //
+ //add binding to the setMarker button (html anchor):
+ var setMarkerButton = player.getContainer().find('.ts-set-marker');
+ var tab = $J('#tab_markers');
+ if(setMarkerButton){
+ if(isInteractive_){
+ setMarkerButton.show().attr('href','#').unbind('click').bind('click', function(){
+ if(tab && tab.length){
+ tab.trigger('click');
+ }
+ map.add(player.getSoundPosition());
+ return false;
+ });
+ }else{
+ setMarkerButton.hide().unbind('click');
+ }
+ }
+
+
+ //the function above calls map.add:
+ //add bindings when adding a marker:
+ map.bind('add',function(data){
+ mapuiAdd.apply(mapUI,[data.marker, data.index,data.isNew]);
+ rulerAdd.apply(ruler,[data.marker, data.index]);
+ });
+
+ //2) MOVE
+
+ //add the binding when we move a marker on the ruler:
+ ruler.bind('markermoved',function(data){
+ var soundPos = data.soundPosition;
+ var markerClass = data.markerClass;
+ if(markerClass=='pointer'){
+ player.setSoundPosition(soundPos);
+ }else{
+ map.move(data.markerElement.getIndex(), soundPos);
+ }
+ });
+
+ //and now add a binding to the map when we move a marker:
+ var rulerMove = ruler.move;
+ var mapuiMove = mapUI.move;
+
+ map.bind('move', function(data){
+ var from = data.fromIndex;
+ var to = data.toIndex;
+ rulerMove.apply(ruler,[from,to]);
+ mapuiMove.apply(mapUI,[from,to,data.newOffset]);
+ });
+
+ //3) EVENTS ON MARKERDIV: SAVE AND REMOVE
+ //save - UI delegates the map:
+ var mapSave = map.save;
+ mapUI.bind('save',function(data){
+ mapSave.apply(map,[data.marker]);
+ });
+ //and map delegates back to the UI:
+ var mapuiSetEditMode = mapUI.setEditMode;
+ map.bind('save',function(data){
+ mapuiSetEditMode.apply(mapUI,[data.index,false]);
+ });
+
+ //remove - UI delegates the map:
+ var mapRemove = map.remove;
+ mapUI.bind('remove',function(data){
+ mapRemove.apply(map,[data.marker]);
+ });
+ //and, again, map delegates back to the UIs:
+ var mapuiRemove = mapUI.remove;
+ var rulerRemove = ruler.remove;
+ map.bind('remove',function(data){
+ mapuiRemove.apply(mapUI, [data.index]);
+ rulerRemove.apply(ruler, [data.index]);
+ });
+
+ //finally, focus events (WHEN the user CLICKS on a textinput or a textarea on a markerdiv)
+ mapUI.bind('focus', function(data){
+ if(data && 'index' in data){
+ if(data.index>=0 && data.index<map.length){
+ var offset = map.toArray()[data.index].offset;
+ player.setSoundPosition(offset);
+ player.getRuler().movePointer(offset);
+ }
+ }
+ });
+
+ $J('#loading_span').empty().remove();
+ //TODO: move this in load_player?
+ // setUpPlayerTabs([jQuery('#tab_analysis'), jQuery('#tab_markers')],
+ // [jQuery('#analyzer_div_id'), jQuery('#markers_div_id')], tabIndex,
+ // 'tab_selected','tab_unselected');
+ setUpPlayerTabs($J('#tab_analysis').add($J('#tab_markers')),
+ [$J('#analyzer_div_id'), $J('#markers_div_id')], tabIndex,
+ 'tab_selected','tab_unselected');
+ };
+ json([itemId],"telemeta.get_markers", onSuccess);
+ }
+});
\ No newline at end of file
--- /dev/null
+/**
+ * TimeSide - Web Audio Components
+ * Copyright (c) 2011 Parisson
+ * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
+ * License: GNU General Public License version 2.0
+ */
+
+/**
+ * Class for loading a player. Requires a div#player, jQuery and all timeside javascript (player.js, markermap.js etcetera)
+ */
+
+var player; //global player variable
+
+function togglePlayerMaximization() {
+ var $ = jQuery;
+ consolelog('entered togglePlayerMaximization');
+ var view = $('#player');
+ $('#player_maximized, #player_minimized').css('display', 'none');
+ var ctr;
+ var dynamicResize = false;
+ if (view.parents('#player_maximized').length) {
+ ctr = $('#player_minimized').append(view);
+ } else {
+ ctr = $('#player_maximized').append(view);
+ dynamicResize = true;
+ }
+ ctr.css({
+ opacity: 0,
+ display: 'block'
+ });
+ var p = player;
+ if (p){
+ p.resize();
+ }
+ ctr.animate({
+ opacity: 1
+ }, 100);
+ if (p){
+ p.setDynamicResize(dynamicResize);
+ }
+}
+
+
+
+function loadPlayer(analizerUrl, soundUrl, itemId, visualizers, currentUserName){
+ var $J = jQuery;
+ var playerDiv = $J('#player');
+ if (!playerDiv.length){
+ //playerError('div #player does not exists');
+ //DO NOT RAISE ANY ERROR, JUST RETURN
+ return;
+ }
+
+ if(!(analizerUrl)){
+ playerError('invalid analyzer url');
+ return;
+ }
+
+ if(!(soundUrl)){
+ playerError('invalid sound url');
+ return;
+ }
+
+
+ //consolelog('till here all ok1');
+ var msgElm = $J('#loading_span_text'); //element to show messages
+ //consolelog('till here all ok2');
+ if(msgElm){
+ msgElm.html('Loading analyzer...');
+ }
+
+ var tableBody = $J('#analyzer_div_id').find('table').find('tbody:last');
+
+ //function to be executed when the analyzer has fully loaded (ie, a duration is provided)
+ function load_player(soundUrl, durationInMsec, itemId, visualizers, currentUserName) {
+ var sound = soundManager.createSound({
+ id: 'sound',
+ autoLoad: false,
+ url: soundUrl
+ });
+
+ loadScripts('/timeside/js/',['rulermarker.js','markermap.js', 'player.js', 'ruler.js','divmarker.js'], function() {
+
+
+ var p = new Player(jQuery('#player'), sound, durationInMsec, itemId, visualizers, currentUserName);
+ consolelog('initialized player');
+ p.setupInterface();
+
+ player = p;
+
+ $J('#player_maximized .toggle, #player_minimized .toggle').click(function() {
+ togglePlayerMaximization();
+ this.blur();
+ return false;
+ });
+ });
+ };
+
+ $J.ajax({
+ url: analizerUrl, //'analyze/xml',
+ dataType: 'xml',
+ success: function(data){
+ //populatetable
+ $J.each($J(data).find('data'),function(index,element){
+ var elm = $J(element);
+ tableBody.append('<tr><td>'+elm.attr('name')+'</td><td>'+elm.attr('value')+'</td><td>'
+ +elm.attr('unit')+'</td></tr>');
+ });
+ //loaded analizer, loading player
+ if(msgElm){
+ msgElm.html('Loading player...');
+ }
+ var duration = $J(data).find('#duration').attr('value');
+ duration = duration.split(":");
+ consolelog('analyzer loaded, duration: '+duration);
+ //format duration
+ var pin = parseInt;
+ var pfl = parseFloat;
+ var timeInMSecs=pin(duration[0])*3600+pin(duration[1])*60+pfl(duration[2]);
+ timeInMSecs = Math.round(timeInMSecs*1000);
+ load_player(soundUrl, timeInMSecs, itemId, visualizers, currentUserName);
+ },
+ error:function(){
+ playerError('Error loading analyzer');
+ //"<img src='/images/dialog-error.png' style='vertical-align:middle'/><span class='login-error'>Error loading analyzer</span>");
+ }
+ });
+}
\ No newline at end of file
--- /dev/null
+
+var Ruler = TimesideArray.extend({
+ //init constructor: soundDuration is IN SECONDS!!! (float)
+ init: function(viewer, soundDuration, isInteractive){
+ this._super();
+ var cssPref = this.cssPrefix;
+
+ this.isInteractive = function(){
+ return isInteractive;
+ };
+
+ this.getSoundDuration= function(){
+ return soundDuration;
+ };
+
+ var waveContainer = viewer.find('.' + cssPref + 'image-canvas');
+ this.debug( 'WAVECONTAINER?? LENGTH='+ waveContainer.length);
+ this.getWaveContainer =function(){
+ return waveContainer;
+ };
+ //ts-image-canvas has width=0. Why was not the case in old code?
+ //BECAUSE IN OLD CODE ts-image-canvas has style="width..height" defined, and not HERE!!!!
+ this.getContainerWidth =function(){
+ return waveContainer.width();
+ };
+
+
+ this.debug( 'init ruler: container width '+this.getContainerWidth());
+
+
+ //private function used in resize() defined below
+
+
+ var container = viewer.find('.' + cssPref + 'ruler');
+
+ this.getRulerContainer = function(){
+ return container;
+ }
+
+
+ if(!isInteractive){ //is not interactive, skip all methods assignmenets below
+ return;
+ }
+ },
+
+ resize : function(){
+ //code copied from old implementation, still to get completely what is going on here...
+ var sectionSteps = [[5, 1], [10, 1], [20, 2], [30, 5], [60, 10], [120, 20], [300, 30],
+ [600, 60], [1800, 300], [3600, 600]];
+ //old computeLayout code
+ var fullSectionDuration,sectionSubDivision, sectionsNum;
+ var width = this.getContainerWidth();
+ var duration = this.getSoundDuration();
+ var cssPref = this.cssPrefix;//defined in superclass
+ var fontSize = 10;
+ var mfloor = Math.floor; //instanciating once increases performances
+ var $J = this.$J; //reference to jQuery
+ //this.debug('container width: ' +" "+width);
+
+
+ var i, ii = sectionSteps.length;
+ var timeLabelWidth = this._textWidth('00:00', fontSize);
+ for (i = 0; i < ii; i++) {
+ var tempDuration = sectionSteps[i][0];
+ var subDivision = sectionSteps[i][1];
+ var labelsNum = mfloor(duration / tempDuration);
+ if ((i == ii - 1) || (width / labelsNum > timeLabelWidth * 2)) {
+ fullSectionDuration = tempDuration;
+ sectionSubDivision = subDivision;
+ sectionsNum = mfloor(duration / fullSectionDuration);
+ //this.debug('(in _computeLayout) this.fullSectionDuration: ' + fullSectionDuration);
+ //this.debug('(in _computeLayout) sectionsNum: ' +sectionsNum);
+ //this.debug('(in _computeLayout) sectionSubDivision: ' +sectionSubDivision);
+ break;
+ }
+ }
+ //old draw() code:
+ if (!duration) {
+ this.debug("Can't draw ruler with a duration of 0");
+ return;
+ }
+ //this.debug("draw ruler, duration: " + duration);
+
+ var container = this.getRulerContainer();
+ var layout = container.find("."+cssPref + 'layout');
+ //REDONE: if does not exists, create it
+ if(!layout || !(layout.length)){
+ layout = $J('<div/>')
+ .addClass(cssPref + 'layout')
+ .css({
+ position: 'relative'
+ }) // bugs on IE when resizing
+ //TODO: bind doubleclick events!!!!!!
+ //.bind('dblclick', this.attachWithEvent(this._onDoubleClick))
+ //.bind('resize', this.attachWithEvent(this.resize)) // Can loop ?
+ .appendTo(container);
+ }else{
+ //remove all elements neither pointer nor marker
+ layout.find(':not(a.ts-pointer,a.ts-marker,a.ts-pointer>*,a.ts-marker>*)').remove();
+ }
+
+ // if (layout && layout.length){
+ // layout.remove();
+ // }
+ // layout = $J('<div/>')
+ // .addClass(cssPref + 'layout')
+ // .css({
+ // position: 'relative'
+ // }) // bugs on IE when resizing
+ // //TODO: bind doubleclick events!!!!!!
+ // //.bind('dblclick', this.attachWithEvent(this._onDoubleClick))
+ // //.bind('resize', this.attachWithEvent(this.resize)) // Can loop ?
+ // .appendTo(container);
+
+
+
+ //creating sections
+ //defining function maketimelabel
+ var makeTimeLabel = this.makeTimeLabel;
+
+ //defining the function createSection
+ var _createSection = function(timeOffset, pixelWidth,timeLabelWidth) {
+ var section = $J('<div/>')
+ .addClass(cssPref + 'section')
+ .css({
+ fontSize: fontSize + 'px',
+ fontFamily: 'monospace',
+ width: pixelWidth,
+ overflow: 'hidden'
+ })
+ .append($J('<div />').addClass(cssPref + 'canvas'));
+
+ var topDiv = $J('<div/>')
+ .addClass(cssPref + 'label')
+ .appendTo(section);
+ var bottomDiv = $J('<div/>')
+ .addClass(cssPref + 'lines')
+
+ .appendTo(section);
+ var empty = $J('<span/>').css({
+ visibility: 'hidden'
+ }).text(' ');
+ var text;
+
+ if (pixelWidth > timeLabelWidth) {
+ text = $J('<span/>')
+ .text(makeTimeLabel(timeOffset))
+ .bind('mousedown selectstart', function() { //WHY THIS?
+ return false;
+ });
+ } else {
+ text = empty.clone();
+ }
+ topDiv.append(text);
+ bottomDiv.append(empty);
+ return section;
+ };
+ //function defined, creating sections:
+ var sections = new Array();
+ var currentWidth = 0;
+ var sectionDuration, sectionWidth;
+ for (i = 0; i <= sectionsNum; i++) {
+ if (i < sectionsNum) {
+ sectionDuration = fullSectionDuration;
+ sectionWidth = mfloor(sectionDuration / duration * width);
+ } else {
+ sectionDuration = duration - i * fullSectionDuration;
+ sectionWidth = width - currentWidth;
+
+ }
+ var section = _createSection(i * fullSectionDuration, sectionWidth, timeLabelWidth);
+ if (i > 0) {
+ section.css({
+ left: currentWidth,
+ top: 0,
+ position: 'absolute'
+ });
+ }
+ section.duration = sectionDuration;
+ layout.append(section);
+ currentWidth += section.width();
+ sections[i] = section;
+ }
+
+ //function to draw section rulers:
+ var _drawSectionRuler= function(section, drawFirstMark) {
+ var j;
+
+ var jg = new jsGraphics(section.find('.' + cssPref + 'canvas').get(0));
+ jg.setColor(layout.find('.' + cssPref + 'lines').css('color'));
+ var height = section.height();
+ var ypos;
+ for (j = 0; j < section.duration; j += sectionSubDivision) {
+ if (j == 0) {
+ if (drawFirstMark) {
+ ypos = 0;
+ } else {
+ continue;
+ }
+ } else {
+ ypos = (j == section.duration / 2) ? 1/2 + 1/8 : 3/4;
+ }
+ //var x = j / this.duration * this.width;
+ var x = j / duration * width;
+ jg.drawLine(x, height * ypos, x, height - 1);
+ }
+ jg.paint();
+ };
+ //draw section rulers
+ for (i = 0; i <= sectionsNum; i++) {
+ _drawSectionRuler(sections[i], (i > 0));
+ }
+
+
+ var pointer = undefined;
+ if('getPointer' in this){
+ pointer = this.getPointer();
+ }
+ if(!pointer){
+ //consolelog('QUALE CHAZZO E IL CONTAINER?????? ' + $J(layout.get(0)).attr('class'));
+ // pointer = new RulerMarker($J(layout.get(0)),this.getWaveContainer(),'pointer', true);
+ // pointer.setText(this.makeTimeLabel(0));
+ //
+ // this.debug('WELL, ');
+ // consolelog(pointer);
+ // var me = this;
+ // pointer.getLabel().mousedown(function(evt) {
+ // var lbl = $J(evt.target);
+ // me.markerBeingClicked = {
+ // 'marker':pointer,
+ // 'offset':evt.pageX-(lbl.offset().left+lbl.outerWidth(true)/2)
+ // };
+ // consolelog(evt.pageX-(lbl.offset().left+lbl.outerWidth(true)/2));
+ // evt.stopPropagation(); //dont notify the ruler;
+ // return false;
+ // });
+ pointer = this.add(0);
+ this.getPointer = function(){
+ return pointer;
+ };
+ }else{
+ pointer.refreshPosition();
+
+ }
+ this.each(function(i,rulermarker){
+ rulermarker.refreshPosition();
+ });
+
+ // if(!pointer){
+ // this.debug("Creating pointer:"+layout);
+ // //this.createMarkerForRuler = function(rulerLayout,viewer,className, fontSize, optionalToolTip)
+ // pointer = this.createMarkerForRuler($J(layout.get(0)),waveContainer,'pointer',fontSize,'move pointer');
+ // this.debug('pointerdisplay'+pointer.css('display'));
+ // }
+
+ //TODO: move pointer??????
+ //this._movePointer(sound.position/1000);
+
+
+ //TODO: draw markers?
+ // if (this.cfg.map) {
+ // $J(this.markers).each(function(i, m) {
+ // m.clear();
+ // });
+ // this.markers = new Array();
+ // this.cfg.map.each(this.attach(function(i, m) {
+ // this.markers.push(this._drawMarker(m, i));
+ // }));
+ // }
+ },
+
+ //overridden: Note that the pointer is NOT cleared!!!!!
+ clear: function(){
+ var markers = this._super();
+ // if('getPointer' in this){
+ // markers.push(this.getPointer());
+ // }
+ for( var i=0; i<markers.length; i++){
+ markers[i].remove();
+ }
+ return markers;
+ },
+ //overridden TimesideArray methods (add, move, remove):
+ remove: function(index){
+ var rulermarker = this._super(index);
+ rulermarker.remove();
+ this.each(index, function(i,rulermarker){
+ consolelog(i);
+ rulermarker.setIndex(i, true);
+ });
+ },
+ //overridden
+ move: function(from, to){
+ var newIndex = this._super(from,to);
+ //this.debug('ruler.move: [from:'+from+', to:'+to+', real:'+newIndex+']');
+ if(newIndex!=from){
+ var i1 = Math.min(from,newIndex);
+ var i2 = Math.max(from,newIndex)+1;
+ //this.debug('updating ['+i1+','+i2+']');
+ this.each(i1,i2, function(index,rulermarker){
+ rulermarker.setIndex(index, true);
+ });
+ }
+ },
+ //overridden
+ //markerObjOrOffset can be a marker object (see in markermap) or any object with the fields isEditable and offset
+ add: function(markerObjOrOffset, indexIfMarker){
+ var soundPosition;
+ var isMovable;
+ var markerClass;
+
+ if(typeof markerObjOrOffset == 'number'){
+ soundPosition = markerObjOrOffset;
+ isMovable = true; //this.isInteractive();
+ markerClass='pointer';
+ }else{
+ soundPosition = markerObjOrOffset.offset;
+ isMovable = markerObjOrOffset.isEditable && this.isInteractive();
+ markerClass='marker';
+ }
+
+ var container = this.getRulerContainer();
+ var layout = container.find("."+this.cssPrefix + 'layout');
+ var $J = this.$J;
+ var pointer = new RulerMarker($J(layout.get(0)),this.getWaveContainer(),markerClass);
+ //call super constructor
+ //if it is a pointer, dont add it
+ if(markerClass != 'pointer'){
+ this._super(pointer,indexIfMarker); //add at the end
+ //note that setText is called BEFORE move as move must have the proper label width
+ this.each(indexIfMarker, function(i,rulermarker){
+ rulermarker.setIndex(i,i!=indexIfMarker);
+ //rulermarker.setIndex.apply(rulermarker, [i,i!=indexIfMarker]); //update label width only if it is not this marker added
+ //as for this marker we update the position below (move)
+ });
+ this.debug('added marker at index '+indexIfMarker+' offset: '+markerObjOrOffset.offset);
+ }else{
+ //note that setText is called BEFORE move as move must have the proper label width
+ pointer.setText(this.makeTimeLabel(0));
+ }
+ //proceed with events and other stuff: move (called AFTER setText or setText)
+ pointer.move(this.toPixelOffset(soundPosition));
+
+ //pointer.setText(markerClass== 'pointer' ? this.makeTimeLabel(0) : this.length);
+
+ //click on labels stop propagating. Always:
+ var lbl = pointer.getLabel();
+ lbl.bind('click', function(evt){
+ evt.stopPropagation();
+ return false;
+ });
+
+ //if there are no events to associate, return it.
+ if(!isMovable){
+ return pointer;
+ }
+
+ //namespace for jquery event:
+ var eventId = 'markerclicked';
+ var doc = $J(document);
+
+ var me = this;
+
+ var ismovingpointer = false;
+ var setmovingpointer = function(value){
+ ismovingpointer = value;
+ }
+ //TODO: this method below private, but how to let him see in the bind below???
+ this.setPointerMovingFromMouse = function(value){
+ setmovingpointer(value);
+ }
+ this.isPointerMovingFromMouse = function(){
+ return ismovingpointer;
+ };
+ //functions to set if we are moving the pointer (for player when playing)
+
+ lbl.bind('mousedown.'+eventId,function(evt) {
+
+ if(markerClass=='pointer'){
+ me.setPointerMovingFromMouse(true);
+ }
+
+ var startX = evt.pageX; //lbl.position().left-container.position().left;
+ var startPos = lbl.position().left+lbl.width()/2;
+
+ evt.stopPropagation(); //dont notify the ruler or other elements;
+ var newPos = startPos;
+ doc.bind('mousemove.'+eventId, function(evt){
+ var x = evt.pageX;
+ newPos = startPos+(x-startX);
+ pointer.move(newPos);
+ //update the text if pointer
+ if(markerClass=='pointer'){
+ pointer.setText(me.makeTimeLabel(me.toSoundPosition(newPos)));
+ }
+ return false;
+
+ });
+ //to avoid scrolling
+ //TODO: what happens if the user releases the mouse OUTSIDE the browser????
+ var mouseup = function(evt_){
+ doc.unbind('mousemove.'+eventId);
+ doc.unbind('mouseup.'+eventId);
+ evt_.stopPropagation();
+ if(markerClass=='pointer'){
+ me.setPointerMovingFromMouse(false);
+ }
+ if(newPos == startPos){
+ consolelog('NOT MOVED!!!!');
+ return false;
+ }
+ var data = {
+ 'markerElement':pointer,
+ 'soundPosition': me.toSoundPosition.apply(me,[newPos]),
+ 'markerClass':markerClass
+ };
+ me.fire('markermoved',data);
+ return false;
+ };
+ doc.bind('mouseup.'+eventId, mouseup);
+ //lbl.bind('mouseup.'+eventId, mouseup);
+ // doc.bind('mouseup.'+eventId, function(evt){
+ // consolelog(newPos);
+ // doc.unbind('mousemove.'+eventId);
+ // doc.unbind('mouseup.'+eventId);
+ //
+ // //TODO: fire event marker moved (with the class name)
+ // var data = {
+ // 'markerElement':pointer,
+ // 'soundPosition': me.toSoundPosition.apply(me,[newPos]),
+ // 'markerClass':markerClass
+ // };
+ // me.fire('markermoved',data);
+ // return false;
+ // });
+ return false;
+ });
+
+ return pointer;
+
+
+ },
+
+ //moves the pointer, does not notify any listener.
+ //soundPosition is in seconds (float)
+ movePointer : function(soundPosition) {
+ var pointer = this.getPointer();
+ if (pointer) {
+ var pixelOffset = this.toPixelOffset(soundPosition);
+ //first set text, so the label width is set, then call move:
+ pointer.setText(this.makeTimeLabel(soundPosition));
+ pointer.move(pixelOffset); //does NOT fire any move method
+ }
+ //this.debug('moving pointer: position set to '+offset);
+ return soundPosition;
+ },
+
+ //soundPosition is in seconds (float)
+ toPixelOffset: function(soundPosition) {
+ //this.debug('sPos:' + soundPosition+ 'sDur: '+this.getSoundDuration());
+ var duration = this.getSoundDuration();
+ if (soundPosition < 0){
+ soundPosition = 0;
+ }else if (soundPosition > duration){
+ soundPosition = duration;
+ }
+ var width = this.getContainerWidth();
+ var pixelOffset = (soundPosition / duration) * width;
+ return pixelOffset;
+ },
+
+ //returns the soundPosition is in seconds (float)
+ toSoundPosition: function(pixelOffset) {
+ var width = this.getContainerWidth();
+
+ if (pixelOffset < 0){
+ pixelOffset = 0;
+ }else if (pixelOffset > width){
+ pixelOffset = width;
+ }
+ var duration = this.getSoundDuration();
+ var soundPosition = (pixelOffset / width) *duration;
+ return soundPosition;
+ }
+});
+
+
+ // TODO: check here
+ // http://stackoverflow.com/questions/3299926/ie-mousemove-bug
+ // div in IE to receive mouse events must have a background
+ // so for the moment
+
+
+
+ // var mouseDown = false;
+ // var _onMouseDown = function(evt) {
+ // mouseDown = true;
+ // this._onMouseMove(evt);
+ // evt.preventDefault(); //If this method is called, the default action of the event will not be triggered.
+ // };
+ // var _onMouseMove = function(evt) {
+ // if (mouseDown) {
+ // var pixelOffset = evt.pageX - container.offset().left;
+ // this._movePointerAndUpdateSoundPosition(pixelOffset / this.width * this.duration);
+ // //moves the pointer and fires onPointerMove
+ // }
+ // return false;
+ // };
+ //
+ // var _onMouseUp= function(evt) {
+ // if (mouseDown) {
+ // mouseDown = false;
+ // this.debug('_onMouseUp:'+this.pointerPos+' '+this.cfg.sound.position);
+ // }
+ // return false;
+ // };
+ // var imgContainer = viewer.find('.' + cssPref + 'image-container'); // for IE
+ // var element = waveContainer.add(imgContainer); //constructs a new jQuery object which is the union of the jquery objects
+ //
+ // element
+ // .bind('click dragstart', function() {
+ // return false;
+ // })
+ // .bind('mousedown', function(evt){
+ // return _onMouseDown(evt);
+ // })
+ // .bind('mousemove', function(evt){
+ // return _onMouseMove(evt);
+ // })
+ // .bind('mouseup', function(evt){
+ // return _onMouseUp(evt);
+ // });
+ // this.$J(document)
+ // .bind('mousemove', function(evt){
+ // return _onMouseMove(evt);
+ // });
\ No newline at end of file
--- /dev/null
+/**
+ * TimeSide - Web Audio Components
+ * Copyright (c) 2011 Parisson
+ * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
+ * License: GNU General Public License version 2.0
+ */
+
+/**
+ * Class representing a RulerMarker in TimesideUI
+ * Requires jQuery and all associated player classes
+ */
+
+var RulerMarker = TimesideClass.extend({
+
+ init: function(rulerLayout, viewer, className) {
+ this._super();
+ var $J = this.$J;
+ var fontSize = 10;
+ this.getFontSize = function(){
+ return fontSize;
+ }
+ var zIndex = 1000;
+ var tooltip = '';
+ //TODO: why viewer get(0) ? more than one? check and maybe simplify
+ var painter = new jsGraphics(viewer.get(0));
+ //from create (oldCode)
+ var cssPref = this.cssPrefix;
+ var y = rulerLayout.find('.' + cssPref + 'label').outerHeight();
+ //added by me:================
+ if(className == "pointer"){
+ y = 0;
+ }
+ //==========================
+ var label = $J('<a/>')
+ .css({
+ display: 'block',
+ width: '10px',
+ textAlign: 'center',
+ position: 'absolute',
+ fontSize: fontSize + 'px',
+ fontFamily: 'monospace',
+ top: y + 'px'
+ })
+ .attr('href', '#')
+ .addClass(cssPref + className)
+ .append('<span />')
+ //.hide();
+
+ if (tooltip){
+ label.attr('title', tooltip);
+ }
+
+ rulerLayout.append(label);
+
+ var height = viewer.height();
+ var x = 0;
+ painter.drawLine(x, 0, x, height);
+
+ x = [-4, 4, 0];
+ y = [0, 0, 4];
+
+ painter.fillPolygon(x, y);
+ painter.paint();
+ var nodes = $J(painter.cnv).children();
+
+ var style = {};
+ if (zIndex) {
+ style.zIndex = zIndex;
+ label.css(style);
+ }
+ style.backgroundColor = '';
+ //nodes.hide();
+ nodes.css(style).addClass(cssPref + className)
+ .each(function(i, node) {
+ node.originalPosition = parseInt($J(node).css('left'));
+ });
+
+ //set the index,
+ var index = -1;
+ this.setIndex = function(idx, optionalUpdateLabelWidth){
+ index = idx;
+ this.setText(idx+1, optionalUpdateLabelWidth ? true : false);
+ };
+ this.getIndex = function(){
+ return index;
+ }
+
+ //end=======================================================
+ //creating public methods:
+ this.getLabel = function(){
+ return label;
+ }
+
+
+ //CODE HERE BELOW IS EXECUTED ONLY IF THE MARKER HAS CAN MOVE IMPLEMENTED (see Ruler???).
+ //Otherwise, no mouse event can call these methods
+ //re-implement function move
+ // var position = 0;
+ // var relativePosition = 0; //position in percentage of container width, set it in move and use it in refreshPosition
+ //
+ // var mRound = Math.round; //instantiate the functio once
+
+ // this.move = function(pixelOffset) {
+ // var width = viewer.width();
+ // if (position != pixelOffset) {
+ // if (pixelOffset < 0) {
+ // pixelOffset = 0;
+ // } else if (pixelOffset >= width) {
+ // pixelOffset = width - 1;
+ // }
+ // nodes.each(function(i, node) {
+ // $J(node).css('left', mRound(node.originalPosition + pixelOffset) + 'px');
+ // });
+ // position = pixelOffset;
+ // this.refreshLabelPosition(width);
+ // //store relative position (see refreshPosition below)
+ // relativePosition = pixelOffset == width-1 ? 1 : pixelOffset/width;
+ // }
+ // return this;
+ // };
+ //
+ // this.refreshLabelPosition = function(optionalContainerWidth){
+ // if(!(optionalContainerWidth)){
+ // optionalContainerWidth = viewer.width();
+ // }
+ // var width = optionalContainerWidth;
+ // var pixelOffset = position;
+ // var labelWidth = label.outerWidth(); //consider margins and padding //label.width();
+ // var labelPixelOffset = pixelOffset - labelWidth / 2;
+ // if (labelPixelOffset < 0){
+ // labelPixelOffset = 0;
+ // }else if (labelPixelOffset + labelWidth > width){
+ // labelPixelOffset = width - labelWidth;
+ // }
+ // label.css({
+ // left: mRound(labelPixelOffset) + 'px'
+ // });
+ //
+ // };
+ //
+ // //function called on ruler.resize. Instead of recreating all markers, simply redraw them
+ // this.refreshPosition = function(){
+ // var width = viewer.width();
+ // //store relativePosition:
+ // var rp = relativePosition;
+ // this.move(mRound(relativePosition*width));
+ // //reset relative position, which does not have to change
+ // //but in move might have been rounded:
+ // relativePosition = rp;
+ // //last thing: resize the vertical line.
+ // //Assumptions (having a look at the web page element with a debugger and the code above
+ // //which uses jsgraphics):
+ // //The line is the first item (see drawLine above)
+ // //not only the height, but also the height of the clip property must be set
+ // var h = viewer.height();
+ // $J(nodes[0]).css({
+ // 'height':h+'px',
+ // 'clip': 'rect(0px 1px '+h+'px 0px)'
+ // });
+ // }
+ //
+ // this.remove = function() {
+ // painter.clear();
+ // $J(painter.cnv).remove();
+ // label.remove();
+ // return this;
+ // };
+
+ this.getViewer = function(){
+ return viewer;
+ }
+ this.getPainter = function(){
+ return painter;
+ }
+
+ this.positionInPixels = 0;
+ this.positionAsViewerRatio = 0;
+
+ },
+
+ //sets the text of the marker, if the text changes the marker width and optionalUpdateLabelPosition=true,
+ //re-arranges the marker position to be center-aligned with its vertical line (the one lying on the wav image)
+ setText: function(text, optionalUpdateLabelPosition) {
+ var label = this.getLabel();
+ if (label) {
+ text += '';
+ var labelWidth = this._textWidth(text, this.getFontSize()) + 10;
+ var oldWidth = label.width();
+ if (oldWidth != labelWidth) {
+ label.css({
+ width: labelWidth+'px'
+ });
+ }
+ label.find('span').html(text);
+ if(oldWidth != labelWidth && optionalUpdateLabelPosition){
+ consolelog('refreshing label position');
+ this.refreshLabelPosition();
+ }
+ }
+ return this;
+ },
+
+
+ getNodes: function(){
+ return this.$J(this.getPainter().cnv).children();
+ },
+ //these methods are executed only if marker is movable (see Ruler.js)
+
+ move : function(pixelOffset) {
+ var width = this.getViewer().width();
+ if (this.positionInPixels != pixelOffset) {
+ if (pixelOffset < 0) {
+ pixelOffset = 0;
+ } else if (pixelOffset >= width) {
+ pixelOffset = width - 1;
+ }
+ var nodes = this.getNodes();
+ var $J = this.$J;
+ var mRound = this.mRound;
+ nodes.each(function(i, node) {
+ $J(node).css('left', mRound(node.originalPosition + pixelOffset) + 'px');
+ });
+ this.positionInPixels = pixelOffset;
+ this.refreshLabelPosition(width);
+ //store relative position (see refreshPosition below)
+ this.positionAsViewerRatio = pixelOffset == width-1 ? 1 : pixelOffset/width;
+ }
+ return this;
+ },
+
+ refreshLabelPosition : function(optionalContainerWidth){
+ if(!(optionalContainerWidth)){
+ optionalContainerWidth = this.getViewer().width();
+ }
+ var label = this.getLabel();
+ var width = optionalContainerWidth;
+ var pixelOffset = this.positionInPixels;
+ var labelWidth = label.outerWidth(); //consider margins and padding //label.width();
+ var labelPixelOffset = pixelOffset - labelWidth / 2;
+ if (labelPixelOffset < 0){
+ labelPixelOffset = 0;
+ }else if (labelPixelOffset + labelWidth > width){
+ labelPixelOffset = width - labelWidth;
+ }
+ label.css({
+ left: this.mRound(labelPixelOffset) + 'px'
+ });
+
+ },
+
+ //function called on ruler.resize. Instead of recreating all markers, simply redraw them
+ refreshPosition : function(){
+ var width = this.getViewer().width();
+ //store relativePosition:
+ var rp = this.positionAsViewerRatio;
+ this.move(this.mRound(this.positionAsViewerRatio*width));
+ //reset relative position, which does not have to change
+ //but in move might have been rounded:
+ this.positionAsViewerRatio = rp;
+ //last thing: resize the vertical line.
+ //Assumptions (having a look at the web page element with a debugger and the code above
+ //which uses jsgraphics):
+ //The line is the first item (see drawLine above)
+ //not only the height, but also the height of the clip property must be set
+ var h = this.getViewer().height();
+ var nodes = this.getNodes();
+ var $J = this.$J;
+ $J(nodes[0]).css({
+ 'height':h+'px',
+ 'clip': 'rect(0px 1px '+h+'px 0px)'
+ });
+ },
+
+ remove : function() {
+ var $J = this.$J;
+ var painter = this.getPainter();
+ var label = this.getLabel();
+ painter.clear();
+ $J(painter.cnv).remove();
+ label.remove();
+ return this;
+ },
+
+ mRound: Math.round
+
+});
--- /dev/null
+/** @license
+
+ SoundManager 2: JavaScript Sound for the Web
+ ----------------------------------------------
+ http://schillmania.com/projects/soundmanager2/
+
+ Copyright (c) 2007, Scott Schiller. All rights reserved.
+ Code provided under the BSD License:
+ http://schillmania.com/projects/soundmanager2/license.txt
+
+ V2.97a.20110424
+*/
+(function(Y){function M(M,X){function i(c){return function(a){return!this._t||!this._t._a?null:c.call(this,a)}}function pa(){if(c.debugURLParam.test(N))c.debugMode=!0}this.flashVersion=8;this.debugFlash=this.debugMode=!1;this.useConsole=!0;this.waitForWindowLoad=this.consoleOnly=!1;this.nullURL="about:blank";this.allowPolling=!0;this.useFastPolling=!1;this.useMovieStar=!0;this.bgColor="#ffffff";this.useHighPerformance=!1;this.flashPollingInterval=null;this.flashLoadTimeout=1E3;this.wmode=null;this.allowScriptAccess=
+"always";this.useHTML5Audio=this.useFlashBlock=!1;this.html5Test=/^probably$/i;this.useGlobalHTML5Audio=!0;this.requireFlash=!1;this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!0},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave",
+"audio/x-wav"],required:!1}};this.defaultOptions={autoLoad:!1,stream:!0,autoPlay:!1,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfailure:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5E3,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:!0,multiShotEvents:!1,position:null,pan:0,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,
+useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.version=null;this.versionNumber="V2.97a.20110424";this.movieURL=null;this.url=M||null;this.altURL=null;this.enabled=this.swfLoaded=!1;this.o=null;this.movieID="sm2-container";this.id=X||"sm2movie";this.swfCSS={swfBox:"sm2-object-box",swfDefault:"movieContainer",swfError:"swf_error",swfTimedout:"swf_timedout",swfLoaded:"swf_loaded",swfUnblocked:"swf_unblocked",sm2Debug:"sm2_debug",
+highPerf:"high_performance",flashDebug:"flash_debug"};this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=!1;this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.didFlashBlock=this.specialWmodeCase=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.baseMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamTypes=["aac","flv","mov","mp4","m4v",
+"f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.mimePattern=this.baseMimeTypes;this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={};this.hasHTML5=null;this.html5={usingFlash:null};this.ignoreFlash=!1;var Z,c=this,y,n=navigator.userAgent,h=Y,N=h.location.href.toString(),k=this.flashVersion,g=document,$,O,r=[],E=!1,F=!1,m=!1,t=!1,qa=!1,G,o,aa,u,z,ba,P,ra,ca,v,sa,H,A,da,ea,Q,fa,ta,ua,R,
+va,I=null,ga=null,w,ha,B,S,T,ia,j,U=!1,ja=!1,wa,xa,x=null,ya,V,p=!1,J,s,ka,za,l,Da=Array.prototype.slice,K=!1,la,C,Aa,Ba=n.match(/pre\//i),Ea=n.match(/(ipad|iphone|ipod)/i);n.match(/mobile/i);var q=n.match(/msie/i),Fa=n.match(/webkit/i),L=n.match(/safari/i)&&!n.match(/chrome/i),Ga=n.match(/opera/i),ma=!N.match(/usehtml5audio/i)&&!N.match(/sm2\-ignorebadua/i)&&L&&n.match(/OS X 10_6_([3-9])/i),na=typeof g.hasFocus!=="undefined"?g.hasFocus():null,D=typeof g.hasFocus==="undefined"&&L,Ca=!D;this._use_maybe=
+N.match(/sm2\-useHTML5Maybe\=1/i);this._overHTTP=g.location?g.location.protocol.match(/http/i):null;this._http=!this._overHTTP?"http:":"";this.useAltURL=!this._overHTTP;this._global_a=null;if(Ea||Ba)c.useHTML5Audio=!0,c.ignoreFlash=!0,c.useGlobalHTML5Audio&&(K=!0);if(Ba||this._use_maybe)c.html5Test=/^(probably|maybe)$/i;this.supported=this.ok=function(){return x?m&&!t:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return q?h[c]:L?y(c)||g[c]:y(c)};this.createSound=function(b){function a(){e=
+S(e);c.sounds[d.id]=new Z(d);c.soundIDs.push(d.id);return c.sounds[d.id]}var e=null,f=null,d=null;if(!m||!c.ok())return ia("soundManager.createSound(): "+w(!m?"notReady":"notOK")),!1;arguments.length===2&&(b={id:arguments[0],url:arguments[1]});d=e=o(b);if(j(d.id,!0))return c.sounds[d.id];if(V(d))f=a(),f._setup_html5(d);else{if(k>8&&c.useMovieStar){if(d.isMovieStar===null)d.isMovieStar=d.serverURL||d.type&&d.type.match(c.netStreamPattern)||d.url.match(c.netStreamPattern)?!0:!1;if(d.isMovieStar&&d.usePeakData)d.usePeakData=
+!1}d=T(d,"soundManager.createSound(): ");f=a();if(k===8)c.o._createSound(d.id,d.onjustbeforefinishtime,d.loops||1,d.usePolicyFile);else if(c.o._createSound(d.id,d.url,d.onjustbeforefinishtime,d.usePeakData,d.useWaveformData,d.useEQData,d.isMovieStar,d.isMovieStar?d.bufferTime:!1,d.loops||1,d.serverURL,d.duration||null,d.autoPlay,!0,d.autoLoad,d.usePolicyFile),!d.serverURL)f.connected=!0,d.onconnect&&d.onconnect.apply(f);(d.autoLoad||d.autoPlay)&&!d.serverURL&&f.load(d)}d.autoPlay&&!d.serverURL&&f.play();
+return f};this.destroySound=function(b,a){if(!j(b))return!1;var e=c.sounds[b],f;e._iO={};e.stop();e.unload();for(f=0;f<c.soundIDs.length;f++)if(c.soundIDs[f]===b){c.soundIDs.splice(f,1);break}a||e.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,a){if(!j(b))return!1;return c.sounds[b].load(a)};this.unload=function(b){if(!j(b))return!1;return c.sounds[b].unload()};this.start=this.play=function(b,a){if(!m||!c.ok())return ia("soundManager.play(): "+w(!m?"notReady":"notOK")),!1;if(!j(b))return a instanceof
+Object||(a={url:a}),a&&a.url?(a.id=b,c.createSound(a).play()):!1;return c.sounds[b].play(a)};this.setPosition=function(b,a){if(!j(b))return!1;return c.sounds[b].setPosition(a)};this.stop=function(b){if(!j(b))return!1;return c.sounds[b].stop()};this.stopAll=function(){for(var b in c.sounds)c.sounds[b]instanceof Z&&c.sounds[b].stop()};this.pause=function(b){if(!j(b))return!1;return c.sounds[b].pause()};this.pauseAll=function(){for(var b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].pause()};this.resume=
+function(b){if(!j(b))return!1;return c.sounds[b].resume()};this.resumeAll=function(){for(var b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){if(!j(b))return!1;return c.sounds[b].togglePause()};this.setPan=function(b,a){if(!j(b))return!1;return c.sounds[b].setPan(a)};this.setVolume=function(b,a){if(!j(b))return!1;return c.sounds[b].setVolume(a)};this.mute=function(b){var a=0;typeof b!=="string"&&(b=null);if(b){if(!j(b))return!1;return c.sounds[b].mute()}else{for(a=
+c.soundIDs.length;a--;)c.sounds[c.soundIDs[a]].mute();c.muted=!0}return!0};this.muteAll=function(){c.mute()};this.unmute=function(b){typeof b!=="string"&&(b=null);if(b){if(!j(b))return!1;return c.sounds[b].unmute()}else{for(b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].unmute();c.muted=!1}return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){if(!j(b))return!1;return c.sounds[b].toggleMute()};this.getMemoryUse=function(){if(k===8)return 0;if(c.o)return parseInt(c.o._getMemoryUse(),
+10)};this.disable=function(b){typeof b==="undefined"&&(b=!1);if(t)return!1;t=!0;for(var a=c.soundIDs.length;a--;)ua(c.sounds[c.soundIDs[a]]);G(b);l.remove(h,"load",z);return!0};this.canPlayMIME=function(b){var a;c.hasHTML5&&(a=J({type:b}));return!x||a?a:b?b.match(c.mimePattern)?!0:!1:null};this.canPlayURL=function(b){var a;c.hasHTML5&&(a=J(b));return!x||a?a:b?b.match(c.filePattern)?!0:!1:null};this.canPlayLink=function(b){if(typeof b.type!=="undefined"&&b.type&&c.canPlayMIME(b.type))return!0;return c.canPlayURL(b.href)};
+this.getSoundById=function(b){if(!b)throw Error("soundManager.getSoundById(): sID is null/undefined");return c.sounds[b]};this.onready=function(c,a){if(c&&c instanceof Function)return a||(a=h),aa("onready",c,a),u(),!0;else throw w("needFunction","onready");};this.ontimeout=function(c,a){if(c&&c instanceof Function)return a||(a=h),aa("ontimeout",c,a),u({type:"ontimeout"}),!0;else throw w("needFunction","ontimeout");};this.getMoviePercent=function(){return c.o&&typeof c.o.PercentLoaded!=="undefined"?
+c.o.PercentLoaded():null};this._wD=this._writeDebug=function(){return!0};this._debug=function(){};this.reboot=function(){var b,a;for(b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].destruct();try{if(q)ga=c.o.innerHTML;I=c.o.parentNode.removeChild(c.o)}catch(e){}ga=I=null;c.enabled=m=U=ja=E=F=t=c.swfLoaded=!1;c.soundIDs=c.sounds=[];c.o=null;for(b in r)if(r.hasOwnProperty(b))for(a=r[b].length;a--;)r[b][a].fired=!1;h.setTimeout(function(){c.beginDelayedInit()},20)};this.destruct=function(){c.disable(!0)};
+this.beginDelayedInit=function(){qa=!0;A();setTimeout(sa,20);P()};this._html5_events={abort:i(function(){}),canplay:i(function(){this._t._onbufferchange(0);var c=!isNaN(this._t.position)?this._t.position/1E3:null;this._t._html5_canplay=!0;if(this._t.position&&this.currentTime!==c)try{this.currentTime=c}catch(a){}}),load:i(function(){this._t.loaded||(this._t._onbufferchange(0),this._t._whileloading(this._t.bytesTotal,this._t.bytesTotal,this._t._get_html5_duration()),this._t._onload(!0))}),emptied:i(function(){}),
+ended:i(function(){this._t._onfinish()}),error:i(function(){this._t._onload(!1)}),loadeddata:i(function(){}),loadedmetadata:i(function(){}),loadstart:i(function(){this._t._onbufferchange(1)}),play:i(function(){this._t._onbufferchange(0)}),playing:i(function(){this._t._onbufferchange(0)}),progress:i(function(b){if(this._t.loaded)return!1;var a,e=0,f=b.type==="progress",d=b.target.buffered;a=b.loaded||0;var oa=b.total||1;if(d&&d.length){for(a=d.length;a--;)e=d.end(a)-d.start(a);a=e/b.target.duration;
+f&&isNaN(a)}isNaN(a)||(this._t._onbufferchange(0),this._t._whileloading(a,oa,this._t._get_html5_duration()),a&&oa&&a===oa&&c._html5_events.load.call(this,b))}),ratechange:i(function(){}),suspend:i(function(b){c._html5_events.progress.call(this,b)}),stalled:i(function(){}),timeupdate:i(function(){this._t._onTimer()}),waiting:i(function(){this._t._onbufferchange(1)})};Z=function(b){var a=this,e,f,d;this.sID=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=o(b);this.pan=this.options.pan;
+this.volume=this.options.volume;this._lastURL=null;this.isHTML5=!1;this._a=null;this.id3={};this._debug=function(){};this._debug();this.load=function(b){var d=null;if(typeof b!=="undefined")a._iO=o(b,a.options),a.instanceOptions=a._iO;else if(b=a.options,a._iO=b,a.instanceOptions=a._iO,a._lastURL&&a._lastURL!==a.url)a._iO.url=a.url,a.url=null;if(!a._iO.url)a._iO.url=a.url;if(a._iO.url===a.url&&a.readyState!==0&&a.readyState!==2)return a;a._lastURL=a.url;a.loaded=!1;a.readyState=1;a.playState=0;if(V(a._iO)){if(d=
+a._setup_html5(a._iO),!d._called_load)d.load(),d._called_load=!0,a._iO.autoPlay&&a.play()}else try{a.isHTML5=!1,a._iO=T(S(a._iO)),k===8?c.o._load(a.sID,a._iO.url,a._iO.stream,a._iO.autoPlay,a._iO.whileloading?1:0,a._iO.loops||1,a._iO.usePolicyFile):c.o._load(a.sID,a._iO.url,a._iO.stream?!0:!1,a._iO.autoPlay?!0:!1,a._iO.loops||1,a._iO.autoLoad?!0:!1,a._iO.usePolicyFile)}catch(e){fa()}return a};this.unload=function(){if(a.readyState!==0){if(a.isHTML5){if(f(),a._a)a._a.pause(),a._a.src=""}else k===8?
+c.o._unload(a.sID,c.nullURL):c.o._unload(a.sID);e()}return a};this.destruct=function(b){if(a.isHTML5){if(f(),a._a)a._a.pause(),a._a.src="",K||a._remove_html5_events()}else a._iO.onfailure=null,c.o._destroySound(a.sID);b||c.destroySound(a.sID,!0)};this.start=this.play=function(b,W){var e,W=W===void 0?!0:W;b||(b={});a._iO=o(b,a._iO);a._iO=o(a._iO,a.options);a.instanceOptions=a._iO;if(a._iO.serverURL&&!a.connected)return a.getAutoPlay()||a.setAutoPlay(!0),a;V(a._iO)&&(a._setup_html5(a._iO),d());if(a.playState===
+1&&!a.paused)if(e=a._iO.multiShot)a.isHTML5&&a.setPosition(a._iO.position);else return a;if(!a.loaded)if(a.readyState===0){if(!a.isHTML5)a._iO.autoPlay=!0;a.load(a._iO)}else if(a.readyState===2)return a;if(a.paused&&a.position&&a.position>0)a.resume();else{a.playState=1;a.paused=!1;(!a.instanceCount||a._iO.multiShotEvents||k>8&&!a.isHTML5&&!a.getAutoPlay())&&a.instanceCount++;a.position=typeof a._iO.position!=="undefined"&&!isNaN(a._iO.position)?a._iO.position:0;if(!a.isHTML5)a._iO=T(S(a._iO));if(a._iO.onplay&&
+W)a._iO.onplay.apply(a),a._onplay_called=!0;a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?(d(),a._setup_html5().play()):c.o._start(a.sID,a._iO.loops||1,k===9?a.position:a.position/1E3)}return a};this.stop=function(b){if(a.playState===1){a._onbufferchange(0);a.resetOnPosition(0);if(!a.isHTML5)a.playState=0;a.paused=!1;a._iO.onstop&&a._iO.onstop.apply(a);if(a.isHTML5){if(a._a)a.setPosition(0),a._a.pause(),a.playState=0,a._onTimer(),f(),a.unload()}else c.o._stop(a.sID,b),a._iO.serverURL&&
+a.unload();a.instanceCount=0;a._iO={}}return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5?a._a&&b&&a.play():c.o._setAutoPlay(a.sID,b);b&&!a.instanceCount&&a.readyState===1&&a.instanceCount++};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===void 0&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a.resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a&&a._html5_canplay&&
+a._a.currentTime!==b)try{a._a.currentTime=b}catch(e){}}else b=k===9?a.position:b,a.readyState&&a.readyState!==2&&c.o._setPosition(a.sID,b,a.paused||!a.playState);a.isHTML5&&a.paused&&a._onTimer(!0);return a};this.pause=function(b){if(a.paused||a.playState===0&&a.readyState!==1)return a;a.paused=!0;a.isHTML5?(a._setup_html5().pause(),f()):(b||b===void 0)&&c.o._pause(a.sID);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5?
+(a._setup_html5().play(),d()):(a._iO.isMovieStar&&a.setPosition(a.position),c.o._pause(a.sID));!a._onplay_called&&a._iO.onplay?(a._iO.onplay.apply(a),a._onplay_called=!0):a._iO.onresume&&a._iO.onresume.apply(a);return a};this.togglePause=function(){if(a.playState===0)return a.play({position:k===9&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,d){typeof b==="undefined"&&(b=0);typeof d==="undefined"&&(d=!1);a.isHTML5||c.o._setPan(a.sID,b);a._iO.pan=
+b;if(!d)a.pan=b,a.options.pan=b;return a};this.setVolume=function(b,d){typeof b==="undefined"&&(b=100);typeof d==="undefined"&&(d=!1);if(a.isHTML5){if(a._a)a._a.volume=Math.max(0,Math.min(1,b/100))}else c.o._setVolume(a.sID,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;if(!d)a.volume=b,a.options.volume=b;return a};this.mute=function(){a.muted=!0;if(a.isHTML5){if(a._a)a._a.muted=!0}else c.o._setVolume(a.sID,0);return a};this.unmute=function(){a.muted=!1;var b=typeof a._iO.volume!=="undefined";if(a.isHTML5){if(a._a)a._a.muted=
+!1}else c.o._setVolume(a.sID,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=function(c,b,d){a._onPositionItems.push({position:c,method:b,scope:typeof d!=="undefined"?d:a,fired:!1});return a};this.processOnPosition=function(){var b,d;b=a._onPositionItems.length;if(!b||!a.playState||a._onPositionFired>=b)return!1;for(;b--;)if(d=a._onPositionItems[b],!d.fired&&a.position>=d.position)d.method.apply(d.scope,[d.position]),d.fired=
+!0,c._onPositionFired++;return!0};this.resetOnPosition=function(b){var d,e;d=a._onPositionItems.length;if(!d)return!1;for(;d--;)if(e=a._onPositionItems[d],e.fired&&b<=e.position)e.fired=!1,c._onPositionFired--;return!0};this._onTimer=function(c){var b={};if(a._hasTimer||c)return a._a&&(c||(a.playState>0||a.readyState===1)&&!a.paused)?(a.duration=a._get_html5_duration(),a.durationEstimate=a.duration,c=a._a.currentTime?a._a.currentTime*1E3:0,a._whileplaying(c,b,b,b,b),!0):!1};this._get_html5_duration=
+function(){var c=a._a?a._a.duration*1E3:a._iO?a._iO.duration:void 0;return c&&!isNaN(c)&&c!==Infinity?c:a._iO?a._iO.duration:null};d=function(){a.isHTML5&&wa(a)};f=function(){a.isHTML5&&xa(a)};e=function(){a._onPositionItems=[];a._onPositionFired=0;a._hasTimer=null;a._onplay_called=!1;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.position=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.failures=0;a.loaded=!1;a.playState=0;a.paused=!1;a.readyState=
+0;a.muted=!1;a.didBeforeFinish=!1;a.didJustBeforeFinish=!1;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.eqData=[];a.eqData.left=[];a.eqData.right=[]};e();this._setup_html5=function(b){var b=o(a._iO,b),d=K?c._global_a:a._a;decodeURI(b.url);var f=d&&d._t?d._t.instanceOptions:null;if(d){if(d._t&&f.url===b.url&&(!a._lastURL||a._lastURL===f.url))return d;K&&d._t&&d._t.playState&&b.url!==f.url&&d._t.stop();e();d.src=b.url;a.url=
+b.url;a._lastURL=b.url;d._called_load=!1}else if(d=new Audio(b.url),d._called_load=!1,K)c._global_a=d;a.isHTML5=!0;a._a=d;d._t=a;a._add_html5_events();d.loop=b.loops>1?"loop":"";b.autoLoad||b.autoPlay?(d.autobuffer="auto",d.preload="auto",a.load(),d._called_load=!0):(d.autobuffer=!1,d.preload="none");d.loop=b.loops>1?"loop":"";return d};this._add_html5_events=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,
+c._html5_events[b],!1);return!0};this._remove_html5_events=function(){a._a._added_events=!1;for(var b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,c._html5_events[b],!1)};this._whileloading=function(c,b,d,e){a.bytesLoaded=c;a.bytesTotal=b;a.duration=Math.floor(d);a.bufferLength=e;if(a._iO.isMovieStar)a.durationEstimate=a.duration;else if(a.durationEstimate=a._iO.duration?a.duration>a._iO.duration?a.duration:a._iO.duration:parseInt(a.bytesTotal/a.bytesLoaded*
+a.duration,10),a.durationEstimate===void 0)a.durationEstimate=a.duration;a.readyState!==3&&a._iO.whileloading&&a._iO.whileloading.apply(a)};this._onid3=function(c,b){var d=[],e,f;e=0;for(f=c.length;e<f;e++)d[c[e]]=b[e];a.id3=o(a.id3,d);a._iO.onid3&&a._iO.onid3.apply(a)};this._whileplaying=function(b,d,e,f,g){if(isNaN(b)||b===null)return!1;a.playState===0&&b>0&&(b=0);a.position=b;a.processOnPosition();if(k>8&&!a.isHTML5){if(a._iO.usePeakData&&typeof d!=="undefined"&&d)a.peakData={left:d.leftPeak,right:d.rightPeak};
+if(a._iO.useWaveformData&&typeof e!=="undefined"&&e)a.waveformData={left:e.split(","),right:f.split(",")};if(a._iO.useEQData&&typeof g!=="undefined"&&g&&g.leftEQ&&(b=g.leftEQ.split(","),a.eqData=b,a.eqData.left=b,typeof g.rightEQ!=="undefined"&&g.rightEQ))a.eqData.right=g.rightEQ.split(",")}a.playState===1&&(!a.isHTML5&&c.flashVersion===8&&!a.position&&a.isBuffering&&a._onbufferchange(0),a._iO.whileplaying&&a._iO.whileplaying.apply(a),(a.loaded||!a.loaded&&a._iO.isMovieStar)&&a._iO.onbeforefinish&&
+a._iO.onbeforefinishtime&&!a.didBeforeFinish&&a.duration-a.position<=a._iO.onbeforefinishtime&&a._onbeforefinish());return!0};this._onconnect=function(b){b=b===1;if(a.connected=b)a.failures=0,j(a.sID)&&(a.getAutoPlay()?a.play(void 0,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._onload=function(b){b=b?!0:!1;a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0);a._iO.onload&&a._iO.onload.apply(a,[b]);return!0};this._onfailure=function(b,c,d){a.failures++;
+if(a._iO.onfailure&&a.failures===1)a._iO.onfailure(a,b,c,d)};this._onbeforefinish=function(){if(!a.didBeforeFinish)a.didBeforeFinish=!0,a._iO.onbeforefinish&&a._iO.onbeforefinish.apply(a)};this._onjustbeforefinish=function(){if(!a.didJustBeforeFinish)a.didJustBeforeFinish=!0,a._iO.onjustbeforefinish&&a._iO.onjustbeforefinish.apply(a)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a.resetOnPosition(0);a._iO.onbeforefinishcomplete&&a._iO.onbeforefinishcomplete.apply(a);a.didBeforeFinish=
+!1;a.didJustBeforeFinish=!1;if(a.instanceCount){a.instanceCount--;if(!a.instanceCount)a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},f();(!a.instanceCount||a._iO.multiShotEvents)&&b&&b.apply(a)}};this._onbufferchange=function(b){if(a.playState===0)return!1;if(b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=b===1;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return!0};this._ondataerror=function(){a.playState>0&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}};
+ea=function(){return g.body?g.body:g._docElement?g.documentElement:g.getElementsByTagName("div")[0]};y=function(b){return g.getElementById(b)};o=function(b,a){var e={},f,d;for(f in b)b.hasOwnProperty(f)&&(e[f]=b[f]);f=typeof a==="undefined"?c.defaultOptions:a;for(d in f)f.hasOwnProperty(d)&&typeof e[d]==="undefined"&&(e[d]=f[d]);return e};l=function(){function b(a){var a=Da.call(a),b=a.length;c?(a[1]="on"+a[1],b>3&&a.pop()):b===3&&a.push(!1);return a}function a(a,b){var g=a.shift(),h=[f[b]];if(c)g[h](a[0],
+a[1]);else g[h].apply(g,a)}var c=h.attachEvent,f={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){a(b(arguments),"add")},remove:function(){a(b(arguments),"remove")}}}();V=function(b){return!b.serverURL&&(b.type?J({type:b.type}):J(b.url)||p)};J=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var a,e=c.audioFormats;if(!s){s=[];for(a in e)e.hasOwnProperty(a)&&(s.push(a),e[a].related&&(s=s.concat(e[a].related)));s=RegExp("\\.("+s.join("|")+
+")","i")}a=typeof b.type!=="undefined"?b.type:null;b=typeof b==="string"?b.toLowerCase().match(s):null;if(!b||!b.length)if(a)b=a.indexOf(";"),b=(b!==-1?a.substr(0,b):a).substr(6);else return!1;else b=b[0].substr(1);if(b&&typeof c.html5[b]!=="undefined")return c.html5[b];else{if(!a)if(b&&c.html5[b])return c.html5[b];else a="audio/"+b;a=c.html5.canPlayType(a);return c.html5[b]=a}};za=function(){function b(b){var d,e,f=!1;if(!a||typeof a.canPlayType!=="function")return!1;if(b instanceof Array){d=0;for(e=
+b.length;d<e&&!f;d++)if(c.html5[b[d]]||a.canPlayType(b[d]).match(c.html5Test))f=!0,c.html5[b[d]]=!0;return f}else return(b=a&&typeof a.canPlayType==="function"?a.canPlayType(b):!1)&&(b.match(c.html5Test)?!0:!1)}if(!c.useHTML5Audio||typeof Audio==="undefined")return!1;var a=typeof Audio!=="undefined"?Ga?new Audio(null):new Audio:null,e,f={},d,g;C();d=c.audioFormats;for(e in d)if(d.hasOwnProperty(e)&&(f[e]=b(d[e].type),d[e]&&d[e].related))for(g=d[e].related.length;g--;)c.html5[d[e].related[g]]=f[e];
+f.canPlayType=a?b:null;c.html5=o(c.html5,f);return!0};w=function(){};S=function(b){if(k===8&&b.loops>1&&b.stream)b.stream=!1;return b};T=function(b){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))b.usePolicyFile=!0;return b};ia=function(b){typeof console!=="undefined"&&typeof console.warn!=="undefined"&&console.warn(b)};$=function(){return!1};ua=function(b){for(var a in b)b.hasOwnProperty(a)&&typeof b[a]==="function"&&(b[a]=$)};R=function(b){typeof b==="undefined"&&
+(b=!1);(t||b)&&c.disable(b)};va=function(b){var a=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(a=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");return(b&&b.lastIndexOf("/")!==-1?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL};ca=function(){if(k!==8&&k!==9)c.flashVersion=8;var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";if(c.useHTML5Audio&&!p&&c.audioFormats.mp4.required&&c.flashVersion<9)c.flashVersion=9;k=c.flashVersion;c.version=c.versionNumber+
+(p?" (HTML5-only mode)":k===9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(k>8)c.defaultOptions=o(c.defaultOptions,c.flash9Options),c.features.buffering=!0;k>8&&c.useMovieStar?(c.defaultOptions=o(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+c.netStreamTypes.join("|")+")(\\?.*)?$","i"),c.mimePattern=c.netStreamMimeTypes,c.features.movieStar=!0):(c.useMovieStar=!1,c.features.movieStar=!1);c.filePattern=c.filePatterns[k!==8?"flash9":"flash8"];c.movieURL=(k===8?"soundmanager2.swf":
+"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=k>8};ta=function(b,a){if(!c.o||!c.allowPolling)return!1;c.o._setPolling(b,a)};Q=function(b,a){var e=a?a:c.url,f=c.altURL?c.altURL:e,d;d=ea();var h,k,i=B(),j,l=null,l=(l=g.getElementsByTagName("html")[0])&&l.dir&&l.dir.match(/rtl/i),b=typeof b==="undefined"?c.id:b;if(E&&F)return!1;if(p)return ca(),c.oMC=y(c.movieID),O(),F=E=!0,!1;E=!0;ca();c.url=va(c._overHTTP?e:f);a=c.url;c.wmode=!c.wmode&&
+c.useHighPerformance&&!c.useMovieStar?"transparent":c.wmode;if(c.wmode!==null&&(n.match(/msie 8/i)||!q&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.specialWmodeCase=!0,c.wmode=null;d={name:b,id:b,src:a,width:"100%",height:"100%",quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:c._http+"//www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)d.FlashVars="debug=1";c.wmode||
+delete d.wmode;if(q)e=g.createElement("div"),k='<object id="'+b+'" data="'+a+'" type="'+d.type+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+c._http+'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="'+d.width+'" height="'+d.height+'"><param name="movie" value="'+a+'" /><param name="AllowScriptAccess" value="'+c.allowScriptAccess+'" /><param name="quality" value="'+d.quality+'" />'+(c.wmode?'<param name="wmode" value="'+c.wmode+'" /> ':"")+
+'<param name="bgcolor" value="'+c.bgColor+'" />'+(c.debugFlash?'<param name="FlashVars" value="'+d.FlashVars+'" />':"")+"</object>";else for(h in e=g.createElement("embed"),d)d.hasOwnProperty(h)&&e.setAttribute(h,d[h]);pa();i=B();if(d=ea())if(c.oMC=y(c.movieID)?y(c.movieID):g.createElement("div"),c.oMC.id){j=c.oMC.className;c.oMC.className=(j?j+" ":c.swfCSS.swfDefault)+(i?" "+i:"");c.oMC.appendChild(e);if(q)h=c.oMC.appendChild(g.createElement("div")),h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}else{c.oMC.id=
+c.movieID;c.oMC.className=c.swfCSS.swfDefault+" "+i;h=i=null;if(!c.useFlashBlock)if(c.useHighPerformance)i={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(i={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},l)i.left=Math.abs(parseInt(i.left,10))+"px";if(Fa)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(j in i)i.hasOwnProperty(j)&&(c.oMC.style[j]=i[j]);try{q||c.oMC.appendChild(e);d.appendChild(c.oMC);if(q)h=c.oMC.appendChild(g.createElement("div")),
+h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}catch(m){throw Error(w("appXHTML"));}}return!0};j=this.getSoundById;H=function(){if(p)return Q(),!1;if(c.o)return!1;c.o=c.getMovie(c.id);if(!c.o)I?(q?c.oMC.innerHTML=ga:c.oMC.appendChild(I),I=null,E=!0):Q(c.id,c.url),c.o=c.getMovie(c.id);c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return!0};ba=function(b){if(b)c.url=b;H()};P=function(){setTimeout(ra,500)};ra=function(){if(U)return!1;U=!0;l.remove(h,"load",P);if(D&&!na)return!1;var b;
+m||(b=c.getMoviePercent());setTimeout(function(){b=c.getMoviePercent();!m&&Ca&&(b===null?c.useFlashBlock||c.flashLoadTimeout===0?c.useFlashBlock&&ha():R(!0):c.flashLoadTimeout!==0&&R(!0))},c.flashLoadTimeout)};ba=function(b){if(b)c.url=b;H()};B=function(){var b=[];c.debugMode&&b.push(c.swfCSS.sm2Debug);c.debugFlash&&b.push(c.swfCSS.flashDebug);c.useHighPerformance&&b.push(c.swfCSS.highPerf);return b.join(" ")};ha=function(){w("fbHandler");var b=c.getMoviePercent(),a=c.swfCSS;if(c.ok()){if(c.oMC)c.oMC.className=
+[B(),a.swfDefault,a.swfLoaded+(c.didFlashBlock?" "+a.swfUnblocked:"")].join(" ")}else{if(x)c.oMC.className=B()+" "+a.swfDefault+" "+(b===null?a.swfTimedout:a.swfError);c.didFlashBlock=!0;u({type:"ontimeout",ignoreInit:!0});c.onerror instanceof Function&&c.onerror.apply(h)}};v=function(){function b(){l.remove(h,"focus",v);l.remove(h,"load",v)}if(na||!D)return b(),!0;na=Ca=!0;L&&D&&l.remove(h,"mousemove",v);U=!1;b();return!0};G=function(b){if(m)return!1;if(p)return m=!0,u(),z(),!0;c.useFlashBlock&&
+c.flashLoadTimeout&&!c.getMoviePercent()||(m=!0);if(t||b){if(c.useFlashBlock)c.oMC.className=B()+" "+(c.getMoviePercent()===null?c.swfCSS.swfTimedout:c.swfCSS.swfError);u({type:"ontimeout"});c.onerror instanceof Function&&c.onerror.apply(h);return!1}l.add(h,"unload",$);if(c.waitForWindowLoad&&!qa)return l.add(h,"load",z),!1;else z();return!0};aa=function(b,a,c){typeof r[b]==="undefined"&&(r[b]=[]);r[b].push({method:a,scope:c||null,fired:!1})};u=function(b){b||(b={type:"onready"});if(!m&&b&&!b.ignoreInit)return!1;
+var a={success:b&&b.ignoreInit?c.ok():!t},e=b&&b.type?r[b.type]||[]:[],b=[],f,d=x&&c.useFlashBlock&&!c.ok();for(f=0;f<e.length;f++)e[f].fired!==!0&&b.push(e[f]);if(b.length){f=0;for(e=b.length;f<e;f++)if(b[f].scope?b[f].method.apply(b[f].scope,[a]):b[f].method(a),!d)b[f].fired=!0}return!0};z=function(){h.setTimeout(function(){c.useFlashBlock&&ha();u();c.onload instanceof Function&&c.onload.apply(h);c.waitForWindowLoad&&l.add(h,"load",z)},1)};C=function(){if(la!==void 0)return la;var b=!1,a=navigator,
+c=a.plugins,f,d=h.ActiveXObject;if(c&&c.length)(a=a.mimeTypes)&&a["application/x-shockwave-flash"]&&a["application/x-shockwave-flash"].enabledPlugin&&a["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(typeof d!=="undefined"){try{f=new d("ShockwaveFlash.ShockwaveFlash")}catch(g){}b=!!f}return la=b};ya=function(){var b,a;if(n.match(/iphone os (1|2|3_0|3_1)/i)){c.hasHTML5=!1;p=!0;if(c.oMC)c.oMC.style.display="none";return!1}if(c.useHTML5Audio){if(!c.html5||!c.html5.canPlayType)return c.hasHTML5=
+!1,!0;else c.hasHTML5=!0;if(ma&&C())return!0}else return!0;for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&&c.audioFormats[a].required&&!c.html5.canPlayType(c.audioFormats[a].type)&&(b=!0);c.ignoreFlash&&(b=!1);p=c.useHTML5Audio&&c.hasHTML5&&!b&&!c.requireFlash;return C()&&b};O=function(){var b,a=[];if(m)return!1;if(c.hasHTML5)for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&a.push(b+": "+c.html5[b]);if(p){if(!m)l.remove(h,"load",c.beginDelayedInit),c.enabled=!0,G();return!0}H();
+try{c.o._externalInterfaceTest(!1),c.allowPolling&&ta(!0,c.flashPollingInterval?c.flashPollingInterval:c.useFastPolling?10:50),c.debugMode||c.o._disableDebug(),c.enabled=!0}catch(e){return R(!0),G(),!1}G();l.remove(h,"load",c.beginDelayedInit);return!0};sa=function(){if(ja)return!1;Q();H();return ja=!0};A=function(){if(da)return!1;da=!0;pa();if(!c.useHTML5Audio&&!C())c.useHTML5Audio=!0;za();c.html5.usingFlash=ya();x=c.html5.usingFlash;da=!0;g.removeEventListener&&g.removeEventListener("DOMContentLoaded",
+A,!1);ba();return!0};wa=function(b){if(!b._hasTimer)b._hasTimer=!0};xa=function(b){if(b._hasTimer)b._hasTimer=!1};fa=function(){if(c.onerror instanceof Function)c.onerror();c.disable()};Aa=function(){if(!ma||!C())return!1;var b=c.audioFormats,a,e;for(e in b)if(b.hasOwnProperty(e)&&(e==="mp3"||e==="mp4"))if(c.html5[e]=!1,b[e]&&b[e].related)for(a=b[e].related.length;a--;)c.html5[b[e].related[a]]=!1};this._setSandboxType=function(){};this._externalInterfaceOK=function(){if(c.swfLoaded)return!1;(new Date).getTime();
+c.swfLoaded=!0;D=!1;ma&&Aa();q?setTimeout(O,100):O()};ka=function(){g.readyState==="complete"&&(A(),g.detachEvent("onreadystatechange",ka));return!0};if(!c.hasHTML5||x)l.add(h,"focus",v),l.add(h,"load",v),l.add(h,"load",P),L&&D&&l.add(h,"mousemove",v);g.addEventListener?g.addEventListener("DOMContentLoaded",A,!1):g.attachEvent?g.attachEvent("onreadystatechange",ka):fa();g.readyState==="complete"&&setTimeout(A,100)}var X=null;if(typeof SM2_DEFER==="undefined"||!SM2_DEFER)X=new M;Y.SoundManager=M;Y.soundManager=
+X})(window);
\ No newline at end of file
--- /dev/null
+/** @license\r
+ * SoundManager 2: JavaScript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code provided under the BSD License:\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * V2.97a.20110424\r
+ */\r
+\r
+/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */\r
+/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */\r
+\r
+(function(window) {\r
+\r
+var soundManager = null;\r
+\r
+function SoundManager(smURL, smID) {\r
+\r
+ this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9.\r
+ this.debugMode = true; // enable debugging output (div#soundmanager-debug, OR console if available+configured)\r
+ this.debugFlash = false; // enable debugging output inside SWF, troubleshoot Flash/browser issues\r
+ this.useConsole = true; // use firebug/safari console.log()-type debug console if available\r
+ this.consoleOnly = false; // if console is being used, do not create/write to #soundmanager-debug\r
+ this.waitForWindowLoad = false; // force SM2 to wait for window.onload() before trying to call soundManager.onload()\r
+ this.nullURL = 'about:blank'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)\r
+ this.allowPolling = true; // allow flash to poll for status update (required for whileplaying() events, peak, sound spectrum functions to work.)\r
+ this.useFastPolling = false; // uses lower flash timer interval for higher callback frequency, best combined with useHighPerformance\r
+ this.useMovieStar = true; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio formats (AAC, M4V, FLV, MOV etc.)\r
+ this.bgColor = '#ffffff'; // movie (.swf) background color, eg. '#000000'\r
+ this.useHighPerformance = false; // position:fixed flash movie can help increase js/flash speed, minimize lag\r
+ this.flashPollingInterval = null; // msec for polling interval. Defaults to 50 unless useFastPolling = true.\r
+ this.flashLoadTimeout = 1000; // msec to wait for flash movie to load before failing (0 = infinity)\r
+ this.wmode = null; // string: flash rendering mode - null, transparent, opaque (last two allow layering of HTML on top)\r
+ this.allowScriptAccess = 'always'; // for scripting the SWF (object/embed property), either 'always' or 'sameDomain'\r
+ this.useFlashBlock = false; // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.\r
+ this.useHTML5Audio = false; // Beta feature: Use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible.\r
+ this.html5Test = /^probably$/i; // HTML5 Audio().canPlayType() test. /^(probably|maybe)$/i if you want to be more liberal/risky.\r
+ this.useGlobalHTML5Audio = true; // (experimental) if true, re-use single HTML5 audio object across all sounds. Enabled by default on mobile devices/iOS.\r
+ this.requireFlash = false; // (experimental) if true, prevents "HTML5-only" mode when flash present. Allows flash to handle RTMP/serverURL, but HTML5 for other cases\r
+\r
+ this.audioFormats = {\r
+ // determines HTML5 support, flash requirements\r
+ // eg. if MP3 or MP4 required, Flash fallback is used if HTML5 can't play it\r
+ // shotgun approach to MIME testing due to browser variance\r
+ 'mp3': {\r
+ 'type': ['audio/mpeg; codecs="mp3"','audio/mpeg','audio/mp3','audio/MPA','audio/mpa-robust'],\r
+ 'required': true\r
+ },\r
+ 'mp4': {\r
+ 'related': ['aac','m4a'], // additional formats under the MP4 container\r
+ 'type': ['audio/mp4; codecs="mp4a.40.2"','audio/aac','audio/x-m4a','audio/MP4A-LATM','audio/mpeg4-generic'],\r
+ 'required': true\r
+ },\r
+ 'ogg': {\r
+ 'type': ['audio/ogg; codecs=vorbis'],\r
+ 'required': false\r
+ },\r
+ 'wav': {\r
+ 'type': ['audio/wav; codecs="1"','audio/wav','audio/wave','audio/x-wav'],\r
+ 'required': false\r
+ }\r
+ };\r
+\r
+ this.defaultOptions = {\r
+ 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)\r
+ 'stream': true, // allows playing before entire file has loaded (recommended)\r
+ 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)\r
+ 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)\r
+ 'onid3': null, // callback function for "ID3 data is added/available"\r
+ 'onload': null, // callback function for "load finished"\r
+ 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)\r
+ 'onplay': null, // callback for "play" start\r
+ 'onpause': null, // callback for "pause"\r
+ 'onresume': null, // callback for "resume" (pause toggle)\r
+ 'whileplaying': null, // callback during play (position update)\r
+ 'onstop': null, // callback for "user stop"\r
+ 'onfailure': null, // callback function for when playing fails\r
+ 'onfinish': null, // callback function for "sound finished playing"\r
+ 'onbeforefinish': null, // callback for "before sound finished playing (at [time])"\r
+ 'onbeforefinishtime': 5000, // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)\r
+ 'onbeforefinishcomplete': null,// function to call when said sound finishes playing\r
+ 'onjustbeforefinish': null, // callback for [n] msec before end of current sound\r
+ 'onjustbeforefinishtime': 200, // [n] - if not using, set to 0 (or null handler) and event will not fire.\r
+ 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time\r
+ 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled\r
+ 'position': null, // offset (milliseconds) to seek to within loaded sound data.\r
+ 'pan': 0, // "pan" settings, left-to-right, -100 to 100\r
+ 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3\r
+ 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)\r
+ 'volume': 100 // self-explanatory. 0-100, the latter being the max.\r
+ };\r
+\r
+ this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used\r
+ 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL\r
+ 'usePeakData': false, // enable left/right channel peak (level) data\r
+ 'useWaveformData': false, // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.\r
+ 'useEQData': false, // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.\r
+ 'onbufferchange': null, // callback for "isBuffering" property change\r
+ 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)\r
+ };\r
+\r
+ this.movieStarOptions = { // flash 9.0r115+ MPEG4 audio options, merged into defaultOptions if flash 9+movieStar mode is enabled\r
+ 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)\r
+ 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants\r
+ 'onconnect': null, // rtmp: callback for connection to flash media server\r
+ 'duration': null // rtmp: song duration (msec)\r
+ };\r
+\r
+ this.version = null;\r
+ this.versionNumber = 'V2.97a.20110424';\r
+ this.movieURL = null;\r
+ this.url = (smURL || null);\r
+ this.altURL = null;\r
+ this.swfLoaded = false;\r
+ this.enabled = false;\r
+ this.o = null;\r
+ this.movieID = 'sm2-container';\r
+ this.id = (smID || 'sm2movie');\r
+ this.swfCSS = {\r
+ 'swfBox': 'sm2-object-box',\r
+ 'swfDefault': 'movieContainer',\r
+ 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)\r
+ 'swfTimedout': 'swf_timedout',\r
+ 'swfLoaded': 'swf_loaded',\r
+ 'swfUnblocked': 'swf_unblocked', // or loaded OK\r
+ 'sm2Debug': 'sm2_debug',\r
+ 'highPerf': 'high_performance',\r
+ 'flashDebug': 'flash_debug'\r
+ };\r
+ this.oMC = null;\r
+ this.sounds = {};\r
+ this.soundIDs = [];\r
+ this.muted = false;\r
+ this.debugID = 'soundmanager-debug';\r
+ this.debugURLParam = /([#?&])debug=1/i;\r
+ this.specialWmodeCase = false;\r
+ this.didFlashBlock = false;\r
+\r
+ this.filePattern = null;\r
+ this.filePatterns = {\r
+ 'flash8': /\.mp3(\?.*)?$/i,\r
+ 'flash9': /\.mp3(\?.*)?$/i\r
+ };\r
+\r
+ this.baseMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3\r
+ this.netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3, mp4, aac etc.\r
+ this.netStreamTypes = ['aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2']; // Flash v9.0r115+ "moviestar" formats\r
+ this.netStreamPattern = new RegExp('\\.(' + this.netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+ this.mimePattern = this.baseMimeTypes;\r
+\r
+ this.features = {\r
+ 'buffering': false,\r
+ 'peakData': false,\r
+ 'waveformData': false,\r
+ 'eqData': false,\r
+ 'movieStar': false\r
+ };\r
+\r
+ this.sandbox = {\r
+ // <d>\r
+ 'type': null,\r
+ 'types': {\r
+ 'remote': 'remote (domain-based) rules',\r
+ 'localWithFile': 'local with file access (no internet access)',\r
+ 'localWithNetwork': 'local with network (internet access only, no local access)',\r
+ 'localTrusted': 'local, trusted (local+internet access)'\r
+ },\r
+ 'description': null,\r
+ 'noRemote': null,\r
+ 'noLocal': null\r
+ // </d>\r
+ };\r
+\r
+ this.hasHTML5 = null; // switch for handling logic\r
+ this.html5 = { // stores canPlayType() results, etc. treat as read-only.\r
+ // mp3: boolean\r
+ // mp4: boolean\r
+ 'usingFlash': null // set if/when flash fallback is needed\r
+ };\r
+ this.ignoreFlash = false; // used for special cases (eg. iPad/iPhone/palm OS?)\r
+\r
+ // --- private SM2 internals ---\r
+\r
+ var SMSound,\r
+ _s = this, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _fV = this.flashVersion, _doc = document, _doNothing, _init, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _addOnEvent, _processOnEvents, _initUserOnload, _go, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _beginInit, _strings, _initMovie, _dcLoaded, _didDCLoaded, _getDocument, _createMovie, _die, _setPolling, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _smTimer, _onTimer, _startTimer, _stopTimer, _needsFlash = null, _featureCheck, _html5OK, _html5Only = false, _html5CanPlay, _html5Ext, _dcIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix,\r
+ _is_pre = _ua.match(/pre\//i), _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isMobile = (_ua.match(/mobile/i) || _is_pre || _is_iDevice), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), \r
+ _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && _ua.match(/OS X 10_6_([3-9])/i)), // Safari 4 and 5 occasionally fail to load/play HTML5 audio on Snow Leopard due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Known Apple "radar" bug. https://bugs.webkit.org/show_bug.cgi?id=32159\r
+ _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (typeof _doc.hasFocus === 'undefined' && _isSafari), _okToDisable = !_tryInitOnFocus;\r
+\r
+ this._use_maybe = (_wl.match(/sm2\-useHTML5Maybe\=1/i)); // temporary feature: #sm2-useHTML5Maybe=1 forces loose canPlay() check\r
+ this._overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null);\r
+ this._http = (!this._overHTTP ? 'http:' : '');\r
+ this.useAltURL = !this._overHTTP; // use altURL if not "online"\r
+ this._global_a = null;\r
+\r
+ if (_is_iDevice || _is_pre) {\r
+ // during HTML5 beta period (off by default), may as well force it on Apple + Palm, flash support unlikely\r
+ _s.useHTML5Audio = true;\r
+ _s.ignoreFlash = true;\r
+ if (_s.useGlobalHTML5Audio) {\r
+ _useGlobalHTML5Audio = true;\r
+ }\r
+ }\r
+\r
+ if (_is_pre || this._use_maybe) {\r
+ // less-strict canPlayType() checking option\r
+ _s.html5Test = /^(probably|maybe)$/i;\r
+ }\r
+\r
+ // Temporary feature: allow force of HTML5 via URL: #sm2-usehtml5audio=0 or 1\r
+ // <d>\r
+ (function(){\r
+ var a = '#sm2-usehtml5audio=', l = _wl, b = null;\r
+ if (l.indexOf(a) !== -1) {\r
+ b = (l.charAt(l.indexOf(a)+a.length) === '1');\r
+ if (typeof console !== 'undefined' && typeof console.log !== 'undefined') {\r
+ console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter');\r
+ }\r
+ _s.useHTML5Audio = b;\r
+ }\r
+ }());\r
+ // </d>\r
+\r
+ // --- public API methods ---\r
+\r
+ this.ok = function() {\r
+ return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5));\r
+ };\r
+\r
+ this.supported = this.ok; // legacy\r
+\r
+ this.getMovie = function(smID) {\r
+ return _isIE?_win[smID]:(_isSafari?_id(smID) || _doc[smID]:_id(smID));\r
+ };\r
+\r
+ this.createSound = function(oOptions) {\r
+ var _cs = _sm+'.createSound(): ',\r
+ thisOptions = null, oSound = null, _tO = null;\r
+ if (!_didInit || !_s.ok()) {\r
+ _complain(_cs + _str(!_didInit?'notReady':'notOK'));\r
+ return false;\r
+ }\r
+ if (arguments.length === 2) {\r
+ // function overloading in JS! :) ..assume simple createSound(id,url) use case\r
+ oOptions = {\r
+ 'id': arguments[0],\r
+ 'url': arguments[1]\r
+ };\r
+ }\r
+ thisOptions = _mixin(oOptions); // inherit from defaultOptions\r
+ _tO = thisOptions; // alias\r
+ // <d>\r
+ if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) {\r
+ _s._wD(_cs + _str('badID', _tO.id), 2);\r
+ }\r
+ _s._wD(_cs + _tO.id + ' (' + _tO.url + ')', 1);\r
+ // </d>\r
+ if (_idCheck(_tO.id, true)) {\r
+ _s._wD(_cs + _tO.id + ' exists', 1);\r
+ return _s.sounds[_tO.id];\r
+ }\r
+\r
+ function make() {\r
+ thisOptions = _loopFix(thisOptions);\r
+ _s.sounds[_tO.id] = new SMSound(_tO);\r
+ _s.soundIDs.push(_tO.id);\r
+ return _s.sounds[_tO.id];\r
+ }\r
+\r
+ if (_html5OK(_tO)) {\r
+ oSound = make();\r
+ _s._wD('Loading sound '+_tO.id+' via HTML5');\r
+ oSound._setup_html5(_tO);\r
+ } else {\r
+ if (_fV > 8 && _s.useMovieStar) {\r
+ if (_tO.isMovieStar === null) {\r
+ _tO.isMovieStar = ((_tO.serverURL || (_tO.type?_tO.type.match(_s.netStreamPattern):false)||_tO.url.match(_s.netStreamPattern))?true:false);\r
+ }\r
+ if (_tO.isMovieStar) {\r
+ _s._wD(_cs + 'using MovieStar handling');\r
+ }\r
+ if (_tO.isMovieStar) {\r
+ if (_tO.usePeakData) {\r
+ _wDS('noPeak');\r
+ _tO.usePeakData = false;\r
+ }\r
+ if (_tO.loops > 1) {\r
+ _wDS('noNSLoop');\r
+ }\r
+ }\r
+ }\r
+ _tO = _policyFix(_tO, _cs);\r
+ oSound = make();\r
+ if (_fV === 8) {\r
+ _s.o._createSound(_tO.id, _tO.onjustbeforefinishtime, _tO.loops||1, _tO.usePolicyFile);\r
+ } else {\r
+ _s.o._createSound(_tO.id, _tO.url, _tO.onjustbeforefinishtime, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile);\r
+ if (!_tO.serverURL) {\r
+ // We are connected immediately\r
+ oSound.connected = true;\r
+ if (_tO.onconnect) {\r
+ _tO.onconnect.apply(oSound);\r
+ }\r
+ }\r
+ }\r
+\r
+ if ((_tO.autoLoad || _tO.autoPlay) && !_tO.serverURL) {\r
+ oSound.load(_tO); // call load for non-rtmp streams\r
+ }\r
+ }\r
+\r
+ if (_tO.autoPlay && !_tO.serverURL) { // rtmp will play in onconnect\r
+ oSound.play();\r
+ }\r
+ return oSound;\r
+ };\r
+\r
+ this.destroySound = function(sID, _bFromSound) {\r
+ // explicitly destroy a sound before normal page unload, etc.\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ var oS = _s.sounds[sID], i;\r
+ oS._iO = {}; // Disable all callbacks while the sound is being destroyed\r
+ oS.stop();\r
+ oS.unload();\r
+ for (i = 0; i < _s.soundIDs.length; i++) {\r
+ if (_s.soundIDs[i] === sID) {\r
+ _s.soundIDs.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+ if (!_bFromSound) {\r
+ // ignore if being called from SMSound instance\r
+ oS.destruct(true);\r
+ }\r
+ oS = null;\r
+ delete _s.sounds[sID];\r
+ return true;\r
+ };\r
+\r
+ this.load = function(sID, oOptions) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].load(oOptions);\r
+ };\r
+\r
+ this.unload = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].unload();\r
+ };\r
+\r
+ this.play = function(sID, oOptions) {\r
+ var fN = _sm+'.play(): ';\r
+ if (!_didInit || !_s.ok()) {\r
+ _complain(fN + _str(!_didInit?'notReady':'notOK'));\r
+ return false;\r
+ }\r
+ if (!_idCheck(sID)) {\r
+ if (!(oOptions instanceof Object)) {\r
+ oOptions = {\r
+ url: oOptions\r
+ }; // overloading use case: play('mySound','/path/to/some.mp3');\r
+ }\r
+ if (oOptions && oOptions.url) {\r
+ // overloading use case, create+play: .play('someID',{url:'/path/to.mp3'});\r
+ _s._wD(fN + 'attempting to create "' + sID + '"', 1);\r
+ oOptions.id = sID;\r
+ return _s.createSound(oOptions).play();\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+ return _s.sounds[sID].play(oOptions);\r
+ };\r
+\r
+ this.start = this.play; // just for convenience\r
+\r
+ this.setPosition = function(sID, nMsecOffset) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].setPosition(nMsecOffset);\r
+ };\r
+\r
+ this.stop = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ _s._wD(_sm+'.stop(' + sID + ')', 1);\r
+ return _s.sounds[sID].stop();\r
+ };\r
+\r
+ this.stopAll = function() {\r
+ _s._wD(_sm+'.stopAll()', 1);\r
+ for (var oSound in _s.sounds) {\r
+ if (_s.sounds[oSound] instanceof SMSound) {\r
+ _s.sounds[oSound].stop(); // apply only to sound objects\r
+ }\r
+ }\r
+ };\r
+\r
+ this.pause = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].pause();\r
+ };\r
+\r
+ this.pauseAll = function() {\r
+ for (var i = _s.soundIDs.length; i--;) {\r
+ _s.sounds[_s.soundIDs[i]].pause();\r
+ }\r
+ };\r
+\r
+ this.resume = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].resume();\r
+ };\r
+\r
+ this.resumeAll = function() {\r
+ for (var i = _s.soundIDs.length; i--;) {\r
+ _s.sounds[_s.soundIDs[i]].resume();\r
+ }\r
+ };\r
+\r
+ this.togglePause = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].togglePause();\r
+ };\r
+\r
+ this.setPan = function(sID, nPan) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].setPan(nPan);\r
+ };\r
+\r
+ this.setVolume = function(sID, nVol) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].setVolume(nVol);\r
+ };\r
+\r
+ this.mute = function(sID) {\r
+ var fN = _sm+'.mute(): ',\r
+ i = 0;\r
+ if (typeof sID !== 'string') {\r
+ sID = null;\r
+ }\r
+ if (!sID) {\r
+ _s._wD(fN + 'Muting all sounds');\r
+ for (i = _s.soundIDs.length; i--;) {\r
+ _s.sounds[_s.soundIDs[i]].mute();\r
+ }\r
+ _s.muted = true;\r
+ } else {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ _s._wD(fN + 'Muting "' + sID + '"');\r
+ return _s.sounds[sID].mute();\r
+ }\r
+ return true;\r
+ };\r
+\r
+ this.muteAll = function() {\r
+ _s.mute();\r
+ };\r
+\r
+ this.unmute = function(sID) {\r
+ var fN = _sm+'.unmute(): ', i;\r
+ if (typeof sID !== 'string') {\r
+ sID = null;\r
+ }\r
+ if (!sID) {\r
+ _s._wD(fN + 'Unmuting all sounds');\r
+ for (i = _s.soundIDs.length; i--;) {\r
+ _s.sounds[_s.soundIDs[i]].unmute();\r
+ }\r
+ _s.muted = false;\r
+ } else {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ _s._wD(fN + 'Unmuting "' + sID + '"');\r
+ return _s.sounds[sID].unmute();\r
+ }\r
+ return true;\r
+ };\r
+\r
+ this.unmuteAll = function() {\r
+ _s.unmute();\r
+ };\r
+\r
+ this.toggleMute = function(sID) {\r
+ if (!_idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return _s.sounds[sID].toggleMute();\r
+ };\r
+\r
+ this.getMemoryUse = function() {\r
+ if (_fV === 8) {\r
+ return 0;\r
+ }\r
+ if (_s.o) {\r
+ return parseInt(_s.o._getMemoryUse(), 10);\r
+ }\r
+ };\r
+\r
+ this.disable = function(bNoDisable) {\r
+ // destroy all functions\r
+ if (typeof bNoDisable === 'undefined') {\r
+ bNoDisable = false;\r
+ }\r
+ if (_disabled) {\r
+ return false;\r
+ }\r
+ _disabled = true;\r
+ _wDS('shutdown', 1);\r
+ for (var i = _s.soundIDs.length; i--;) {\r
+ _disableObject(_s.sounds[_s.soundIDs[i]]);\r
+ }\r
+ _initComplete(bNoDisable); // fire "complete", despite fail\r
+ _event.remove(_win, 'load', _initUserOnload);\r
+ return true;\r
+ };\r
+\r
+ this.canPlayMIME = function(sMIME) {\r
+ var result;\r
+ if (_s.hasHTML5) {\r
+ result = _html5CanPlay({type:sMIME});\r
+ }\r
+ if (!_needsFlash || result) {\r
+ // no flash, or OK\r
+ return result;\r
+ } else {\r
+ return (sMIME?(sMIME.match(_s.mimePattern)?true:false):null);\r
+ }\r
+ };\r
+\r
+ this.canPlayURL = function(sURL) {\r
+ var result;\r
+ if (_s.hasHTML5) {\r
+ result = _html5CanPlay(sURL);\r
+ }\r
+ if (!_needsFlash || result) {\r
+ // no flash, or OK\r
+ return result;\r
+ } else {\r
+ return (sURL?(sURL.match(_s.filePattern)?true:false):null);\r
+ }\r
+ };\r
+\r
+ this.canPlayLink = function(oLink) {\r
+ if (typeof oLink.type !== 'undefined' && oLink.type) {\r
+ if (_s.canPlayMIME(oLink.type)) {\r
+ return true;\r
+ }\r
+ }\r
+ return _s.canPlayURL(oLink.href);\r
+ };\r
+\r
+ this.getSoundById = function(sID, suppressDebug) {\r
+ if (!sID) {\r
+ throw new Error(_sm+'.getSoundById(): sID is null/undefined');\r
+ }\r
+ var result = _s.sounds[sID];\r
+ if (!result && !suppressDebug) {\r
+ _s._wD('"' + sID + '" is an invalid sound ID.', 2);\r
+ }\r
+ return result;\r
+ };\r
+\r
+ this.onready = function(oMethod, oScope) {\r
+ var sType = 'onready';\r
+ if (oMethod && oMethod instanceof Function) {\r
+ if (_didInit) {\r
+ _wDS('queue', sType);\r
+ }\r
+ if (!oScope) {\r
+ oScope = _win;\r
+ }\r
+ _addOnEvent(sType, oMethod, oScope);\r
+ _processOnEvents();\r
+ return true;\r
+ } else {\r
+ throw _str('needFunction', sType);\r
+ }\r
+ };\r
+\r
+ this.ontimeout = function(oMethod, oScope) {\r
+ var sType = 'ontimeout';\r
+ if (oMethod && oMethod instanceof Function) {\r
+ if (_didInit) {\r
+ _wDS('queue');\r
+ }\r
+ if (!oScope) {\r
+ oScope = _win;\r
+ }\r
+ _addOnEvent(sType, oMethod, oScope);\r
+ _processOnEvents({type:sType});\r
+ return true;\r
+ } else {\r
+ throw _str('needFunction', sType);\r
+ }\r
+ };\r
+\r
+ this.getMoviePercent = function() {\r
+ return (_s.o && typeof _s.o.PercentLoaded !== 'undefined'?_s.o.PercentLoaded():null);\r
+ };\r
+\r
+ this._writeDebug = function(sText, sType, bTimestamp) {\r
+ // pseudo-private console.log()-style output\r
+ // <d>\r
+ var sDID = 'soundmanager-debug', o, oItem, sMethod;\r
+ if (!_s.debugMode) {\r
+ return false;\r
+ }\r
+ if (typeof bTimestamp !== 'undefined' && bTimestamp) {\r
+ sText = sText + ' | ' + new Date().getTime();\r
+ }\r
+ if (_hasConsole && _s.useConsole) {\r
+ sMethod = _debugLevels[sType];\r
+ if (typeof console[sMethod] !== 'undefined') {\r
+ console[sMethod](sText);\r
+ } else {\r
+ console.log(sText);\r
+ }\r
+ if (_s.useConsoleOnly) {\r
+ return true;\r
+ }\r
+ }\r
+ try {\r
+ o = _id(sDID);\r
+ if (!o) {\r
+ return false;\r
+ }\r
+ oItem = _doc.createElement('div');\r
+ if (++_wdCount % 2 === 0) {\r
+ oItem.className = 'sm2-alt';\r
+ }\r
+ if (typeof sType === 'undefined') {\r
+ sType = 0;\r
+ } else {\r
+ sType = parseInt(sType, 10);\r
+ }\r
+ oItem.appendChild(_doc.createTextNode(sText));\r
+ if (sType) {\r
+ if (sType >= 2) {\r
+ oItem.style.fontWeight = 'bold';\r
+ }\r
+ if (sType === 3) {\r
+ oItem.style.color = '#ff3333';\r
+ }\r
+ }\r
+ // o.appendChild(oItem); // top-to-bottom\r
+ o.insertBefore(oItem, o.firstChild); // bottom-to-top\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+ o = null;\r
+ // </d>\r
+ return true;\r
+ };\r
+ this._wD = this._writeDebug; // alias\r
+\r
+ this._debug = function() {\r
+ // <d>\r
+ _wDS('currentObj', 1);\r
+ for (var i = 0, j = _s.soundIDs.length; i < j; i++) {\r
+ _s.sounds[_s.soundIDs[i]]._debug();\r
+ }\r
+ // </d>\r
+ };\r
+\r
+ this.reboot = function() {\r
+ // attempt to reset and init SM2\r
+ _s._wD(_sm+'.reboot()');\r
+ if (_s.soundIDs.length) {\r
+ _s._wD('Destroying ' + _s.soundIDs.length + ' SMSound objects...');\r
+ }\r
+ var i, j;\r
+ for (i = _s.soundIDs.length; i--;) {\r
+ _s.sounds[_s.soundIDs[i]].destruct();\r
+ }\r
+ // trash ze flash\r
+ try {\r
+ if (_isIE) {\r
+ _oRemovedHTML = _s.o.innerHTML;\r
+ }\r
+ _oRemoved = _s.o.parentNode.removeChild(_s.o);\r
+ _s._wD('Flash movie removed.');\r
+ } catch(e) {\r
+ // uh-oh.\r
+ _wDS('badRemove', 2);\r
+ }\r
+ // actually, force recreate of movie.\r
+ _oRemovedHTML = _oRemoved = null;\r
+ _s.enabled = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false;\r
+ _s.soundIDs = _s.sounds = [];\r
+ _s.o = null;\r
+ for (i in _on_queue) {\r
+ if (_on_queue.hasOwnProperty(i)) {\r
+ for (j = _on_queue[i].length; j--;) {\r
+ _on_queue[i][j].fired = false;\r
+ }\r
+ }\r
+ }\r
+ _s._wD(_sm + ': Rebooting...');\r
+ _win.setTimeout(function() {\r
+ _s.beginDelayedInit();\r
+ }, 20);\r
+ };\r
+\r
+ this.destruct = function() {\r
+ _s._wD(_sm+'.destruct()');\r
+ _s.disable(true);\r
+ };\r
+\r
+ this.beginDelayedInit = function() {\r
+ // _s._wD(_sm+'.beginDelayedInit()');\r
+ _windowLoaded = true;\r
+ _dcLoaded();\r
+ setTimeout(_beginInit, 20);\r
+ _delayWaitForEI();\r
+ };\r
+\r
+\r
+ // Wrap html5 event handlers so we don't call them on destroyed sounds\r
+ function _html5_event(oFn) {\r
+ return function(e) {\r
+ if (!this._t || !this._t._a) {\r
+ if (this._t && this._t.sID) {\r
+ _s._wD(_h5+'ignoring '+e.type+': '+this._t.sID);\r
+ } else {\r
+ _s._wD(_h5+'ignoring '+e.type);\r
+ }\r
+ return null;\r
+ } else {\r
+ return oFn.call(this, e);\r
+ }\r
+ };\r
+ }\r
+\r
+ this._html5_events = {\r
+\r
+ // HTML5 event-name-to-handler map\r
+ abort: _html5_event(function(e) {\r
+ _s._wD(_h5+'abort: '+this._t.sID);\r
+ }),\r
+\r
+ // enough has loaded to play\r
+ canplay: _html5_event(function(e) {\r
+ _s._wD(_h5+'canplay: '+this._t.sID+', '+this._t.url);\r
+ this._t._onbufferchange(0);\r
+ var position1K = (!isNaN(this._t.position)?this._t.position/1000:null);\r
+ // set the position if position was set before the sound loaded\r
+ this._t._html5_canplay = true;\r
+ if (this._t.position && this.currentTime !== position1K) {\r
+ _s._wD(_h5+'canplay: setting position to '+position1K+'');\r
+ try {\r
+ this.currentTime = position1K;\r
+ } catch(ee) {\r
+ _s._wD(_h5+'setting position failed: '+ee.message, 2);\r
+ }\r
+ }\r
+ }),\r
+\r
+ load: _html5_event(function(e) {\r
+ if (!this._t.loaded) {\r
+ this._t._onbufferchange(0);\r
+ // should be 1, and the same\r
+ this._t._whileloading(this._t.bytesTotal, this._t.bytesTotal, this._t._get_html5_duration());\r
+ this._t._onload(true);\r
+ }\r
+ }),\r
+\r
+ emptied: _html5_event(function(e) {\r
+ _s._wD(_h5+'emptied: '+this._t.sID);\r
+ }),\r
+\r
+ ended: _html5_event(function(e) {\r
+ _s._wD(_h5+'ended: '+this._t.sID);\r
+ this._t._onfinish();\r
+ }),\r
+\r
+ error: _html5_event(function(e) {\r
+ _s._wD(_h5+'error: '+this.error.code);\r
+ // call load with error state?\r
+ this._t._onload(false);\r
+ }),\r
+\r
+ loadeddata: _html5_event(function(e) {\r
+ _s._wD(_h5+'loadeddata: '+this._t.sID);\r
+ }),\r
+\r
+ loadedmetadata: _html5_event(function(e) {\r
+ _s._wD(_h5+'loadedmetadata: '+this._t.sID);\r
+ }),\r
+\r
+ loadstart: _html5_event(function(e) {\r
+ _s._wD(_h5+'loadstart: '+this._t.sID);\r
+ // assume buffering at first\r
+ this._t._onbufferchange(1);\r
+ }),\r
+\r
+ play: _html5_event(function(e) {\r
+ _s._wD(_h5+'play: '+this._t.sID+', '+this._t.url);\r
+ // once play starts, no buffering\r
+ this._t._onbufferchange(0);\r
+ }),\r
+\r
+ // TODO: verify if this is actually implemented anywhere yet.\r
+ playing: _html5_event(function(e) {\r
+ _s._wD(_h5+'playing: '+this._t.sID+', '+this._t.url);\r
+ // once play starts, no buffering\r
+ this._t._onbufferchange(0);\r
+ }),\r
+\r
+ progress: _html5_event(function(e) {\r
+\r
+ if (this._t.loaded) {\r
+ return false;\r
+ }\r
+\r
+ var i, j, str, loadSum = 0, buffered = 0,\r
+ isProgress = (e.type === 'progress'),\r
+ ranges = e.target.buffered,\r
+ loaded = (e.loaded||0), // firefox 3.6 implements e.loaded/total (bytes)\r
+ total = (e.total||1);\r
+\r
+ if (ranges && ranges.length) {\r
+\r
+ // if loaded is 0, try TimeRanges implementation as % of load\r
+ // https://developer.mozilla.org/en/DOM/TimeRanges\r
+ for (i=ranges.length; i--;) {\r
+ buffered = (ranges.end(i) - ranges.start(i));\r
+ }\r
+\r
+ // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges\r
+ loaded = buffered/e.target.duration;\r
+\r
+ // <d>\r
+ if (isProgress && ranges.length > 1) {\r
+ str = [];\r
+ j = ranges.length;\r
+ for (i=0; i<j; i++) {\r
+ str.push(e.target.buffered.start(i) +'-'+ e.target.buffered.end(i));\r
+ }\r
+ _s._wD(_h5+'progress: timeRanges: '+str.join(', '));\r
+ }\r
+ // </d>\r
+\r
+ if (isProgress && !isNaN(loaded)) {\r
+ _s._wD(_h5+'progress: '+this._t.sID+': ' + Math.floor(loaded*100)+'% loaded');\r
+ }\r
+\r
+ }\r
+\r
+ if (!isNaN(loaded)) {\r
+\r
+ this._t._onbufferchange(0); // if progress, likely not buffering\r
+ this._t._whileloading(loaded, total, this._t._get_html5_duration());\r
+\r
+ if (loaded && total && loaded === total) {\r
+ // in case "onload" doesn't fire (eg. gecko 1.9.2)\r
+ _s._html5_events.load.call(this, e);\r
+ }\r
+\r
+ }\r
+\r
+ }),\r
+\r
+ ratechange: _html5_event(function(e) {\r
+ _s._wD(_h5+'ratechange: '+this._t.sID);\r
+ }),\r
+\r
+ suspend: _html5_event(function(e) {\r
+ // download paused/stopped, may have finished (eg. onload)\r
+ _s._wD(_h5+'suspend: '+this._t.sID);\r
+ _s._html5_events.progress.call(this, e);\r
+ }),\r
+\r
+ stalled: _html5_event(function(e) {\r
+ _s._wD(_h5+'stalled: '+this._t.sID);\r
+ }),\r
+\r
+ timeupdate: _html5_event(function(e) {\r
+ this._t._onTimer();\r
+ }),\r
+\r
+ waiting: _html5_event(function(e) { // see also: seeking\r
+ _s._wD(_h5+'waiting: '+this._t.sID);\r
+ // playback faster than download rate, etc.\r
+ this._t._onbufferchange(1);\r
+ })\r
+\r
+ };\r
+\r
+ // --- SMSound (sound object) instance ---\r
+\r
+ SMSound = function(oOptions) {\r
+ var _t = this, _resetProperties, _stop_html5_timer, _start_html5_timer;\r
+ this.sID = oOptions.id;\r
+ this.url = oOptions.url;\r
+ this.options = _mixin(oOptions);\r
+ this.instanceOptions = this.options; // per-play-instance-specific options\r
+ this._iO = this.instanceOptions; // short alias\r
+ // assign property defaults\r
+ this.pan = this.options.pan;\r
+ this.volume = this.options.volume;\r
+ this._lastURL = null;\r
+ this.isHTML5 = false;\r
+ this._a = null;\r
+\r
+ // --- public methods ---\r
+\r
+ this.id3 = {};\r
+\r
+ this._debug = function() {\r
+ // <d>\r
+ // pseudo-private console.log()-style output\r
+ if (_s.debugMode) {\r
+ var stuff = null, msg = [], sF, sfBracket, maxLength = 64;\r
+ for (stuff in _t.options) {\r
+ if (_t.options[stuff] !== null) {\r
+ if (_t.options[stuff] instanceof Function) {\r
+ // handle functions specially\r
+ sF = _t.options[stuff].toString();\r
+ sF = sF.replace(/\s\s+/g, ' '); // normalize spaces\r
+ sfBracket = sF.indexOf('{');\r
+ msg.push(' ' + stuff + ': {' + sF.substr(sfBracket + 1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '') + '... }');\r
+ } else {\r
+ msg.push(' ' + stuff + ': ' + _t.options[stuff]);\r
+ }\r
+ }\r
+ }\r
+ _s._wD('SMSound() merged options: {\n' + msg.join(', \n') + '\n}');\r
+ }\r
+ // </d>\r
+ };\r
+\r
+ this._debug();\r
+\r
+ this.load = function(oOptions) {\r
+ var oS = null;\r
+ if (typeof oOptions !== 'undefined') {\r
+ _t._iO = _mixin(oOptions, _t.options);\r
+ _t.instanceOptions = _t._iO;\r
+ } else {\r
+ oOptions = _t.options;\r
+ _t._iO = oOptions;\r
+ _t.instanceOptions = _t._iO;\r
+ if (_t._lastURL && _t._lastURL !== _t.url) {\r
+ _wDS('manURL');\r
+ _t._iO.url = _t.url;\r
+ _t.url = null;\r
+ }\r
+ }\r
+ if (!_t._iO.url) {\r
+ _t._iO.url = _t.url;\r
+ }\r
+ _s._wD('SMSound.load(): ' + _t._iO.url, 1);\r
+ if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) {\r
+ _wDS('onURL', 1);\r
+ return _t;\r
+ }\r
+ _t._lastURL = _t.url;\r
+ _t.loaded = false;\r
+ _t.readyState = 1;\r
+ _t.playState = 0;\r
+ if (_html5OK(_t._iO)) {\r
+ oS = _t._setup_html5(_t._iO);\r
+ if (!oS._called_load) {\r
+ _s._wD(_h5+'load: '+_t.sID);\r
+ oS.load();\r
+ oS._called_load = true;\r
+ if (_t._iO.autoPlay) {\r
+ _t.play();\r
+ }\r
+ } else {\r
+ _s._wD('HTML5 ignoring request to load again: '+_t.sID);\r
+ }\r
+ } else {\r
+ try {\r
+ _t.isHTML5 = false;\r
+ _t._iO = _policyFix(_loopFix(_t._iO));\r
+ if (_fV === 8) {\r
+ _s.o._load(_t.sID, _t._iO.url, _t._iO.stream, _t._iO.autoPlay, (_t._iO.whileloading?1:0), _t._iO.loops||1, _t._iO.usePolicyFile);\r
+ } else {\r
+ _s.o._load(_t.sID, _t._iO.url, _t._iO.stream?true:false, _t._iO.autoPlay?true:false, _t._iO.loops||1, _t._iO.autoLoad?true:false, _t._iO.usePolicyFile);\r
+ }\r
+ } catch(e) {\r
+ _wDS('smError', 2);\r
+ _debugTS('onload', false);\r
+ _die();\r
+ }\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.unload = function() {\r
+ // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3\r
+ // Flash 9/AS3: Close stream, preventing further load\r
+ if (_t.readyState !== 0) {\r
+ _s._wD('SMSound.unload(): "' + _t.sID + '"');\r
+ if (!_t.isHTML5) {\r
+ if (_fV === 8) {\r
+ _s.o._unload(_t.sID, _s.nullURL);\r
+ } else {\r
+ _s.o._unload(_t.sID);\r
+ }\r
+ } else {\r
+ _stop_html5_timer();\r
+ if (_t._a) {\r
+ // abort()-style method here, stop loading? (doesn't exist?)\r
+ _t._a.pause();\r
+// if (!_useGlobalHTML5Audio || (_useGlobalHTML5Audio && _t.playState)) { // if global audio, only unload if actively playing\r
+ _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
+// }\r
+ }\r
+ }\r
+ // reset load/status flags\r
+ _resetProperties();\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.destruct = function(_bFromSM) {\r
+ _s._wD('SMSound.destruct(): "' + _t.sID + '"');\r
+ if (!_t.isHTML5) {\r
+ // kill sound within Flash\r
+ // Disable the onfailure handler\r
+ _t._iO.onfailure = null;\r
+ _s.o._destroySound(_t.sID);\r
+ } else {\r
+ _stop_html5_timer();\r
+ if (_t._a) {\r
+ // abort()-style method here, stop loading? (doesn't exist?)\r
+ _t._a.pause();\r
+ _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
+ if (!_useGlobalHTML5Audio) {\r
+ _t._remove_html5_events();\r
+ }\r
+ }\r
+ }\r
+ if (!_bFromSM) {\r
+ _s.destroySound(_t.sID, true); // ensure deletion from controller\r
+ }\r
+ };\r
+\r
+ this.play = function(oOptions, _updatePlayState) {\r
+ var fN = 'SMSound.play(): ', allowMulti;\r
+ _updatePlayState = _updatePlayState === undefined ? true : _updatePlayState; // default true\r
+ if (!oOptions) {\r
+ oOptions = {};\r
+ }\r
+ _t._iO = _mixin(oOptions, _t._iO);\r
+ _t._iO = _mixin(_t._iO, _t.options);\r
+ _t.instanceOptions = _t._iO;\r
+ if (_t._iO.serverURL) {\r
+ if (!_t.connected) {\r
+ if (!_t.getAutoPlay()) {\r
+ _s._wD(fN+' Netstream not connected yet - setting autoPlay');\r
+ _t.setAutoPlay(true);\r
+ }\r
+ return _t; // play will be called in _onconnect()\r
+ }\r
+ }\r
+ if (_html5OK(_t._iO)) {\r
+ _t._setup_html5(_t._iO);\r
+ _start_html5_timer();\r
+ }\r
+ if (_t.playState === 1 && !_t.paused) {\r
+ allowMulti = _t._iO.multiShot;\r
+ if (!allowMulti) {\r
+ _s._wD(fN + '"' + _t.sID + '" already playing (one-shot)', 1);\r
+ return _t;\r
+ } else {\r
+ _s._wD(fN + '"' + _t.sID + '" already playing (multi-shot)', 1);\r
+ if (_t.isHTML5) {\r
+ // TODO: BUG?\r
+ _t.setPosition(_t._iO.position);\r
+ }\r
+ }\r
+ }\r
+ if (!_t.loaded) {\r
+ if (_t.readyState === 0) {\r
+ _s._wD(fN + 'Attempting to load "' + _t.sID + '"', 1);\r
+ // try to get this sound playing ASAP\r
+ if (!_t.isHTML5) {\r
+ _t._iO.autoPlay = true; // assign directly because setAutoPlay() increments the instanceCount\r
+ _t.load(_t._iO);\r
+ } else {\r
+ _t.load(_t._iO);\r
+ // _t.readyState = 1; // redundant\r
+ }\r
+ } else if (_t.readyState === 2) {\r
+ _s._wD(fN + 'Could not load "' + _t.sID + '" - exiting', 2);\r
+ return _t;\r
+ } else {\r
+ _s._wD(fN + '"' + _t.sID + '" is loading - attempting to play..', 1);\r
+ }\r
+ } else {\r
+ _s._wD(fN + '"' + _t.sID + '"');\r
+ }\r
+ // Streams will pause when their buffer is full if they are being loaded.\r
+ // In this case paused is true, but the song hasn't started playing yet. If\r
+ // we just call resume() the onplay() callback will never be called. So\r
+ // only call resume() if the position is > 0.\r
+ // Another reason is because options like volume won't have been applied yet.\r
+ if (_t.paused && _t.position && _t.position > 0) { // https://gist.github.com/37b17df75cc4d7a90bf6\r
+ _s._wD(fN + '"' + _t.sID + '" is resuming from paused state',1);\r
+ _t.resume();\r
+ } else {\r
+ _s._wD(fN+'"'+ _t.sID+'" is starting to play');\r
+ _t.playState = 1;\r
+ _t.paused = false;\r
+ if (!_t.instanceCount || _t._iO.multiShotEvents || (_fV > 8 && !_t.isHTML5 && !_t.getAutoPlay())) {\r
+ _t.instanceCount++;\r
+ }\r
+ _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);\r
+ if (!_t.isHTML5) {\r
+ _t._iO = _policyFix(_loopFix(_t._iO));\r
+ }\r
+ if (_t._iO.onplay && _updatePlayState) {\r
+ _t._iO.onplay.apply(_t);\r
+ _t._onplay_called = true;\r
+ }\r
+ _t.setVolume(_t._iO.volume, true);\r
+ _t.setPan(_t._iO.pan, true);\r
+ if (!_t.isHTML5) {\r
+ _s.o._start(_t.sID, _t._iO.loops || 1, (_fV === 9?_t.position:_t.position / 1000));\r
+ } else {\r
+ _start_html5_timer();\r
+ _t._setup_html5().play();\r
+ }\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.start = this.play; // just for convenience\r
+\r
+ this.stop = function(bAll) {\r
+ if (_t.playState === 1) {\r
+ _t._onbufferchange(0);\r
+ _t.resetOnPosition(0);\r
+ if (!_t.isHTML5) {\r
+ _t.playState = 0;\r
+ }\r
+ _t.paused = false;\r
+ if (_t._iO.onstop) {\r
+ _t._iO.onstop.apply(_t);\r
+ }\r
+ if (!_t.isHTML5) {\r
+ _s.o._stop(_t.sID, bAll);\r
+ // hack for netStream: just unload\r
+ if (_t._iO.serverURL) {\r
+ _t.unload();\r
+ }\r
+ } else {\r
+ if (_t._a) {\r
+ _t.setPosition(0); // act like Flash, though\r
+ _t._a.pause(); // html5 has no stop()\r
+ _t.playState = 0;\r
+ _t._onTimer(); // and update UI\r
+ _stop_html5_timer();\r
+ _t.unload();\r
+ }\r
+ }\r
+ _t.instanceCount = 0;\r
+ _t._iO = {};\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.setAutoPlay = function(autoPlay) {\r
+ _s._wD('sound '+_t.sID+' turned autoplay ' + (autoPlay ? 'on' : 'off'));\r
+ _t._iO.autoPlay = autoPlay;\r
+ if (_t.isHTML5) {\r
+ if (_t._a && autoPlay) {\r
+ _t.play(); // HTML5 onload isn't reliable\r
+ }\r
+ } else {\r
+ _s.o._setAutoPlay(_t.sID, autoPlay);\r
+ }\r
+ if (autoPlay) {\r
+ // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP)\r
+ if (!_t.instanceCount && _t.readyState === 1) {\r
+ _t.instanceCount++;\r
+ _s._wD('sound '+_t.sID+' incremented instance count to '+_t.instanceCount);\r
+ }\r
+ }\r
+ };\r
+\r
+ this.getAutoPlay = function() {\r
+ return _t._iO.autoPlay;\r
+ };\r
+\r
+ this.setPosition = function(nMsecOffset, bNoDebug) {\r
+ if (nMsecOffset === undefined) {\r
+ nMsecOffset = 0;\r
+ }\r
+ // Use the duration from the instance options, if we don't have a track duration yet.\r
+ var original_pos, position, position1K, offset = (_t.isHTML5 ? Math.max(nMsecOffset,0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); // position >= 0 and <= current available (loaded) duration\r
+ original_pos = _t.position;\r
+ _t.position = offset;\r
+ position1K = _t.position/1000;\r
+ _t.resetOnPosition(_t.position);\r
+ _t._iO.position = offset;\r
+ if (!_t.isHTML5) {\r
+ position = _fV === 9 ? _t.position : position1K;\r
+ if (_t.readyState && _t.readyState !== 2) {\r
+ _s.o._setPosition(_t.sID, position, (_t.paused || !_t.playState)); // if paused or not playing, will not resume (by playing)\r
+ }\r
+ } else if (_t._a) {\r
+ // Set the position in the canplay handler if the sound is not ready yet\r
+ if (_t._html5_canplay) {\r
+ if (_t._a.currentTime !== position1K) {\r
+ // Only set the position if we need to.\r
+ // DOM/JS errors/exceptions to watch out for:\r
+ // if seek is beyond (loaded?) position, "DOM exception 11"\r
+ // "INDEX_SIZE_ERR": DOM exception 1\r
+ _s._wD('setPosition('+position1K+'): setting position');\r
+ try {\r
+ _t._a.currentTime = position1K;\r
+ } catch(e) {\r
+ _s._wD('setPosition('+position1K+'): setting position failed: '+e.message, 2);\r
+ }\r
+ }\r
+ } else {\r
+ _s._wD('setPosition('+position1K+'): delaying, sound not ready');\r
+ }\r
+ }\r
+ if (_t.isHTML5) {\r
+ if (_t.paused) { // if paused, refresh UI right away\r
+ _t._onTimer(true); // force update\r
+ }\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.pause = function(bCallFlash) {\r
+ if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) {\r
+ return _t;\r
+ }\r
+ _s._wD('SMSound.pause()');\r
+ _t.paused = true;\r
+ if (!_t.isHTML5) {\r
+ if (bCallFlash || bCallFlash === undefined) {\r
+ _s.o._pause(_t.sID);\r
+ }\r
+ } else {\r
+ _t._setup_html5().pause();\r
+ _stop_html5_timer();\r
+ }\r
+ if (_t._iO.onpause) {\r
+ _t._iO.onpause.apply(_t);\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ // When auto-loaded streams pause on buffer full they have a playState of 0.\r
+ // We need to make sure that the playState is set to 1 when these streams "resume".\r
+ //\r
+ // When a paused stream is resumed, we need to trigger the onplay() callback if it\r
+ // hasn't been called already. In this case since the sound is being played for the\r
+ // first time, I think it's more appropriate to call onplay() rather than onresume().\r
+ this.resume = function() {\r
+ if (!_t.paused) {\r
+ return _t;\r
+ }\r
+ _s._wD('SMSound.resume()');\r
+ _t.paused = false;\r
+ _t.playState = 1;\r
+ if (!_t.isHTML5) {\r
+ if (_t._iO.isMovieStar) {\r
+ // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.\r
+ _t.setPosition(_t.position);\r
+ }\r
+ _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)\r
+ } else {\r
+ _t._setup_html5().play();\r
+ _start_html5_timer();\r
+ }\r
+ if (!_t._onplay_called && _t._iO.onplay) {\r
+ _t._iO.onplay.apply(_t);\r
+ _t._onplay_called = true;\r
+ } else if (_t._iO.onresume) {\r
+ _t._iO.onresume.apply(_t);\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.togglePause = function() {\r
+ _s._wD('SMSound.togglePause()');\r
+ if (_t.playState === 0) {\r
+ _t.play({\r
+ position: (_fV === 9 && !_t.isHTML5 ? _t.position:_t.position / 1000)\r
+ });\r
+ return _t;\r
+ }\r
+ if (_t.paused) {\r
+ _t.resume();\r
+ } else {\r
+ _t.pause();\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.setPan = function(nPan, bInstanceOnly) {\r
+ if (typeof nPan === 'undefined') {\r
+ nPan = 0;\r
+ }\r
+ if (typeof bInstanceOnly === 'undefined') {\r
+ bInstanceOnly = false;\r
+ }\r
+ if (!_t.isHTML5) {\r
+ _s.o._setPan(_t.sID, nPan);\r
+ } // else { no HTML5 pan? }\r
+ _t._iO.pan = nPan;\r
+ if (!bInstanceOnly) {\r
+ _t.pan = nPan;\r
+ _t.options.pan = nPan;\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.setVolume = function(nVol, bInstanceOnly) {\r
+ if (typeof nVol === 'undefined') {\r
+ nVol = 100;\r
+ }\r
+ if (typeof bInstanceOnly === 'undefined') {\r
+ bInstanceOnly = false;\r
+ }\r
+ if (!_t.isHTML5) {\r
+ _s.o._setVolume(_t.sID, (_s.muted && !_t.muted) || _t.muted?0:nVol);\r
+ } else if (_t._a) {\r
+ _t._a.volume = Math.max(0, Math.min(1, nVol/100)); // valid range: 0-1\r
+ }\r
+ _t._iO.volume = nVol;\r
+ if (!bInstanceOnly) {\r
+ _t.volume = nVol;\r
+ _t.options.volume = nVol;\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.mute = function() {\r
+ _t.muted = true;\r
+ if (!_t.isHTML5) {\r
+ _s.o._setVolume(_t.sID, 0);\r
+ } else if (_t._a) {\r
+ _t._a.muted = true;\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.unmute = function() {\r
+ _t.muted = false;\r
+ var hasIO = typeof _t._iO.volume !== 'undefined';\r
+ if (!_t.isHTML5) {\r
+ _s.o._setVolume(_t.sID, hasIO?_t._iO.volume:_t.options.volume);\r
+ } else if (_t._a) {\r
+ _t._a.muted = false;\r
+ }\r
+ return _t;\r
+ };\r
+\r
+ this.toggleMute = function() {\r
+ return (_t.muted?_t.unmute():_t.mute());\r
+ };\r
+\r
+ this.onposition = function(nPosition, oMethod, oScope) {\r
+ // TODO: allow for ranges, too? eg. (nPosition instanceof Array)\r
+ _t._onPositionItems.push({\r
+ position: nPosition,\r
+ method: oMethod,\r
+ scope: (typeof oScope !== 'undefined'?oScope:_t),\r
+ fired: false\r
+ });\r
+ return _t;\r
+ };\r
+\r
+ this.processOnPosition = function() {\r
+ var i, item, j = _t._onPositionItems.length;\r
+ if (!j || !_t.playState || _t._onPositionFired >= j) {\r
+ return false;\r
+ }\r
+ for (i=j; i--;) {\r
+ item = _t._onPositionItems[i];\r
+ if (!item.fired && _t.position >= item.position) {\r
+ item.method.apply(item.scope,[item.position]);\r
+ item.fired = true;\r
+ _s._onPositionFired++;\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+\r
+ this.resetOnPosition = function(nPosition) {\r
+ // reset "fired" for items interested in this position\r
+ var i, item, j = _t._onPositionItems.length;\r
+ if (!j) {\r
+ return false;\r
+ }\r
+ for (i=j; i--;) {\r
+ item = _t._onPositionItems[i];\r
+ if (item.fired && nPosition <= item.position) {\r
+ item.fired = false;\r
+ _s._onPositionFired--;\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+\r
+ // pseudo-private soundManager reference\r
+\r
+ this._onTimer = function(bForce) {\r
+ // HTML5-only _whileplaying() etc.\r
+ var time, x = {};\r
+ if (_t._hasTimer || bForce) {\r
+ if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { // TODO: May not need to track readyState (1 = loading)\r
+ _t.duration = _t._get_html5_duration();\r
+ _t.durationEstimate = _t.duration;\r
+ time = _t._a.currentTime?_t._a.currentTime*1000:0;\r
+ _t._whileplaying(time,x,x,x,x);\r
+ return true;\r
+ } else {\r
+ _s._wD('_onTimer: Warn for "'+_t.sID+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK'));\r
+ return false;\r
+ }\r
+ }\r
+ };\r
+\r
+ // --- private internals ---\r
+\r
+ this._get_html5_duration = function() {\r
+ var d = (_t._a ? _t._a.duration*1000 : (_t._iO ? _t._iO.duration : undefined));\r
+ return (d && !isNaN(d) && d !== Infinity ? d : (_t._iO ? _t._iO.duration : null));\r
+ };\r
+\r
+ _start_html5_timer = function() {\r
+ if (_t.isHTML5) {\r
+ _startTimer(_t);\r
+ }\r
+ };\r
+\r
+ _stop_html5_timer = function() {\r
+ if (_t.isHTML5) {\r
+ _stopTimer(_t);\r
+ }\r
+ };\r
+\r
+ _resetProperties = function(bLoaded) {\r
+ _t._onPositionItems = [];\r
+ _t._onPositionFired = 0;\r
+ _t._hasTimer = null;\r
+ _t._onplay_called = false;\r
+ _t._a = null;\r
+ _t._html5_canplay = false;\r
+ _t.bytesLoaded = null;\r
+ _t.bytesTotal = null;\r
+ _t.position = null;\r
+ _t.duration = (_t._iO && _t._iO.duration?_t._iO.duration:null);\r
+ _t.durationEstimate = null;\r
+ _t.failures = 0;\r
+ _t.loaded = false;\r
+ _t.playState = 0;\r
+ _t.paused = false;\r
+ _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success\r
+ _t.muted = false;\r
+ _t.didBeforeFinish = false;\r
+ _t.didJustBeforeFinish = false;\r
+ _t.isBuffering = false;\r
+ _t.instanceOptions = {};\r
+ _t.instanceCount = 0;\r
+ _t.peakData = {\r
+ left: 0,\r
+ right: 0\r
+ };\r
+ _t.waveformData = {\r
+ left: [],\r
+ right: []\r
+ };\r
+ _t.eqData = []; // legacy: 1D array\r
+ _t.eqData.left = [];\r
+ _t.eqData.right = [];\r
+ };\r
+\r
+ _resetProperties();\r
+\r
+ // pseudo-private methods used by soundManager\r
+\r
+ this._setup_html5 = function(oOptions) {\r
+ var _iO = _mixin(_t._iO, oOptions), d = decodeURI,\r
+ _a = _useGlobalHTML5Audio ? _s._global_a : _t._a,\r
+ _dURL = d(_iO.url),\r
+ _oldIO = (_a && _a._t ? _a._t.instanceOptions : null);\r
+ if (_a) {\r
+ if (_a._t && _oldIO.url === _iO.url && (!_t._lastURL || (_t._lastURL === _oldIO.url))) {\r
+ return _a; // same url, ignore request\r
+ }\r
+ _s._wD('setting new URL on existing object: ' + _dURL + (_t._lastURL ? ', old URL: ' + _t._lastURL : ''));\r
+ /*\r
+ * "First things first, I, Poppa.." (reset the previous state of the old sound, if playing)\r
+ * Fixes case with devices that can only play one sound at a time\r
+ * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state\r
+ */\r
+ if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) {\r
+ _a._t.stop();\r
+ }\r
+ _resetProperties(); // new URL, so reset load/playstate and so on\r
+ _a.src = _iO.url;\r
+ _t.url = _iO.url;\r
+ _t._lastURL = _iO.url;\r
+ _a._called_load = false;\r
+ } else {\r
+ _s._wD('creating HTML5 Audio() element with URL: '+_dURL);\r
+ _a = new Audio(_iO.url);\r
+ _a._called_load = false;\r
+ if (_useGlobalHTML5Audio) {\r
+ _s._global_a = _a;\r
+ }\r
+ }\r
+ _t.isHTML5 = true;\r
+ _t._a = _a; // store a ref on the track\r
+ _a._t = _t; // store a ref on the audio\r
+ _t._add_html5_events();\r
+ _a.loop = (_iO.loops>1?'loop':'');\r
+ if (_iO.autoLoad || _iO.autoPlay) {\r
+ _a.autobuffer = 'auto'; // early HTML5 implementation (non-standard)\r
+ _a.preload = 'auto'; // standard\r
+ _t.load();\r
+ _a._called_load = true;\r
+ } else {\r
+ _a.autobuffer = false; // early HTML5 implementation (non-standard)\r
+ _a.preload = 'none'; // standard\r
+ }\r
+ _a.loop = (_iO.loops>1?'loop':''); // boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop\r
+ return _a;\r
+ };\r
+\r
+ // related private methods\r
+\r
+ this._add_html5_events = function() {\r
+ if (_t._a._added_events) {\r
+ return false;\r
+ }\r
+\r
+ var f;\r
+\r
+ function add(oEvt, oFn, bCapture) {\r
+ return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null;\r
+ }\r
+\r
+ _s._wD(_h5+'adding event listeners: '+_t.sID);\r
+ _t._a._added_events = true;\r
+\r
+ for (f in _s._html5_events) {\r
+ if (_s._html5_events.hasOwnProperty(f)) {\r
+ add(f, _s._html5_events[f]);\r
+ }\r
+ }\r
+\r
+ return true;\r
+ };\r
+\r
+ // Keep this externally accessible\r
+ this._remove_html5_events = function() {\r
+ // Remove event listeners\r
+ function remove(oEvt, oFn, bCapture) {\r
+ return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null);\r
+ }\r
+ _s._wD(_h5+'removing event listeners: '+_t.sID);\r
+ _t._a._added_events = false;\r
+\r
+ for (var f in _s._html5_events) {\r
+ if (_s._html5_events.hasOwnProperty(f)) {\r
+ remove(f, _s._html5_events[f]);\r
+ }\r
+ }\r
+ };\r
+\r
+ // --- "private" methods called by Flash ---\r
+\r
+ this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) {\r
+ _t.bytesLoaded = nBytesLoaded;\r
+ _t.bytesTotal = nBytesTotal;\r
+ _t.duration = Math.floor(nDuration);\r
+ _t.bufferLength = nBufferLength;\r
+ if (!_t._iO.isMovieStar) {\r
+ if (_t._iO.duration) {\r
+ // use options, if specified and larger\r
+ _t.durationEstimate = (_t.duration > _t._iO.duration) ? _t.duration : _t._iO.duration;\r
+ } else {\r
+ _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10);\r
+ }\r
+ if (_t.durationEstimate === undefined) {\r
+ _t.durationEstimate = _t.duration;\r
+ }\r
+ if (_t.readyState !== 3 && _t._iO.whileloading) {\r
+ _t._iO.whileloading.apply(_t);\r
+ }\r
+ } else {\r
+ _t.durationEstimate = _t.duration;\r
+ if (_t.readyState !== 3 && _t._iO.whileloading) {\r
+ _t._iO.whileloading.apply(_t);\r
+ }\r
+ }\r
+ };\r
+\r
+ this._onid3 = function(oID3PropNames, oID3Data) {\r
+ // oID3PropNames: string array (names)\r
+ // ID3Data: string array (data)\r
+ _s._wD('SMSound._onid3(): "' + this.sID + '" ID3 data received.');\r
+ var oData = [], i, j;\r
+ for (i = 0, j = oID3PropNames.length; i < j; i++) {\r
+ oData[oID3PropNames[i]] = oID3Data[i];\r
+ }\r
+ _t.id3 = _mixin(_t.id3, oData);\r
+ if (_t._iO.onid3) {\r
+ _t._iO.onid3.apply(_t);\r
+ }\r
+ };\r
+\r
+ this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {\r
+ if (isNaN(nPosition) || nPosition === null) {\r
+ return false; // flash safety net\r
+ }\r
+ if (_t.playState === 0 && nPosition > 0) {\r
+ // invalid position edge case for end/stop\r
+ nPosition = 0;\r
+ }\r
+ _t.position = nPosition;\r
+ _t.processOnPosition();\r
+ if (_fV > 8 && !_t.isHTML5) {\r
+ if (_t._iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) {\r
+ _t.peakData = {\r
+ left: oPeakData.leftPeak,\r
+ right: oPeakData.rightPeak\r
+ };\r
+ }\r
+ if (_t._iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) {\r
+ _t.waveformData = {\r
+ left: oWaveformDataLeft.split(','),\r
+ right: oWaveformDataRight.split(',')\r
+ };\r
+ }\r
+ if (_t._iO.useEQData) {\r
+ if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) {\r
+ var eqLeft = oEQData.leftEQ.split(',');\r
+ _t.eqData = eqLeft;\r
+ _t.eqData.left = eqLeft;\r
+ if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) {\r
+ _t.eqData.right = oEQData.rightEQ.split(',');\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (_t.playState === 1) {\r
+ // special case/hack: ensure buffering is false if loading from cache (and not yet started)\r
+ if (!_t.isHTML5 && _s.flashVersion === 8 && !_t.position && _t.isBuffering) {\r
+ _t._onbufferchange(0);\r
+ }\r
+ if (_t._iO.whileplaying) {\r
+ _t._iO.whileplaying.apply(_t); // flash may call after actual finish\r
+ }\r
+ if ((_t.loaded || (!_t.loaded && _t._iO.isMovieStar)) && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration - _t.position <= _t._iO.onbeforefinishtime) {\r
+ _t._onbeforefinish();\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+\r
+ // Only applies to RTMP\r
+ this._onconnect = function(bSuccess) {\r
+ var fN = 'SMSound._onconnect(): ';\r
+ bSuccess = (bSuccess === 1);\r
+ _s._wD(fN+'"'+_t.sID+'"'+(bSuccess?' connected.':' failed to connect? - '+_t.url), (bSuccess?1:2));\r
+ _t.connected = bSuccess;\r
+ if (bSuccess) {\r
+ _t.failures = 0;\r
+ if (_idCheck(_t.sID)) {\r
+ if (_t.getAutoPlay()) {\r
+ _t.play(undefined, _t.getAutoPlay()); // only update the play state if auto playing\r
+ } else if (_t._iO.autoLoad) {\r
+ _t.load();\r
+ }\r
+ }\r
+ if (_t._iO.onconnect) {\r
+ _t._iO.onconnect.apply(_t,[bSuccess]);\r
+ }\r
+ }\r
+ };\r
+\r
+ this._onload = function(nSuccess) {\r
+ var fN = 'SMSound._onload(): ', loadOK = (nSuccess?true:false);\r
+ _s._wD(fN + '"' + _t.sID + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2));\r
+ // <d>\r
+ if (!loadOK && !_t.isHTML5) {\r
+ if (_s.sandbox.noRemote === true) {\r
+ _s._wD(fN + _str('noNet'), 1);\r
+ }\r
+ if (_s.sandbox.noLocal === true) {\r
+ _s._wD(fN + _str('noLocal'), 1);\r
+ }\r
+ }\r
+ // </d>\r
+ _t.loaded = loadOK;\r
+ _t.readyState = loadOK?3:2;\r
+ _t._onbufferchange(0);\r
+ if (_t._iO.onload) {\r
+ _t._iO.onload.apply(_t, [loadOK]);\r
+ }\r
+ return true;\r
+ };\r
+\r
+ // fire onfailure() only once at most\r
+ // at this point we just recreate failed sounds rather than trying to reconnect.\r
+ this._onfailure = function(msg, level, code) {\r
+ _t.failures++;\r
+ _s._wD('SMSound._onfailure(): "'+_t.sID+'" count '+_t.failures);\r
+ if (_t._iO.onfailure && _t.failures === 1) {\r
+ _t._iO.onfailure(_t, msg, level, code);\r
+ } else {\r
+ _s._wD('SMSound._onfailure(): ignoring');\r
+ }\r
+ };\r
+\r
+ this._onbeforefinish = function() {\r
+ if (!_t.didBeforeFinish) {\r
+ _t.didBeforeFinish = true;\r
+ if (_t._iO.onbeforefinish) {\r
+ _s._wD('SMSound._onbeforefinish(): "' + _t.sID + '"');\r
+ _t._iO.onbeforefinish.apply(_t);\r
+ }\r
+ }\r
+ };\r
+\r
+ this._onjustbeforefinish = function(msOffset) {\r
+ if (!_t.didJustBeforeFinish) {\r
+ _t.didJustBeforeFinish = true;\r
+ if (_t._iO.onjustbeforefinish) {\r
+ _s._wD('SMSound._onjustbeforefinish(): "' + _t.sID + '"');\r
+ _t._iO.onjustbeforefinish.apply(_t);\r
+ }\r
+ }\r
+ };\r
+\r
+ this._onfinish = function() {\r
+ // _s._wD('SMSound._onfinish(): "' + _t.sID + '" got instanceCount '+_t.instanceCount);\r
+ var _io_onfinish = _t._iO.onfinish; // store local copy before it gets trashed..\r
+ _t._onbufferchange(0);\r
+ _t.resetOnPosition(0);\r
+ if (_t._iO.onbeforefinishcomplete) {\r
+ _t._iO.onbeforefinishcomplete.apply(_t);\r
+ }\r
+ // reset some state items\r
+ _t.didBeforeFinish = false;\r
+ _t.didJustBeforeFinish = false;\r
+ if (_t.instanceCount) {\r
+ _t.instanceCount--;\r
+ if (!_t.instanceCount) {\r
+ // reset instance options\r
+ _t.playState = 0;\r
+ _t.paused = false;\r
+ _t.instanceCount = 0;\r
+ _t.instanceOptions = {};\r
+ _t._iO = {};\r
+ _stop_html5_timer();\r
+ }\r
+ if (!_t.instanceCount || _t._iO.multiShotEvents) {\r
+ // fire onfinish for last, or every instance\r
+ if (_io_onfinish) {\r
+ _s._wD('SMSound._onfinish(): "' + _t.sID + '"');\r
+ _io_onfinish.apply(_t);\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ this._onbufferchange = function(nIsBuffering) {\r
+ var fN = 'SMSound._onbufferchange()';\r
+ if (_t.playState === 0) {\r
+ // ignore if not playing\r
+ return false;\r
+ }\r
+ if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) {\r
+ return false;\r
+ }\r
+ _t.isBuffering = (nIsBuffering === 1);\r
+ if (_t._iO.onbufferchange) {\r
+ _s._wD(fN + ': ' + nIsBuffering);\r
+ _t._iO.onbufferchange.apply(_t);\r
+ }\r
+ return true;\r
+ };\r
+\r
+ this._ondataerror = function(sError) {\r
+ // flash 9 wave/eq data handler\r
+ if (_t.playState > 0) { // hack: called at start, and end from flash at/after onfinish()\r
+ _s._wD('SMSound._ondataerror(): ' + sError);\r
+ if (_t._iO.ondataerror) {\r
+ _t._iO.ondataerror.apply(_t);\r
+ }\r
+ }\r
+ };\r
+\r
+ }; // SMSound()\r
+\r
+ // --- private SM2 internals ---\r
+\r
+ _getDocument = function() {\r
+ return (_doc.body?_doc.body:(_doc._docElement?_doc.documentElement:_doc.getElementsByTagName('div')[0]));\r
+ };\r
+\r
+ _id = function(sID) {\r
+ return _doc.getElementById(sID);\r
+ };\r
+\r
+ _mixin = function(oMain, oAdd) {\r
+ // non-destructive merge\r
+ var o1 = {}, i, o2, o;\r
+ for (i in oMain) { // clone c1\r
+ if (oMain.hasOwnProperty(i)) {\r
+ o1[i] = oMain[i];\r
+ }\r
+ }\r
+ o2 = (typeof oAdd === 'undefined'?_s.defaultOptions:oAdd);\r
+ for (o in o2) {\r
+ if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') {\r
+ o1[o] = o2[o];\r
+ }\r
+ }\r
+ return o1;\r
+ };\r
+\r
+ _event = (function() {\r
+\r
+ var old = (_win.attachEvent),\r
+ evt = {\r
+ add: (old?'attachEvent':'addEventListener'),\r
+ remove: (old?'detachEvent':'removeEventListener')\r
+ };\r
+\r
+ function getArgs(oArgs) {\r
+ var args = _slice.call(oArgs), len = args.length;\r
+ if (old) {\r
+ args[1] = 'on' + args[1]; // prefix\r
+ if (len > 3) {\r
+ args.pop(); // no capture\r
+ }\r
+ } else if (len === 3) {\r
+ args.push(false);\r
+ }\r
+ return args;\r
+ }\r
+\r
+ function apply(args, sType) {\r
+ var element = args.shift(),\r
+ method = [evt[sType]];\r
+ if (old) {\r
+ element[method](args[0], args[1]);\r
+ } else {\r
+ element[method].apply(element, args);\r
+ }\r
+ }\r
+\r
+ function add() {\r
+ apply(getArgs(arguments), 'add');\r
+ }\r
+\r
+ function remove() {\r
+ apply(getArgs(arguments), 'remove');\r
+ }\r
+\r
+ return {\r
+ 'add': add,\r
+ 'remove': remove\r
+ };\r
+\r
+ }());\r
+\r
+ _html5OK = function(iO) {\r
+ return (!iO.serverURL && (iO.type?_html5CanPlay({type:iO.type}):_html5CanPlay(iO.url)||_html5Only)); // Use type, if specified. If HTML5-only mode, no other options, so just give 'er\r
+ };\r
+\r
+ _html5CanPlay = function(sURL) {\r
+ // try to find MIME, test and return truthiness\r
+ if (!_s.useHTML5Audio || !_s.hasHTML5) {\r
+ return false;\r
+ }\r
+ var result, mime, offset, fileExt, item, aF = _s.audioFormats;\r
+ if (!_html5Ext) {\r
+ _html5Ext = [];\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ _html5Ext.push(item);\r
+ if (aF[item].related) {\r
+ _html5Ext = _html5Ext.concat(aF[item].related);\r
+ }\r
+ }\r
+ }\r
+ _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')','i');\r
+ }\r
+ mime = (typeof sURL.type !== 'undefined'?sURL.type:null);\r
+ fileExt = (typeof sURL === 'string'?sURL.toLowerCase().match(_html5Ext):null); // TODO: Strip URL queries, etc.\r
+ if (!fileExt || !fileExt.length) {\r
+ if (!mime) {\r
+ return false;\r
+ } else {\r
+ // audio/mp3 -> mp3, result should be known\r
+ offset = mime.indexOf(';');\r
+ fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); // strip "audio/X; codecs.."\r
+ }\r
+ } else {\r
+ fileExt = fileExt[0].substr(1); // "mp3", for example\r
+ }\r
+ if (fileExt && typeof _s.html5[fileExt] !== 'undefined') {\r
+ // result known\r
+ return _s.html5[fileExt];\r
+ } else {\r
+ if (!mime) {\r
+ if (fileExt && _s.html5[fileExt]) {\r
+ return _s.html5[fileExt];\r
+ } else {\r
+ // best-case guess, audio/whatever-dot-filename-format-you're-playing\r
+ mime = 'audio/'+fileExt;\r
+ }\r
+ }\r
+ result = _s.html5.canPlayType(mime);\r
+ _s.html5[fileExt] = result;\r
+ // _s._wD('canPlayType, found result: '+result);\r
+ return result;\r
+ }\r
+ };\r
+\r
+ _testHTML5 = function() {\r
+ if (!_s.useHTML5Audio || typeof Audio === 'undefined') {\r
+ return false;\r
+ }\r
+ // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/\r
+ var a = (typeof Audio !== 'undefined' ? (_isOpera ? new Audio(null) : new Audio()) : null), item, support = {}, aF, i, _hasFlash = _detectFlash();\r
+ function _cp(m) {\r
+ var canPlay, i, j, isOK = false;\r
+ if (!a || typeof a.canPlayType !== 'function') {\r
+ return false;\r
+ }\r
+ if (m instanceof Array) {\r
+ // iterate through all mime types, return any successes\r
+ for (i=0, j=m.length; i<j && !isOK; i++) {\r
+ if (_s.html5[m[i]] || a.canPlayType(m[i]).match(_s.html5Test)) {\r
+ isOK = true;\r
+ _s.html5[m[i]] = true;\r
+ }\r
+ }\r
+ return isOK;\r
+ } else {\r
+ canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);\r
+ return (canPlay && (canPlay.match(_s.html5Test)?true:false));\r
+ }\r
+ }\r
+ // test all registered formats + codecs\r
+ aF = _s.audioFormats;\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ support[item] = _cp(aF[item].type);\r
+ // assign result to related formats, too\r
+ if (aF[item] && aF[item].related) {\r
+ for (i=aF[item].related.length; i--;) {\r
+ _s.html5[aF[item].related[i]] = support[item];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ support.canPlayType = (a?_cp:null);\r
+ _s.html5 = _mixin(_s.html5, support);\r
+ return true;\r
+ };\r
+\r
+ _strings = {\r
+ // <d>\r
+ notReady: 'Not loaded yet - wait for soundManager.onload()/onready()',\r
+ notOK: 'Audio support is not available.',\r
+ appXHTML: _smc + 'createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.',\r
+ spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)',\r
+ swf404: _sm + ': Verify that %s is a valid path.',\r
+ tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)',\r
+ checkSWF: 'See SWF output for more debug info.',\r
+ localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/',\r
+ waitFocus: _sm + ': Special case: Waiting for focus-related event..',\r
+ waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...',\r
+ waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...',\r
+ needFunction: _sm + ': Function object expected for %s',\r
+ badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',\r
+ noMS: 'MovieStar mode not enabled. Exiting.',\r
+ currentObj: '--- ' + _sm + '._debug(): Current sound objects ---',\r
+ waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash..',\r
+ waitOnload: _sm + ': Waiting for window.onload()',\r
+ docLoaded: _sm + ': Document already loaded',\r
+ onload: _smc + 'initComplete(): calling soundManager.onload()',\r
+ onloadOK: _sm + '.onload() complete',\r
+ init: '-- ' + _smc + 'init() --',\r
+ didInit: _smc + 'init(): Already called?',\r
+ flashJS: _sm + ': Attempting to call Flash from JS..',\r
+ noPolling: _sm + ': Polling (whileloading()/whileplaying() support) is disabled.',\r
+ secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html',\r
+ badRemove: 'Warning: Failed to remove flash movie.',\r
+ noPeak: 'Warning: peakData features unsupported for movieStar formats',\r
+ shutdown: _sm + '.disable(): Shutting down',\r
+ queue: _sm + ': Queueing %s handler',\r
+ smFail: _sm + ': Failed to initialise.',\r
+ smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',\r
+ fbTimeout: 'No flash response, applying .'+_s.swfCSS.swfTimedout+' CSS..',\r
+ fbLoaded: 'Flash loaded',\r
+ fbHandler: _smc+'flashBlockHandler()',\r
+ manURL: 'SMSound.load(): Using manually-assigned URL',\r
+ onURL: _sm + '.load(): current URL already assigned.',\r
+ badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',\r
+ as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)',\r
+ noNSLoop: 'Note: Looping not implemented for MovieStar formats',\r
+ needfl9: 'Note: Switching to flash 9, required for MP4 formats.',\r
+ mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case',\r
+ mfOn: 'mobileFlash::enabling on-screen flash repositioning',\r
+ policy: 'Enabling usePolicyFile for data access'\r
+ // </d>\r
+ };\r
+\r
+ _str = function() { // o [,items to replace]\r
+ // <d>\r
+ var args = _slice.call(arguments), // real array, please\r
+ o = args.shift(), // first arg\r
+ str = (_strings && _strings[o]?_strings[o]:''), i, j;\r
+ if (str && args && args.length) {\r
+ for (i = 0, j = args.length; i < j; i++) {\r
+ str = str.replace('%s', args[i]);\r
+ }\r
+ }\r
+ return str;\r
+ // </d>\r
+ };\r
+\r
+ _loopFix = function(sOpt) {\r
+ // flash 8 requires stream = false for looping to work\r
+ if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) {\r
+ _wDS('as2loop');\r
+ sOpt.stream = false;\r
+ }\r
+ return sOpt;\r
+ };\r
+\r
+ _policyFix = function(sOpt, sPre) {\r
+ if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) {\r
+ _s._wD((sPre?sPre+':':'') + _str('policy'));\r
+ sOpt.usePolicyFile = true;\r
+ }\r
+ return sOpt;\r
+ };\r
+\r
+ _complain = function(sMsg) {\r
+ if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') {\r
+ console.warn(sMsg);\r
+ } else {\r
+ _s._wD(sMsg);\r
+ }\r
+ };\r
+\r
+ _doNothing = function() {\r
+ return false;\r
+ };\r
+\r
+ _disableObject = function(o) {\r
+ for (var oProp in o) {\r
+ if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') {\r
+ o[oProp] = _doNothing;\r
+ }\r
+ }\r
+ oProp = null;\r
+ };\r
+\r
+ _failSafely = function(bNoDisable) {\r
+ // general failure exception handler\r
+ if (typeof bNoDisable === 'undefined') {\r
+ bNoDisable = false;\r
+ }\r
+ if (_disabled || bNoDisable) {\r
+ _wDS('smFail', 2);\r
+ _s.disable(bNoDisable);\r
+ }\r
+ };\r
+\r
+ _normalizeMovieURL = function(smURL) {\r
+ var urlParams = null;\r
+ if (smURL) {\r
+ if (smURL.match(/\.swf(\?.*)?$/i)) {\r
+ urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);\r
+ if (urlParams) {\r
+ return smURL; // assume user knows what they're doing\r
+ }\r
+ } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {\r
+ smURL = smURL + '/';\r
+ }\r
+ }\r
+ return (smURL && smURL.lastIndexOf('/') !== - 1?smURL.substr(0, smURL.lastIndexOf('/') + 1):'./') + _s.movieURL;\r
+ };\r
+\r
+ _setVersionInfo = function() {\r
+ if (_fV !== 8 && _fV !== 9) {\r
+ _s._wD(_str('badFV', _fV, _defaultFlashVersion));\r
+ _s.flashVersion = _defaultFlashVersion;\r
+ }\r
+ var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); // debug flash movie, if applicable\r
+ if (_s.useHTML5Audio && !_html5Only && _s.audioFormats.mp4.required && _s.flashVersion < 9) {\r
+ _s._wD(_str('needfl9'));\r
+ _s.flashVersion = 9;\r
+ }\r
+ _fV = _s.flashVersion; // short-hand for internal use\r
+ _s.version = _s.versionNumber + (_html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)'));\r
+ // set up default options\r
+ if (_fV > 8) {\r
+ _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options);\r
+ _s.features.buffering = true;\r
+ }\r
+ if (_fV > 8 && _s.useMovieStar) {\r
+ // flash 9+ support for movieStar formats as well as MP3\r
+ _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions);\r
+ _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _s.netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+ _s.mimePattern = _s.netStreamMimeTypes;\r
+ _s.features.movieStar = true;\r
+ } else {\r
+ _s.useMovieStar = false;\r
+ _s.features.movieStar = false;\r
+ }\r
+ _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')];\r
+ _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf',isDebug);\r
+ _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8);\r
+ };\r
+\r
+ _setPolling = function(bPolling, bHighPerformance) {\r
+ if (!_s.o || !_s.allowPolling) {\r
+ return false;\r
+ }\r
+ _s.o._setPolling(bPolling, bHighPerformance);\r
+ };\r
+\r
+ function _initDebug() {\r
+ if (_s.debugURLParam.test(_wl)) {\r
+ _s.debugMode = true; // allow force of debug mode via URL\r
+ }\r
+ // <d>\r
+ if (_id(_s.debugID)) {\r
+ return false;\r
+ }\r
+ var oD, oDebug, oTarget, oToggle, tmp;\r
+ if (_s.debugMode && !_id(_s.debugID) && ((!_hasConsole || !_s.useConsole) || (_s.useConsole && _hasConsole && !_s.consoleOnly))) {\r
+ oD = _doc.createElement('div');\r
+ oD.id = _s.debugID + '-toggle';\r
+ oToggle = {\r
+ 'position': 'fixed',\r
+ 'bottom': '0px',\r
+ 'right': '0px',\r
+ 'width': '1.2em',\r
+ 'height': '1.2em',\r
+ 'lineHeight': '1.2em',\r
+ 'margin': '2px',\r
+ 'textAlign': 'center',\r
+ 'border': '1px solid #999',\r
+ 'cursor': 'pointer',\r
+ 'background': '#fff',\r
+ 'color': '#333',\r
+ 'zIndex': 10001\r
+ };\r
+ oD.appendChild(_doc.createTextNode('-'));\r
+ oD.onclick = _toggleDebug;\r
+ oD.title = 'Toggle SM2 debug console';\r
+ if (_ua.match(/msie 6/i)) {\r
+ oD.style.position = 'absolute';\r
+ oD.style.cursor = 'hand';\r
+ }\r
+ for (tmp in oToggle) {\r
+ if (oToggle.hasOwnProperty(tmp)) {\r
+ oD.style[tmp] = oToggle[tmp];\r
+ }\r
+ }\r
+ oDebug = _doc.createElement('div');\r
+ oDebug.id = _s.debugID;\r
+ oDebug.style.display = (_s.debugMode?'block':'none');\r
+ if (_s.debugMode && !_id(oD.id)) {\r
+ try {\r
+ oTarget = _getDocument();\r
+ oTarget.appendChild(oD);\r
+ } catch(e2) {\r
+ throw new Error(_str('appXHTML'));\r
+ }\r
+ oTarget.appendChild(oDebug);\r
+ }\r
+ }\r
+ oTarget = null;\r
+ // </d>\r
+ }\r
+\r
+ _createMovie = function(smID, smURL) {\r
+\r
+ var specialCase = null,\r
+ remoteURL = (smURL?smURL:_s.url),\r
+ localURL = (_s.altURL?_s.altURL:remoteURL),\r
+ oEmbed, oMovie, oTarget = _getDocument(), tmp, movieHTML, oEl, extraClass = _getSWFCSS(), s, x, sClass, side = '100%', isRTL = null, html = _doc.getElementsByTagName('html')[0];\r
+ isRTL = (html && html.dir && html.dir.match(/rtl/i));\r
+ smID = (typeof smID === 'undefined'?_s.id:smID);\r
+\r
+ if (_didAppend && _appendSuccess) {\r
+ return false; // ignore if already succeeded\r
+ }\r
+\r
+ function _initMsg() {\r
+ _s._wD('-- SoundManager 2 ' + _s.version + (!_html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_html5Only ? (_s.useMovieStar?', MovieStar mode':'') + (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : (_s.useFastPolling?'fast':'normal')) + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1);\r
+ }\r
+\r
+ if (_html5Only) {\r
+ _setVersionInfo();\r
+ _initMsg();\r
+ _s.oMC = _id(_s.movieID);\r
+ _init();\r
+ // prevent multiple init attempts\r
+ _didAppend = true;\r
+ _appendSuccess = true;\r
+ return false;\r
+ }\r
+\r
+ _didAppend = true;\r
+\r
+ // safety check for legacy (change to Flash 9 URL)\r
+ _setVersionInfo();\r
+ _s.url = _normalizeMovieURL(_s._overHTTP?remoteURL:localURL);\r
+ smURL = _s.url;\r
+\r
+ _s.wmode = (!_s.wmode && _s.useHighPerformance && !_s.useMovieStar?'transparent':_s.wmode);\r
+\r
+ if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) {\r
+ _s.specialWmodeCase = true;\r
+ // extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here\r
+ // does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout\r
+ // wmode breaks IE 8 on Vista + Win7 too in some cases, as of Jan.2011 (?)\r
+ _wDS('spcWmode');\r
+ _s.wmode = null;\r
+ }\r
+\r
+ oEmbed = {\r
+ 'name': smID,\r
+ 'id': smID,\r
+ 'src': smURL,\r
+ 'width': side,\r
+ 'height': side,\r
+ 'quality': 'high',\r
+ 'allowScriptAccess': _s.allowScriptAccess,\r
+ 'bgcolor': _s.bgColor,\r
+ 'pluginspage': _s._http+'//www.macromedia.com/go/getflashplayer',\r
+ 'type': 'application/x-shockwave-flash',\r
+ 'wmode': _s.wmode,\r
+ 'hasPriority': 'true' // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html\r
+ };\r
+\r
+ if (_s.debugFlash) {\r
+ oEmbed.FlashVars = 'debug=1';\r
+ }\r
+\r
+ if (!_s.wmode) {\r
+ delete oEmbed.wmode; // don't write empty attribute\r
+ }\r
+\r
+ if (_isIE) {\r
+ // IE is "special".\r
+ oMovie = _doc.createElement('div');\r
+ movieHTML = '<object id="' + smID + '" data="' + smURL + '" type="' + oEmbed.type + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+_s._http+'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="' + oEmbed.width + '" height="' + oEmbed.height + '"><param name="movie" value="' + smURL + '" /><param name="AllowScriptAccess" value="' + _s.allowScriptAccess + '" /><param name="quality" value="' + oEmbed.quality + '" />' + (_s.wmode?'<param name="wmode" value="' + _s.wmode + '" /> ':'') + '<param name="bgcolor" value="' + _s.bgColor + '" />' + (_s.debugFlash?'<param name="FlashVars" value="' + oEmbed.FlashVars + '" />':'') + '</object>';\r
+ } else {\r
+ oMovie = _doc.createElement('embed');\r
+ for (tmp in oEmbed) {\r
+ if (oEmbed.hasOwnProperty(tmp)) {\r
+ oMovie.setAttribute(tmp, oEmbed[tmp]);\r
+ }\r
+ }\r
+ }\r
+\r
+ _initDebug();\r
+ extraClass = _getSWFCSS();\r
+ oTarget = _getDocument();\r
+\r
+ if (oTarget) {\r
+ _s.oMC = _id(_s.movieID)?_id(_s.movieID):_doc.createElement('div');\r
+ if (!_s.oMC.id) {\r
+ _s.oMC.id = _s.movieID;\r
+ _s.oMC.className = _s.swfCSS.swfDefault + ' ' + extraClass;\r
+ // "hide" flash movie\r
+ s = null;\r
+ oEl = null;\r
+ if (!_s.useFlashBlock) {\r
+ if (_s.useHighPerformance) {\r
+ s = {\r
+ 'position': 'fixed',\r
+ 'width': '8px',\r
+ 'height': '8px',\r
+ // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.\r
+ 'bottom': '0px',\r
+ 'left': '0px',\r
+ 'overflow': 'hidden'\r
+ };\r
+ } else {\r
+ s = {\r
+ 'position': 'absolute',\r
+ 'width': '6px',\r
+ 'height': '6px',\r
+ 'top': '-9999px',\r
+ 'left': '-9999px'\r
+ };\r
+ if (isRTL) {\r
+ s.left = Math.abs(parseInt(s.left,10))+'px';\r
+ }\r
+ }\r
+ }\r
+ if (_isWebkit) {\r
+ _s.oMC.style.zIndex = 10000; // soundcloud-reported render/crash fix, safari 5\r
+ }\r
+ if (!_s.debugFlash) {\r
+ for (x in s) {\r
+ if (s.hasOwnProperty(x)) {\r
+ _s.oMC.style[x] = s[x];\r
+ }\r
+ }\r
+ }\r
+ try {\r
+ if (!_isIE) {\r
+ _s.oMC.appendChild(oMovie);\r
+ }\r
+ oTarget.appendChild(_s.oMC);\r
+ if (_isIE) {\r
+ oEl = _s.oMC.appendChild(_doc.createElement('div'));\r
+ oEl.className = _s.swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+ _appendSuccess = true;\r
+ } catch(e) {\r
+ throw new Error(_str('appXHTML'));\r
+ }\r
+ } else {\r
+ // it's already in the document.\r
+ sClass = _s.oMC.className;\r
+ _s.oMC.className = (sClass?sClass+' ':_s.swfCSS.swfDefault) + (extraClass?' '+extraClass:'');\r
+ _s.oMC.appendChild(oMovie);\r
+ if (_isIE) {\r
+ oEl = _s.oMC.appendChild(_doc.createElement('div'));\r
+ oEl.className = _s.swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+ _appendSuccess = true;\r
+ }\r
+ }\r
+\r
+ if (specialCase) {\r
+ _s._wD(specialCase);\r
+ }\r
+\r
+ _initMsg();\r
+ _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_s._overHTTP && _s.altURL?' (alternate URL)':''), 1);\r
+\r
+ return true;\r
+ };\r
+\r
+ _idCheck = this.getSoundById;\r
+\r
+ _initMovie = function() {\r
+ if (_html5Only) {\r
+ _createMovie();\r
+ return false;\r
+ }\r
+ // attempt to get, or create, movie\r
+ if (_s.o) {\r
+ return false; // may already exist\r
+ }\r
+ _s.o = _s.getMovie(_s.id); // inline markup\r
+ if (!_s.o) {\r
+ if (!_oRemoved) {\r
+ // try to create\r
+ _createMovie(_s.id, _s.url);\r
+ } else {\r
+ // try to re-append removed movie after reboot()\r
+ if (!_isIE) {\r
+ _s.oMC.appendChild(_oRemoved);\r
+ } else {\r
+ _s.oMC.innerHTML = _oRemovedHTML;\r
+ }\r
+ _oRemoved = null;\r
+ _didAppend = true;\r
+ }\r
+ _s.o = _s.getMovie(_s.id);\r
+ }\r
+ if (_s.o) {\r
+ _s._wD(_smc+'initMovie(): Got '+_s.o.nodeName+' element ('+(_didAppend?'created via JS':'static HTML')+')');\r
+ _wDS('waitEI');\r
+ }\r
+ if (_s.oninitmovie instanceof Function) {\r
+ setTimeout(_s.oninitmovie, 1);\r
+ }\r
+ return true;\r
+ };\r
+\r
+ _go = function(sURL) {\r
+ // where it all begins.\r
+ if (sURL) {\r
+ _s.url = sURL;\r
+ }\r
+ _initMovie();\r
+ };\r
+\r
+ _delayWaitForEI = function() {\r
+ setTimeout(_waitForEI, 500);\r
+ };\r
+\r
+ _waitForEI = function() {\r
+ if (_waitingForEI) {\r
+ return false;\r
+ }\r
+ _waitingForEI = true;\r
+ _event.remove(_win, 'load', _delayWaitForEI);\r
+ if (_tryInitOnFocus && !_isFocused) {\r
+ _wDS('waitFocus');\r
+ return false;\r
+ }\r
+ var p;\r
+ if (!_didInit) {\r
+ p = _s.getMoviePercent();\r
+ _s._wD(_str('waitImpatient', (p === 100?' (SWF loaded)':(p > 0?' (SWF ' + p + '% loaded)':''))));\r
+ }\r
+ setTimeout(function() {\r
+ p = _s.getMoviePercent();\r
+ if (!_didInit) {\r
+ _s._wD(_sm + ': No Flash response within expected time.\nLikely causes: ' + (p === 0?'Loading ' + _s.movieURL + ' may have failed (and/or Flash ' + _fV + '+ not present?), ':'') + 'Flash blocked or JS-Flash security error.' + (_s.debugFlash?' ' + _str('checkSWF'):''), 2);\r
+ if (!_s._overHTTP && p) {\r
+ _wDS('localFail', 2);\r
+ if (!_s.debugFlash) {\r
+ _wDS('tryDebug', 2);\r
+ }\r
+ }\r
+ if (p === 0) {\r
+ // if 0 (not null), probably a 404.\r
+ _s._wD(_str('swf404', _s.url));\r
+ }\r
+ _debugTS('flashtojs', false, ': Timed out' + _s._overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)');\r
+ }\r
+ // give up / time-out, depending\r
+ if (!_didInit && _okToDisable) {\r
+ if (p === null) {\r
+ // SWF failed. Maybe blocked.\r
+ if (_s.useFlashBlock || _s.flashLoadTimeout === 0) {\r
+ if (_s.useFlashBlock) {\r
+ _flashBlockHandler();\r
+ }\r
+ _wDS('waitForever');\r
+ } else {\r
+ // old SM2 behaviour, simply fail\r
+ _failSafely(true);\r
+ }\r
+ } else {\r
+ // flash loaded? Shouldn't be a blocking issue, then.\r
+ if (_s.flashLoadTimeout === 0) {\r
+ _wDS('waitForever');\r
+ } else {\r
+ _failSafely(true);\r
+ }\r
+ }\r
+ }\r
+ }, _s.flashLoadTimeout);\r
+ };\r
+\r
+ _go = function(sURL) {\r
+ // where it all begins.\r
+ if (sURL) {\r
+ _s.url = sURL;\r
+ }\r
+ _initMovie();\r
+ };\r
+\r
+ // <d>\r
+ _wDS = function(o, errorLevel) {\r
+ if (!o) {\r
+ return '';\r
+ } else {\r
+ return _s._wD(_str(o), errorLevel);\r
+ }\r
+ };\r
+\r
+ if (_wl.indexOf('debug=alert') + 1 && _s.debugMode) {\r
+ _s._wD = function(sText) {window.alert(sText);};\r
+ }\r
+\r
+ _toggleDebug = function() {\r
+ var o = _id(_s.debugID),\r
+ oT = _id(_s.debugID + '-toggle');\r
+ if (!o) {\r
+ return false;\r
+ }\r
+ if (_debugOpen) {\r
+ // minimize\r
+ oT.innerHTML = '+';\r
+ o.style.display = 'none';\r
+ } else {\r
+ oT.innerHTML = '-';\r
+ o.style.display = 'block';\r
+ }\r
+ _debugOpen = !_debugOpen;\r
+ };\r
+\r
+ _debugTS = function(sEventType, bSuccess, sMessage) {\r
+ // troubleshooter debug hooks\r
+ if (typeof sm2Debugger !== 'undefined') {\r
+ try {\r
+ sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ // </d>\r
+\r
+ _getSWFCSS = function() {\r
+ var css = [];\r
+ if (_s.debugMode) {\r
+ css.push(_s.swfCSS.sm2Debug);\r
+ }\r
+ if (_s.debugFlash) {\r
+ css.push(_s.swfCSS.flashDebug);\r
+ }\r
+ if (_s.useHighPerformance) {\r
+ css.push(_s.swfCSS.highPerf);\r
+ }\r
+ return css.join(' ');\r
+ };\r
+\r
+ _flashBlockHandler = function() {\r
+ // *possible* flash block situation.\r
+ var name = _str('fbHandler'), p = _s.getMoviePercent(), css = _s.swfCSS;\r
+ if (!_s.ok()) {\r
+ if (_needsFlash) {\r
+ // make the movie more visible, so user can fix\r
+ _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError);\r
+ _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':''));\r
+ }\r
+ _s.didFlashBlock = true;\r
+ _processOnEvents({type:'ontimeout',ignoreInit:true}); // fire onready(), complain lightly\r
+ if (_s.onerror instanceof Function) {\r
+ _s.onerror.apply(_win);\r
+ }\r
+ } else {\r
+ // SM2 loaded OK (or recovered)\r
+ if (_s.didFlashBlock) {\r
+ _s._wD(name+': Unblocked');\r
+ }\r
+ if (_s.oMC) {\r
+ _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' ');\r
+ }\r
+ }\r
+ };\r
+\r
+ _handleFocus = function() {\r
+ function cleanup() {\r
+ _event.remove(_win, 'focus', _handleFocus);\r
+ _event.remove(_win, 'load', _handleFocus);\r
+ }\r
+ if (_isFocused || !_tryInitOnFocus) {\r
+ cleanup();\r
+ return true;\r
+ }\r
+ _okToDisable = true;\r
+ _isFocused = true;\r
+ _s._wD(_smc+'handleFocus()');\r
+ if (_isSafari && _tryInitOnFocus) {\r
+ // giant Safari 3.1 hack - assume mousemove = focus given lack of focus event\r
+ _event.remove(_win, 'mousemove', _handleFocus);\r
+ }\r
+ // allow init to restart\r
+ _waitingForEI = false;\r
+ cleanup();\r
+ return true;\r
+ };\r
+\r
+ _initComplete = function(bNoDisable) {\r
+ if (_didInit) {\r
+ return false;\r
+ }\r
+ if (_html5Only) {\r
+ // all good.\r
+ _s._wD('-- SoundManager 2: loaded --');\r
+ _didInit = true;\r
+ _processOnEvents();\r
+ _initUserOnload();\r
+ return true;\r
+ }\r
+ var sClass = _s.oMC.className,\r
+ wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent());\r
+ if (!wasTimeout) {\r
+ _didInit = true;\r
+ }\r
+ _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'security/load error':'OK') + ') --', 1);\r
+ if (_disabled || bNoDisable) {\r
+ if (_s.useFlashBlock) {\r
+ _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_s.swfCSS.swfTimedout:_s.swfCSS.swfError);\r
+ }\r
+ _processOnEvents({type:'ontimeout'});\r
+ _debugTS('onload', false);\r
+ if (_s.onerror instanceof Function) {\r
+ _s.onerror.apply(_win);\r
+ }\r
+ return false;\r
+ } else {\r
+ _debugTS('onload', true);\r
+ }\r
+ _event.add(_win, 'unload', _doNothing); // prevent browser from showing cached state via back button, because flash will be dead\r
+ if (_s.waitForWindowLoad && !_windowLoaded) {\r
+ _wDS('waitOnload');\r
+ _event.add(_win, 'load', _initUserOnload);\r
+ return false;\r
+ } else {\r
+ if (_s.waitForWindowLoad && _windowLoaded) {\r
+ _wDS('docLoaded');\r
+ }\r
+ _initUserOnload();\r
+ }\r
+ return true;\r
+ };\r
+\r
+ _addOnEvent = function(sType, oMethod, oScope) {\r
+ if (typeof _on_queue[sType] === 'undefined') {\r
+ _on_queue[sType] = [];\r
+ }\r
+ _on_queue[sType].push({\r
+ 'method': oMethod,\r
+ 'scope': (oScope || null),\r
+ 'fired': false\r
+ });\r
+ };\r
+\r
+ _processOnEvents = function(oOptions) {\r
+ if (!oOptions) { // assume onready, if unspecified\r
+ oOptions = {\r
+ type: 'onready'\r
+ };\r
+ }\r
+ if (!_didInit && oOptions && !oOptions.ignoreInit) {\r
+ // not ready yet.\r
+ return false;\r
+ }\r
+ var status = {\r
+ success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled)\r
+ },\r
+ srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), // queue specified by type, or none\r
+ queue = [], i, j,\r
+ canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok());\r
+ for (i = 0; i < srcQueue.length; i++) {\r
+ if (srcQueue[i].fired !== true) {\r
+ queue.push(srcQueue[i]);\r
+ }\r
+ }\r
+ if (queue.length) {\r
+ _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s'));\r
+ for (i = 0, j = queue.length; i < j; i++) {\r
+ if (queue[i].scope) {\r
+ queue[i].method.apply(queue[i].scope, [status]);\r
+ } else {\r
+ queue[i].method(status);\r
+ }\r
+ if (!canRetry) { // flashblock case doesn't count here\r
+ queue[i].fired = true;\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+\r
+ _initUserOnload = function() {\r
+ _win.setTimeout(function() {\r
+ if (_s.useFlashBlock) {\r
+ _flashBlockHandler();\r
+ }\r
+ _processOnEvents();\r
+ // call user-defined "onload", scoped to window\r
+ if (_s.onload instanceof Function) {\r
+ _wDS('onload', 1);\r
+ _s.onload.apply(_win);\r
+ _wDS('onloadOK', 1);\r
+ }\r
+ if (_s.waitForWindowLoad) {\r
+ _event.add(_win, 'load', _initUserOnload);\r
+ }\r
+ },1);\r
+ };\r
+\r
+ _detectFlash = function() {\r
+\r
+ // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt\r
+\r
+ if (_hasFlash !== undefined) {\r
+ // this work has already been done.\r
+ return _hasFlash;\r
+ }\r
+\r
+ var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject;\r
+\r
+ if (nP && nP.length) {\r
+\r
+ type = 'application/x-shockwave-flash';\r
+ types = n.mimeTypes;\r
+ if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
+ hasPlugin = true;\r
+ }\r
+\r
+ } else if (typeof AX !== 'undefined') {\r
+\r
+ try {\r
+ obj = new AX('ShockwaveFlash.ShockwaveFlash');\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+ hasPlugin = (!!obj);\r
+\r
+ }\r
+\r
+ _hasFlash = hasPlugin;\r
+\r
+ return hasPlugin;\r
+\r
+ };\r
+\r
+ _featureCheck = function() {\r
+ var needsFlash, item,\r
+ isSpecial = (_ua.match(/iphone os (1|2|3_0|3_1)/i)?true:false); // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (iPad) + iOS4 works.\r
+ if (isSpecial) {\r
+ _s.hasHTML5 = false; // has Audio(), but is broken; let it load links directly.\r
+ _html5Only = true; // ignore flash case, however\r
+ if (_s.oMC) {\r
+ _s.oMC.style.display = 'none';\r
+ }\r
+ return false;\r
+ }\r
+ if (_s.useHTML5Audio) {\r
+ if (!_s.html5 || !_s.html5.canPlayType) {\r
+ _s._wD('SoundManager: No HTML5 Audio() support detected.');\r
+ _s.hasHTML5 = false;\r
+ return true;\r
+ } else {\r
+ _s.hasHTML5 = true;\r
+ }\r
+ if (_isBadSafari) {\r
+ _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1);\r
+ if (_detectFlash()) {\r
+ return true;\r
+ }\r
+ }\r
+ } else {\r
+ // flash required.\r
+ return true;\r
+ }\r
+ for (item in _s.audioFormats) {\r
+ if (_s.audioFormats.hasOwnProperty(item) && _s.audioFormats[item].required && !_s.html5.canPlayType(_s.audioFormats[item].type)) {\r
+ // may need flash for this format?\r
+ needsFlash = true;\r
+ }\r
+ }\r
+ // sanity check..\r
+ if (_s.ignoreFlash) {\r
+ needsFlash = false;\r
+ }\r
+ _html5Only = (_s.useHTML5Audio && _s.hasHTML5 && !needsFlash && !_s.requireFlash);\r
+ return (_detectFlash() && needsFlash);\r
+ };\r
+\r
+ _init = function() {\r
+ var item, tests = [];\r
+ _wDS('init');\r
+\r
+ // called after onload()\r
+ if (_didInit) {\r
+ _wDS('didInit');\r
+ return false;\r
+ }\r
+\r
+ function _cleanup() {\r
+ _event.remove(_win, 'load', _s.beginDelayedInit);\r
+ }\r
+\r
+ if (_s.hasHTML5) {\r
+ for (item in _s.audioFormats) {\r
+ if (_s.audioFormats.hasOwnProperty(item)) {\r
+ tests.push(item+': '+_s.html5[item]);\r
+ }\r
+ }\r
+ _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1);\r
+ }\r
+\r
+ if (_html5Only) {\r
+ if (!_didInit) {\r
+ // we don't need no steenking flash!\r
+ _cleanup();\r
+ _s.enabled = true;\r
+ _initComplete();\r
+ }\r
+ return true;\r
+ }\r
+\r
+ // flash path\r
+ _initMovie();\r
+ try {\r
+ _wDS('flashJS');\r
+ _s.o._externalInterfaceTest(false); // attempt to talk to Flash\r
+ if (!_s.allowPolling) {\r
+ _wDS('noPolling', 1);\r
+ } else {\r
+ _setPolling(true, _s.flashPollingInterval ? _s.flashPollingInterval : (_s.useFastPolling ? 10 : 50));\r
+ }\r
+ if (!_s.debugMode) {\r
+ _s.o._disableDebug();\r
+ }\r
+ _s.enabled = true;\r
+ _debugTS('jstoflash', true);\r
+ } catch(e) {\r
+ _s._wD('js/flash exception: ' + e.toString());\r
+ _debugTS('jstoflash', false);\r
+ _failSafely(true); // don't disable, for reboot()\r
+ _initComplete();\r
+ return false;\r
+ }\r
+ _initComplete();\r
+ // event cleanup\r
+ _cleanup();\r
+ return true;\r
+ };\r
+\r
+ _beginInit = function() {\r
+ if (_initPending) {\r
+ return false;\r
+ }\r
+ _createMovie();\r
+ _initMovie();\r
+ _initPending = true;\r
+ return true;\r
+ };\r
+\r
+ _dcLoaded = function() {\r
+ if (_didDCLoaded) {\r
+ return false;\r
+ }\r
+ _didDCLoaded = true;\r
+ _initDebug();\r
+ if (!_s.useHTML5Audio) {\r
+ if (!_detectFlash()) {\r
+ _s._wD('SoundManager: No Flash detected, trying HTML5');\r
+ _s.useHTML5Audio = true;\r
+ }\r
+ }\r
+ _testHTML5();\r
+ _s.html5.usingFlash = _featureCheck();\r
+ _needsFlash = _s.html5.usingFlash;\r
+ _didDCLoaded = true;\r
+ if (_doc.removeEventListener) {\r
+ _doc.removeEventListener('DOMContentLoaded', _dcLoaded, false);\r
+ }\r
+ _go();\r
+ return true;\r
+ };\r
+\r
+ _startTimer = function(oSound) {\r
+ if (!oSound._hasTimer) {\r
+ oSound._hasTimer = true;\r
+ }\r
+ };\r
+\r
+ _stopTimer = function(oSound) {\r
+ if (oSound._hasTimer) {\r
+ oSound._hasTimer = false;\r
+ }\r
+ };\r
+\r
+ _die = function() {\r
+ if (_s.onerror instanceof Function) {\r
+ _s.onerror();\r
+ }\r
+ _s.disable();\r
+ };\r
+\r
+ _badSafariFix = function() {\r
+ // special case: "bad" Safari can fall back to flash for MP3/MP4\r
+ if (!_isBadSafari || !_detectFlash()) {\r
+ return false; // doesn't apply\r
+ }\r
+ var aF = _s.audioFormats, i, item;\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ // special case: "bad" Safari can fall back to flash for MP3/MP4\r
+ if (item === 'mp3' || item === 'mp4') {\r
+ _s._wD(_sm+': Using flash fallback for '+item+' format');\r
+ _s.html5[item] = false;\r
+ // assign result to related formats, too\r
+ if (aF[item] && aF[item].related) {\r
+ for (i = aF[item].related.length; i--;) {\r
+ _s.html5[aF[item].related[i]] = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ // pseudo-private methods called by Flash\r
+\r
+ this._setSandboxType = function(sandboxType) {\r
+ // <d>\r
+ var sb = _s.sandbox;\r
+ sb.type = sandboxType;\r
+ sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')];\r
+ _s._wD('Flash security sandbox type: ' + sb.type);\r
+ if (sb.type === 'localWithFile') {\r
+ sb.noRemote = true;\r
+ sb.noLocal = false;\r
+ _wDS('secNote', 2);\r
+ } else if (sb.type === 'localWithNetwork') {\r
+ sb.noRemote = false;\r
+ sb.noLocal = true;\r
+ } else if (sb.type === 'localTrusted') {\r
+ sb.noRemote = false;\r
+ sb.noLocal = false;\r
+ }\r
+ // </d>\r
+ };\r
+\r
+ this._externalInterfaceOK = function(flashDate) {\r
+ // flash callback confirming flash loaded, EI working etc.\r
+ // flashDate = approx. timing/delay info for JS/flash bridge\r
+ if (_s.swfLoaded) {\r
+ return false;\r
+ }\r
+ var eiTime = new Date().getTime();\r
+ _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':''));\r
+ _debugTS('swf', true);\r
+ _debugTS('flashtojs', true);\r
+ _s.swfLoaded = true;\r
+ _tryInitOnFocus = false;\r
+ if (_isBadSafari) {\r
+ _badSafariFix();\r
+ }\r
+ if (_isIE) {\r
+ // IE needs a timeout OR delay until window.onload - may need TODO: investigating\r
+ setTimeout(_init, 100);\r
+ } else {\r
+ _init();\r
+ }\r
+ };\r
+\r
+ _dcIE = function() {\r
+ if (_doc.readyState === 'complete') {\r
+ _dcLoaded();\r
+ _doc.detachEvent('onreadystatechange', _dcIE);\r
+ }\r
+ return true;\r
+ };\r
+\r
+ // focus and window load, init\r
+ if (!_s.hasHTML5 || _needsFlash) {\r
+ // only applies to Flash mode\r
+ _event.add(_win, 'focus', _handleFocus);\r
+ _event.add(_win, 'load', _handleFocus);\r
+ _event.add(_win, 'load', _delayWaitForEI);\r
+ if (_isSafari && _tryInitOnFocus) {\r
+ _event.add(_win, 'mousemove', _handleFocus); // massive Safari focus hack\r
+ }\r
+ }\r
+\r
+ if (_doc.addEventListener) {\r
+ _doc.addEventListener('DOMContentLoaded', _dcLoaded, false);\r
+ } else if (_doc.attachEvent) {\r
+ _doc.attachEvent('onreadystatechange', _dcIE);\r
+ } else {\r
+ // no add/attachevent support - safe to assume no JS -> Flash either\r
+ _debugTS('onload', false);\r
+ _die();\r
+ }\r
+\r
+ if (_doc.readyState === 'complete') {\r
+ setTimeout(_dcLoaded,100);\r
+ }\r
+\r
+} // SoundManager()\r
+\r
+// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading\r
+if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) {\r
+ soundManager = new SoundManager();\r
+}\r
+\r
+// public interfaces\r
+window.SoundManager = SoundManager; // constructor\r
+window.soundManager = soundManager; // public API, flash callbacks etc\r
+\r
+}(window));\r
--- /dev/null
+/**
+ * TimeSide - Web Audio Components
+ * Copyright (c) 2011 Parisson
+ * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
+ * License: GNU General Public License version 2.0
+ */
+
+/**
+ * Base class defining classes for TimesideUI
+ */
+
+/* Simple JavaScript Inheritance
+ * By John Resig http://ejohn.org/
+ * MIT Licensed.
+ * (Inspired by base2 and Prototype)
+ *
+ * In my (Riccardo) opinion the lightest and most-comprehensive way to implement inhertance and OOP in
+ * javascript. Usages can be found below.
+ * Basically,
+ * 1) a new Class is instantiated with Class.extend(). This function takes a dictionary
+ * of properties/methods which will be put IN THE PROTOTYPE of the class, so that each instance will share the same properties/methods
+ * and the latter don't have to be created for each instance separately.
+ * 2) If var A = Class.extend({...}) and var B = A.extend({..}), then methods which are found in B will override the same methods in A.
+ * In this case, the variable this._super inside the overridden methods will refers to the super-method and can thus be called safely.
+ * Consequently, if a _super property/method is implemented in the extend dictionary, it WILL NOT be accessible
+ * to the overriding methods of B. Basically, don't use _super as a key of the argument of extend.
+ * 3) AFTER the prototype has been populated, the init function, if exists, is called. The latter can be seen as a class constructor in java,
+ * with a substantial difference: when executing the init() method the class prototype has already been populated with all inherited methods.
+ * Private variable can be declared in the init function, as well as
+ * relative getters and setters, if needed. Downside is that the privileged getters and setters can’t be put in the prototype,
+ * i.e. they are created for each instance separately, and the _super keyword does not apply to them. Another issue is the overhead of closures in general (basically, write as less as possible
+ * in the init function, in particular if the class has to be declared several times)
+ * Of course, the this._super keyword of methods implemented in the init constructor does not work
+ *
+ * EXAMPLE:
+ * var MyClass = Class.extend({
+ * init: function(optionalArray){ //constructor
+ * this._super(); //!!!ERROR: Class is the base class and does not have a super construcor
+ * var me = []; //private variable
+ * this.count = 6; //set the value of the public property defined below
+ * this.getMe = function(){ //public method
+ * this._super(); //!!!ERROR: methods defined in the init function don't have acces to _super
+ * }
+ * this.alert = function(){ //another public method, !!!WARNING: this will be put in the MyClass scope (NOT in the prototype)
+ * alert('ok');
+ * }
+ * },
+ * count:0, //public property
+ * alert: function(){ //public method. !!!WARNING: this method will be put in the prototype BEFORE the init is called,
+ * alert('no'); // so the alert defined above will be actually called
+ * }
+ * });
+ * var MyClass2 = MyClass.extend({
+ * init: function(){
+ * this._super(); //call the super constructor
+ * }
+ * alert: function(){ //override a method
+ * this._super(); //call the super method, ie alerts 'no'. WARNING: However, as long as there is an alert written
+ * //in the init method of the superclass (see above), THAT method will be called
+ * }
+ * });
+ *
+ */
+//
+(function(){
+
+ var initializing = false, fnTest = /xyz/.test(function(){
+ xyz;
+ }) ? /\b_super\b/ : /.*/;
+
+ /*The xyz test above determines whether the browser can inspect the textual body of a function.
+ *If it can, you can perform an optimization by only wrapping an overridden method if it
+ *actually calls this._super() somewhere in its body.
+ *Since it requires an additional closure and function call overhead to support _super,
+ *it’s nice to skip that step if it isn’t needed.
+ */
+
+ // The base Class implementation (does nothing)
+ this.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ Class.extend = function(prop) {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop) {
+ // Check if we're overwriting an existing function
+ prototype[name] = typeof prop[name] == "function" &&
+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+
+ // The dummy class constructor
+ function Class() {
+ // All construction is actually done in the init method
+ if ( !initializing && this.init ){
+ this.init.apply(this, arguments);
+ }
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+})();
+
+//Defining the base TimeClass class. Player, Ruler, MarkerMap are typical implementations (see js files)
+//Basically we store here static methods which must be accessible
+//in several timside sub-classes
+var TimesideClass = Class.extend({
+
+ _textWidth : function(text, fontSize) {
+ var ratio = 3/5;
+ return text.length * ratio * fontSize;
+ },
+
+ /*
+ *formats (ie returns a string representation of) a time which is in the form seconds,milliseconds (eg 07.6750067)
+ * formatArray is an array of strings which can be:
+ * 'h' hours. Use 'hh' for a zero-padding to 10 (so that 6 hours is rendered as '06')
+ * 'm' hours. Use 'mm' for a zero-padding to 10 (so that 6 minutes is rendered as '06')
+ * 's' hours. Use 'ss' foar a zero-padding to 10 (so that 6 seconds is rendered as '06')
+ * 'D' deciseconds
+ * 'C' centiseconds (it will be padded to 10, so that 5 centiseconds will be rendered as '05')
+ * 'S' milliseconds (it will be padded to 100, so that 5 milliseconds will be rendered as '005')
+ * If formatArray is null or undefined or zero-length, it defaults to ['mm','ss']
+ * 'h','m' and 's' will be prepended the separator ':'. For the others, the prepended separator is '.'
+ * Examples:
+ * makeTimeLabel(607,087) returns '10:07' (formatArray defaults to ['mm','ss'])
+ * makeTimeLabel(607,087,['m':'s']) returns '10:7'
+ * makeTimeLabel(607,087,['m':'s','C']) returns '10:7.09'
+ */
+ makeTimeLabel: function(time, formatArray){
+ if(!(formatArray)){
+ formatArray = ['mm','ss'];
+ }
+ //marker offset is in float format second.decimalPart
+ var pInt = parseInt;
+ var round = Math.round;
+ var factor = 60*24;
+ var hours = pInt(time/factor);
+ time-=hours*factor;
+ factor = 60;
+ var minutes = pInt(time/factor);
+ time-=minutes*factor;
+ var seconds = pInt(time);
+ time-=seconds;
+
+ //here below the function to format a number
+ //ceilAsPowerOfTen is the ceil specifiedas integer indicating the relative power of ten
+ //(0: return the number as it is, 1: format as "0#" and so on)
+ //Examples: format(6) = "6", format(6,1)= "06", format(23,1)= "23"
+
+ //first of all, instantiate the power function once (and not inside the function or function's loop):
+ //note that minimumNumberOfDigits lower to 2 returns integer as it is
+ var mpow = Math.pow; //instantiate mpow once
+ var format = function(integer,minimumNumberOfDigits){
+ var n = ""+integer;
+ var zero = "0"; //instantiating once increases performances???
+ for(var i=1; i< minimumNumberOfDigits; i++){
+ if(integer<mpow(10,i)){
+ n = zero+n;
+ }
+ }
+ return n;
+ }
+ var ret = [];
+ for(var i =0; i<formatArray.length; i++){
+ var f = formatArray[i];
+ var separator = ":";
+ if(f=='h'){
+ ret[i]=hours;
+ }else if(f=='hh'){
+ ret[i]=format(hours,2);
+ }else if(f=='m'){
+ ret[i]=minutes;
+ }else if(f=='mm'){
+ ret[i]=format(minutes,2);
+ }else if(f=='s'){
+ ret[i]=seconds;
+ }else if(f=='ss'){
+ ret[i]=format(seconds,2);
+ }else if(f=='S'){
+ separator = ".";
+ ret[i]=format(round(time*1000),3);
+ }else if(f=='C'){
+ separator = ".";
+ ret[i]=format(round(time*100),2);
+ }else if(f=='D'){
+ separator = ".";
+ ret[i]= round(time*10);
+ }
+ if(i>0){
+ ret[i] = separator+ret[i];
+ }
+ }
+ return ret.join("");
+ },
+
+ cssPrefix : 'ts-',
+ $J : jQuery,
+ debugging : true,
+ debug : function(message) {
+ if (this.debugging && typeof console != 'undefined' && console.log) {
+ console.log(message);
+ }
+ },
+ //init constructor. Define the 'bind' and 'fire' (TODO: rename as 'trigger'?) methods
+ //we do it in the init function so that we can set a private variable storing all
+ //listeners. This means we have to re-write all methods
+ init: function(){
+
+ //the map for listeners. Must be declared in the init as it's private and NOT shared by all instances
+ //(ie, every instance has its own copy)
+ this.listenersMap={};
+ //follows jquery bind. Same as adding a listener for a key
+
+ },
+
+ /**
+ *methods defining listeners, events fire and bind:
+ */
+ bind : function(key, callback, optionalThisArgInCallback){
+ if(!(callback && callback instanceof Function)){
+ this.debug('cannot bind '+key+' to callback: the latter is null or not a function');
+ return;
+ }
+ var listenersMap = this.listenersMap;
+ var keyAlreadyRegistered = (key in listenersMap);
+ if(!keyAlreadyRegistered){
+ listenersMap[key] = [];
+ }
+ listenersMap[key].push({
+ callback:callback,
+ optionalThisArgInCallback:optionalThisArgInCallback
+ });
+ },
+ unbind : function(){
+ var listenersMap = this.listenersMap;
+ if(arguments.length>0){
+ var key = arguments[0];
+ if(key in listenersMap){
+ delete listenersMap[key];
+ }
+ }else{
+ for(key in listenersMap){
+ delete listenersMap[key];
+ }
+ }
+ },
+ fire : function(key, dataArgument){
+ var listenersMap = this.listenersMap;
+ if(!(key in listenersMap)){
+ this.debug(key+' fired but no binding associated to it');
+ return;
+ }
+ var callbacks = listenersMap[key];
+ var len = callbacks && callbacks.length ? callbacks.length : 0;
+ for(var i=0; i<len; i++){
+ var obj = callbacks[i];
+ if('optionalThisArgInCallback' in obj){
+ obj.callback.apply(obj.optionalThisArgInCallback, [dataArgument]);
+ }else{
+ obj.callback(dataArgument);
+ }
+ }
+ }
+
+});
+
+//re-implemented array for easier access/modification of markers:
+//Ruler, MArkerMap and MarkerMapDiv implement this class
+var TimesideArray = TimesideClass.extend({
+ init: function(optionalArray){
+ this._super();
+ //here methods that CANNOT be overridden
+ var me= optionalArray ? optionalArray : [];
+ //note that this method written here OVERRIDES the same method written outside init in the children!!!!
+ this.toArray = function(returnACopy){
+ if(returnACopy){
+ consolelog('copying array');
+ var ret = [];
+ for(var i=0; i<me.length; i++){
+ ret.push(me[i]);
+ }
+ return ret;
+ }
+ return me;
+ }
+ this.length = me.length; //in order to match the javascript array property
+ },
+ length:0, //implement it as public property to be consistent with Array length property. Be careful however to NOT TO modify directly this property!!!
+ //adds at the end of the array. If index is missing the object is appended at the end
+ add : function(object, index){
+ var array = this.toArray();
+ if(arguments.length<2){
+ index = array.length;
+ }
+ array.splice(index,0,object);
+ this.length = array.length; //note that length is a property and must be updated!!!
+ return object;
+ },
+ //removes item at index, returns the removed element
+ remove : function(index){
+ var array = this.toArray();
+ var ret = array.splice(index,1)[0];
+ this.length = array.length; //note that length is a property and must be updated!!!
+ return ret;
+ },
+ //Iterate over the array, with the same syntax of jQuery.each, ie, executes a function(index,element)
+ //for each element from startIndexInclusive to
+ //endIndexExclusive.
+ //The only required argument is callback:
+ //1) each(callback) iterates over all elements executing callback
+ //2) each(m, callback) iterates over the elements from m executing callback
+ //3) each(m,n,callback) iterates over the elements from m (inclusive) to n-1 (inclusive) executing callback
+
+ //NOTE: writing each : function(startInclusive, endExclusive, callback) throws an error in chrome, as the last
+ //argument (even if it is a function) is a number. Why?????
+ //Anyway, we must write the function arguments as empty
+ each : function(){
+ // consolelog(arguments.length+' arguments passed. Details: ');
+ // for(var j=0; j<arguments.length; j++){
+ // consolelog('arguments['+ j+']: ');consolelog(arguments[j]);
+ // }
+ var startInclusive, endExclusive, callback;
+
+ var arg = arguments;
+ var len = arg.length;
+ var l = this.length;
+ switch(len){
+ case 0:
+ this.debug('each called without arguments!!!');
+ return;
+ case 1:
+ //callback = arg[0];
+ startInclusive = 0;
+ endExclusive = l;
+ break;
+ case 2:
+ if(arg[0] >= l){
+ return;
+ }
+ startInclusive = arg[0]=== undefined ? 0 : arg[0];
+ endExclusive = l;
+ //callback = arg[len-1];
+ break;
+ default:
+ startInclusive = arg[0]=== undefined ? 0 : arg[0];
+ endExclusive = arg[1]=== undefined ? l : arg[1];
+ //callback = arg[len-1];
+ }
+ callback = arg[len-1];
+ if(!(callback instanceof Function)){
+ this.debug('callback NOT a function!!!');
+ return;
+ }
+ var me =this.toArray();
+ for(var i = startInclusive; i<endExclusive; i++){
+ callback(i,me[i]);
+ }
+
+ },
+
+ //clears the array and the events associated to it, ie removes all its elements and calls unbind(). Returns the array of the removed elements
+ clear: function(){
+ this.unbind();
+ var me = this.toArray();
+ var l = me.length;
+ this.length = 0;
+ if(l==0){
+ return [];
+ }
+ return me.splice(0,l);
+ },
+ //moves the element from position [from] to position [to]. Shifts all elements
+ //from position [to] (inclusive) of one position. Note that the elemnt at position from is first removed
+ //and then inserted at position to. Therefore,
+ //if to==from+1 the element is not moved. Returns from if the element
+ //is not moved, i.e. either in the case above, or when:
+ //1) from or to are not integers or from or to are lower than zero or greater than the array length.
+ //in any other case, returns the index of the element moved, which is not necessarily to:
+ //It is, if to<from, otherwise (to>from+1) is to-1
+ move : function(from, to){
+ var pInt = parseInt;
+ if(pInt(from)!==from || pInt(to)!==to){
+ return from;
+ }
+ var me =this.toArray();
+ var len = me.length;
+ if((from<0 || from>len)||(to<0 || to>len)){
+ return from;
+ }
+ //if we moved left to right, the insertion index is actually
+ //newIndex-1, as we must also consider the removal of the object at index from
+ if(to>from){
+ to--;
+ }
+ if(from != to){
+ var elm = me.splice(from,1)[0];
+ me.splice(to,0,elm);
+ }
+ return to;
+ }
+});
+
+
+/*
+ * Sets a "tab look" on some elements of the page. Takes at least 3 arguments, at most 5:
+ * 1st argument: an array (or a jquery object) of html elements, ususally anchors, representing the tabs
+ * 2nd argument: an array (or a jquery object) of html elements, ususally divs, representing the containers to be shown/hidden when
+ * clicking the tabs. The n-th tab will set the n-th container to visible, hiding the others. So order is important. Note that if tabs
+ * or container are jQuery objects, the html elements inside them are sorted according to the document order. That's why tabs and
+ * container can be passed also as javascript arrays, so that the binding n-th tab -> n-th container can be decided by the user
+ * regardeless on how elements are written on the page, if already present
+ * 3rd argument: the selected index. If missing it defaults to zero.
+ * 4th argument: selectedtab class. Applies to the selected tab after click of one tab. If missing, nothing is done
+ * 5th argument the unselectedtab class. Applies to all tabs not selected after click of one tab. If missing, nothing is done
+ *
+ * NOTE: The last 2 arguments are mostly for customizing the tab "visual look", as some css elements (eg, (position, top, zIndex)
+ * are set inside the code and cannot be changed, as they are mandatory to let tab anchor behave like desktop application tabs. Note also
+ * that every tab container is set to 'visible' by means of jQuery.show()
+ *
+ * Examples:
+ * setUpPlayerTabs([jQuery('#tab1),jQuery('#tab1)], [jQuery('#div1),jQuery('#div2)], 1);
+ * sets the elements with id '#tab1' and '#tab2' as tab and assign the click events to them so that clicking tab_1 will show '#div_1'
+ * (and hide '#div2') and viceversa for '#tab2'. The selected index will be 1 (second tab '#tab2')
+*/
+function setUpPlayerTabs() {//called from within controller.js once all markers have been loaded.
+ //this is because we need all divs to be visible to calculate size. selIndex is optional, it defaults to 0
+ //
+
+ var $J = jQuery;
+ var tabs_ = arguments[0];
+ var divs_ = arguments[1]; //they might be ctually any content, div is a shoertand
+
+ //converting arguments to array: tabs
+ var tabs=[];
+ if(tabs_ instanceof $J){
+ tabs_.each(function(i,elm){
+ tabs.push(elm);
+ });
+ }else{
+ tabs = tabs_;
+ }
+ //set the overflow property of the parent tab to visible, otherwise scrollbars are displayed
+ //and the trick of setting position:relative+top:1px+zIndices (see css) doesnt work)
+ $J(tabs).each(function(i,tab){
+ var t = $J(tab).attr('href','#');
+ t.show(); //might be hidden
+ //set necessary style for the tab appearence:
+ var overflow = t.parent().css('overflow');
+ if(overflow && overflow != 'visible'){
+ t.parent().css('overflow','visible');
+ }
+ });
+ //converting arguments to array: divs
+ var divs=[];
+ if(divs_ instanceof $J){
+ divs_.each(function(i,elm){
+ divs.push(elm);
+ });
+ }else{
+ divs = divs_;
+ }
+
+ //reading remaing arguments (if any)
+ var selIndex = arguments.length>2 ? arguments[2] : 0;
+ var selectedTabClass = arguments.length>3 ? arguments[3] : undefined;
+ var unselectedTabClass = arguments.length>4 ? arguments[4] : undefined;
+
+ //function to be associate to every click on the tab (see below)
+ var tabClicked = function(index) {
+ for(var i=0; i<tabs.length; i++){
+ var t = $J(tabs[i]);
+
+ var div = $J(divs[i]);
+ // consolelog(t.attr('id')+' is '+(i==index ? 'showing ' : 'hiding ')+div.attr('id'));
+ var addClass = i==index ? selectedTabClass : unselectedTabClass;
+ var removeClass = i==index ? unselectedTabClass : selectedTabClass;
+ if(removeClass){
+ t.removeClass(removeClass);
+ }
+ if(addClass){
+ t.addClass(addClass);
+ }
+
+ //relevant css. Will override any css set in stylesheets
+ t.css({
+ 'position':'relative',
+ 'top':'1px',
+ 'zIndex': (i==index ? '10' : '0')
+ });
+
+ if(i===index){
+ div.fadeIn('slow');
+ }else{
+ div.hide();
+ }
+ }
+ };
+
+ //bind clicks on tabs to the function just created
+ for (var i=0;i<tabs.length;i++){
+ // introduce a new scope (round brackets)
+ //otherwise i is retrieved from the current scope and will be always equal to tabs.length
+ //due to this loop
+ (function(tabIndex){
+ $J(tabs[i]).click(function(){
+ tabClicked(tabIndex);
+ return false;//returning false avoids scroll of the anchor to the top of the page
+ });
+ })(i);
+ }
+
+ //select the tab
+ $(tabs[selIndex]).trigger("click");
+}
\ No newline at end of file
--- /dev/null
+/* This notice must be untouched at all times.\r
+\r
+wz_jsgraphics.js v. 3.03\r
+The latest version is available at\r
+http://www.walterzorn.com\r
+or http://www.devira.com\r
+or http://www.walterzorn.de\r
+\r
+Copyright (c) 2002-2004 Walter Zorn. All rights reserved.\r
+Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )\r
+Last modified: 28. 1. 2008\r
+\r
+Performance optimizations for Internet Explorer\r
+by Thomas Frank and John Holdsworth.\r
+fillPolygon method implemented by Matthieu Haller.\r
+\r
+High Performance JavaScript Graphics Library.\r
+Provides methods\r
+- to draw lines, rectangles, ellipses, polygons\r
+ with specifiable line thickness,\r
+- to fill rectangles, polygons, ellipses and arcs\r
+- to draw text.\r
+NOTE: Operations, functions and branching have rather been optimized\r
+to efficiency and speed than to shortness of source code.\r
+\r
+LICENSE: LGPL\r
+\r
+This library is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU Lesser General Public\r
+License (LGPL) as published by the Free Software Foundation; either\r
+version 2.1 of the License, or (at your option) any later version.\r
+\r
+This library is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+Lesser General Public License for more details.\r
+\r
+You should have received a copy of the GNU Lesser General Public\r
+License along with this library; if not, write to the Free Software\r
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,\r
+or see http://www.gnu.org/copyleft/lesser.html\r
+*/\r
+\r
+\r
+var jg_ok, jg_ie, jg_fast, jg_dom, jg_moz;\r
+\r
+\r
+function _chkDHTM(x, i)\r
+{\r
+ x = document.body || null;\r
+ jg_ie = x && typeof x.insertAdjacentHTML != "undefined" && document.createElement;\r
+ jg_dom = (x && !jg_ie &&\r
+ typeof x.appendChild != "undefined" &&\r
+ typeof document.createRange != "undefined" &&\r
+ typeof (i = document.createRange()).setStartBefore != "undefined" &&\r
+ typeof i.createContextualFragment != "undefined");\r
+ jg_fast = jg_ie && document.all && !window.opera;\r
+ jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";\r
+ jg_ok = !!(jg_ie || jg_dom);\r
+}\r
+\r
+function _pntCnvDom()\r
+{\r
+ var x = this.wnd.document.createRange();\r
+ x.setStartBefore(this.cnv);\r
+ x = x.createContextualFragment(jg_fast? this._htmRpc() : this.htm);\r
+ if(this.cnv) this.cnv.appendChild(x);\r
+ this.htm = "";\r
+}\r
+\r
+function _pntCnvIe()\r
+{\r
+ if(this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this._htmRpc() : this.htm);\r
+ this.htm = "";\r
+}\r
+\r
+function _pntDoc()\r
+{\r
+ this.wnd.document.write(jg_fast? this._htmRpc() : this.htm);\r
+ this.htm = '';\r
+}\r
+\r
+function _pntN()\r
+{\r
+ ;\r
+}\r
+\r
+function _mkDiv(x, y, w, h)\r
+{\r
+ this.htm += '<div style="position:absolute;'+\r
+ 'left:' + x + 'px;'+\r
+ 'top:' + y + 'px;'+\r
+ 'width:' + w + 'px;'+\r
+ 'height:' + h + 'px;'+\r
+ 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
+ 'background-color:' + this.color +\r
+ (!jg_moz? ';overflow:hidden' : '')+\r
+ ';"><\/div>';\r
+}\r
+\r
+function _mkDivIe(x, y, w, h)\r
+{\r
+ this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';\r
+}\r
+\r
+function _mkDivPrt(x, y, w, h)\r
+{\r
+ this.htm += '<div style="position:absolute;'+\r
+ 'border-left:' + w + 'px solid ' + this.color + ';'+\r
+ 'left:' + x + 'px;'+\r
+ 'top:' + y + 'px;'+\r
+ 'width:0px;'+\r
+ 'height:' + h + 'px;'+\r
+ 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
+ 'background-color:' + this.color +\r
+ (!jg_moz? ';overflow:hidden' : '')+\r
+ ';"><\/div>';\r
+}\r
+\r
+var _regex = /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;\r
+function _htmRpc()\r
+{\r
+ return this.htm.replace(\r
+ _regex,\r
+ '<div style="overflow:hidden;position:absolute;background-color:'+\r
+ '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');\r
+}\r
+\r
+function _htmPrtRpc()\r
+{\r
+ return this.htm.replace(\r
+ _regex,\r
+ '<div style="overflow:hidden;position:absolute;background-color:'+\r
+ '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');\r
+}\r
+\r
+function _mkLin(x1, y1, x2, y2)\r
+{\r
+ if(x1 > x2)\r
+ {\r
+ var _x2 = x2;\r
+ var _y2 = y2;\r
+ x2 = x1;\r
+ y2 = y1;\r
+ x1 = _x2;\r
+ y1 = _y2;\r
+ }\r
+ var dx = x2-x1, dy = Math.abs(y2-y1),\r
+ x = x1, y = y1,\r
+ yIncr = (y1 > y2)? -1 : 1;\r
+\r
+ if(dx >= dy)\r
+ {\r
+ var pr = dy<<1,\r
+ pru = pr - (dx<<1),\r
+ p = pr-dx,\r
+ ox = x;\r
+ while(dx > 0)\r
+ {--dx;\r
+ ++x;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(ox, y, x-ox, 1);\r
+ y += yIncr;\r
+ p += pru;\r
+ ox = x;\r
+ }\r
+ else p += pr;\r
+ }\r
+ this._mkDiv(ox, y, x2-ox+1, 1);\r
+ }\r
+\r
+ else\r
+ {\r
+ var pr = dx<<1,\r
+ pru = pr - (dy<<1),\r
+ p = pr-dy,\r
+ oy = y;\r
+ if(y2 <= y1)\r
+ {\r
+ while(dy > 0)\r
+ {--dy;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(x++, y, 1, oy-y+1);\r
+ y += yIncr;\r
+ p += pru;\r
+ oy = y;\r
+ }\r
+ else\r
+ {\r
+ y += yIncr;\r
+ p += pr;\r
+ }\r
+ }\r
+ this._mkDiv(x2, y2, 1, oy-y2+1);\r
+ }\r
+ else\r
+ {\r
+ while(dy > 0)\r
+ {--dy;\r
+ y += yIncr;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(x++, oy, 1, y-oy);\r
+ p += pru;\r
+ oy = y;\r
+ }\r
+ else p += pr;\r
+ }\r
+ this._mkDiv(x2, oy, 1, y2-oy+1);\r
+ }\r
+ }\r
+}\r
+\r
+function _mkLin2D(x1, y1, x2, y2)\r
+{\r
+ if(x1 > x2)\r
+ {\r
+ var _x2 = x2;\r
+ var _y2 = y2;\r
+ x2 = x1;\r
+ y2 = y1;\r
+ x1 = _x2;\r
+ y1 = _y2;\r
+ }\r
+ var dx = x2-x1, dy = Math.abs(y2-y1),\r
+ x = x1, y = y1,\r
+ yIncr = (y1 > y2)? -1 : 1;\r
+\r
+ var s = this.stroke;\r
+ if(dx >= dy)\r
+ {\r
+ if(dx > 0 && s-3 > 0)\r
+ {\r
+ var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;\r
+ _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
+ }\r
+ else var _s = s;\r
+ var ad = Math.ceil(s/2);\r
+\r
+ var pr = dy<<1,\r
+ pru = pr - (dx<<1),\r
+ p = pr-dx,\r
+ ox = x;\r
+ while(dx > 0)\r
+ {--dx;\r
+ ++x;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(ox, y, x-ox+ad, _s);\r
+ y += yIncr;\r
+ p += pru;\r
+ ox = x;\r
+ }\r
+ else p += pr;\r
+ }\r
+ this._mkDiv(ox, y, x2-ox+ad+1, _s);\r
+ }\r
+\r
+ else\r
+ {\r
+ if(s-3 > 0)\r
+ {\r
+ var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;\r
+ _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
+ }\r
+ else var _s = s;\r
+ var ad = Math.round(s/2);\r
+\r
+ var pr = dx<<1,\r
+ pru = pr - (dy<<1),\r
+ p = pr-dy,\r
+ oy = y;\r
+ if(y2 <= y1)\r
+ {\r
+ ++ad;\r
+ while(dy > 0)\r
+ {--dy;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(x++, y, _s, oy-y+ad);\r
+ y += yIncr;\r
+ p += pru;\r
+ oy = y;\r
+ }\r
+ else\r
+ {\r
+ y += yIncr;\r
+ p += pr;\r
+ }\r
+ }\r
+ this._mkDiv(x2, y2, _s, oy-y2+ad);\r
+ }\r
+ else\r
+ {\r
+ while(dy > 0)\r
+ {--dy;\r
+ y += yIncr;\r
+ if(p > 0)\r
+ {\r
+ this._mkDiv(x++, oy, _s, y-oy+ad);\r
+ p += pru;\r
+ oy = y;\r
+ }\r
+ else p += pr;\r
+ }\r
+ this._mkDiv(x2, oy, _s, y2-oy+ad+1);\r
+ }\r
+ }\r
+}\r
+\r
+function _mkLinDott(x1, y1, x2, y2)\r
+{\r
+ if(x1 > x2)\r
+ {\r
+ var _x2 = x2;\r
+ var _y2 = y2;\r
+ x2 = x1;\r
+ y2 = y1;\r
+ x1 = _x2;\r
+ y1 = _y2;\r
+ }\r
+ var dx = x2-x1, dy = Math.abs(y2-y1),\r
+ x = x1, y = y1,\r
+ yIncr = (y1 > y2)? -1 : 1,\r
+ drw = true;\r
+ if(dx >= dy)\r
+ {\r
+ var pr = dy<<1,\r
+ pru = pr - (dx<<1),\r
+ p = pr-dx;\r
+ while(dx > 0)\r
+ {--dx;\r
+ if(drw) this._mkDiv(x, y, 1, 1);\r
+ drw = !drw;\r
+ if(p > 0)\r
+ {\r
+ y += yIncr;\r
+ p += pru;\r
+ }\r
+ else p += pr;\r
+ ++x;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ var pr = dx<<1,\r
+ pru = pr - (dy<<1),\r
+ p = pr-dy;\r
+ while(dy > 0)\r
+ {--dy;\r
+ if(drw) this._mkDiv(x, y, 1, 1);\r
+ drw = !drw;\r
+ y += yIncr;\r
+ if(p > 0)\r
+ {\r
+ ++x;\r
+ p += pru;\r
+ }\r
+ else p += pr;\r
+ }\r
+ }\r
+ if(drw) this._mkDiv(x, y, 1, 1);\r
+}\r
+\r
+function _mkOv(left, top, width, height)\r
+{\r
+ var a = (++width)>>1, b = (++height)>>1,\r
+ wod = width&1, hod = height&1,\r
+ cx = left+a, cy = top+b,\r
+ x = 0, y = b,\r
+ ox = 0, oy = b,\r
+ aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
+ st = (aa2>>1)*(1-(b<<1)) + bb2,\r
+ tt = (bb2>>1) - aa2*((b<<1)-1),\r
+ w, h;\r
+ while(y > 0)\r
+ {\r
+ if(st < 0)\r
+ {\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0)\r
+ {\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ w = x-ox;\r
+ h = oy-y;\r
+ if((w&2) && (h&2))\r
+ {\r
+ this._mkOvQds(cx, cy, x-2, y+2, 1, 1, wod, hod);\r
+ this._mkOvQds(cx, cy, x-1, y+1, 1, 1, wod, hod);\r
+ }\r
+ else this._mkOvQds(cx, cy, x-1, oy, w, h, wod, hod);\r
+ ox = x;\r
+ oy = y;\r
+ }\r
+ else\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ }\r
+ }\r
+ w = a-ox+1;\r
+ h = (oy<<1)+hod;\r
+ y = cy-oy;\r
+ this._mkDiv(cx-a, y, w, h);\r
+ this._mkDiv(cx+ox+wod-1, y, w, h);\r
+}\r
+\r
+function _mkOv2D(left, top, width, height)\r
+{\r
+ var s = this.stroke;\r
+ width += s+1;\r
+ height += s+1;\r
+ var a = width>>1, b = height>>1,\r
+ wod = width&1, hod = height&1,\r
+ cx = left+a, cy = top+b,\r
+ x = 0, y = b,\r
+ aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
+ st = (aa2>>1)*(1-(b<<1)) + bb2,\r
+ tt = (bb2>>1) - aa2*((b<<1)-1);\r
+\r
+ if(s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))\r
+ {\r
+ var ox = 0, oy = b,\r
+ w, h,\r
+ pxw;\r
+ while(y > 0)\r
+ {\r
+ if(st < 0)\r
+ {\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0)\r
+ {\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ w = x-ox;\r
+ h = oy-y;\r
+\r
+ if(w-1)\r
+ {\r
+ pxw = w+1+(s&1);\r
+ h = s;\r
+ }\r
+ else if(h-1)\r
+ {\r
+ pxw = s;\r
+ h += 1+(s&1);\r
+ }\r
+ else pxw = h = s;\r
+ this._mkOvQds(cx, cy, x-1, oy, pxw, h, wod, hod);\r
+ ox = x;\r
+ oy = y;\r
+ }\r
+ else\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ }\r
+ }\r
+ this._mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);\r
+ this._mkDiv(cx+a+wod-s, cy-oy, s, (oy<<1)+hod);\r
+ }\r
+\r
+ else\r
+ {\r
+ var _a = (width-(s<<1))>>1,\r
+ _b = (height-(s<<1))>>1,\r
+ _x = 0, _y = _b,\r
+ _aa2 = (_a*_a)<<1, _aa4 = _aa2<<1, _bb2 = (_b*_b)<<1, _bb4 = _bb2<<1,\r
+ _st = (_aa2>>1)*(1-(_b<<1)) + _bb2,\r
+ _tt = (_bb2>>1) - _aa2*((_b<<1)-1),\r
+\r
+ pxl = new Array(),\r
+ pxt = new Array(),\r
+ _pxb = new Array();\r
+ pxl[0] = 0;\r
+ pxt[0] = b;\r
+ _pxb[0] = _b-1;\r
+ while(y > 0)\r
+ {\r
+ if(st < 0)\r
+ {\r
+ pxl[pxl.length] = x;\r
+ pxt[pxt.length] = y;\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0)\r
+ {\r
+ pxl[pxl.length] = x;\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ pxt[pxt.length] = y;\r
+ }\r
+ else\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ }\r
+\r
+ if(_y > 0)\r
+ {\r
+ if(_st < 0)\r
+ {\r
+ _st += _bb2*((_x<<1)+3);\r
+ _tt += _bb4*(++_x);\r
+ _pxb[_pxb.length] = _y-1;\r
+ }\r
+ else if(_tt < 0)\r
+ {\r
+ _st += _bb2*((_x<<1)+3) - _aa4*(_y-1);\r
+ _tt += _bb4*(++_x) - _aa2*(((_y--)<<1)-3);\r
+ _pxb[_pxb.length] = _y-1;\r
+ }\r
+ else\r
+ {\r
+ _tt -= _aa2*((_y<<1)-3);\r
+ _st -= _aa4*(--_y);\r
+ _pxb[_pxb.length-1]--;\r
+ }\r
+ }\r
+ }\r
+\r
+ var ox = -wod, oy = b,\r
+ _oy = _pxb[0],\r
+ l = pxl.length,\r
+ w, h;\r
+ for(var i = 0; i < l; i++)\r
+ {\r
+ if(typeof _pxb[i] != "undefined")\r
+ {\r
+ if(_pxb[i] < _oy || pxt[i] < oy)\r
+ {\r
+ x = pxl[i];\r
+ this._mkOvQds(cx, cy, x, oy, x-ox, oy-_oy, wod, hod);\r
+ ox = x;\r
+ oy = pxt[i];\r
+ _oy = _pxb[i];\r
+ }\r
+ }\r
+ else\r
+ {\r
+ x = pxl[i];\r
+ this._mkDiv(cx-x, cy-oy, 1, (oy<<1)+hod);\r
+ this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
+ ox = x;\r
+ oy = pxt[i];\r
+ }\r
+ }\r
+ this._mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);\r
+ this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
+ }\r
+}\r
+\r
+function _mkOvDott(left, top, width, height)\r
+{\r
+ var a = (++width)>>1, b = (++height)>>1,\r
+ wod = width&1, hod = height&1, hodu = hod^1,\r
+ cx = left+a, cy = top+b,\r
+ x = 0, y = b,\r
+ aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
+ st = (aa2>>1)*(1-(b<<1)) + bb2,\r
+ tt = (bb2>>1) - aa2*((b<<1)-1),\r
+ drw = true;\r
+ while(y > 0)\r
+ {\r
+ if(st < 0)\r
+ {\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0)\r
+ {\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ }\r
+ else\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ }\r
+ if(drw && y >= hodu) this._mkOvQds(cx, cy, x, y, 1, 1, wod, hod);\r
+ drw = !drw;\r
+ }\r
+}\r
+\r
+function _mkRect(x, y, w, h)\r
+{\r
+ var s = this.stroke;\r
+ this._mkDiv(x, y, w, s);\r
+ this._mkDiv(x+w, y, s, h);\r
+ this._mkDiv(x, y+h, w+s, s);\r
+ this._mkDiv(x, y+s, s, h-s);\r
+}\r
+\r
+function _mkRectDott(x, y, w, h)\r
+{\r
+ this.drawLine(x, y, x+w, y);\r
+ this.drawLine(x+w, y, x+w, y+h);\r
+ this.drawLine(x, y+h, x+w, y+h);\r
+ this.drawLine(x, y, x, y+h);\r
+}\r
+\r
+function jsgFont()\r
+{\r
+ this.PLAIN = 'font-weight:normal;';\r
+ this.BOLD = 'font-weight:bold;';\r
+ this.ITALIC = 'font-style:italic;';\r
+ this.ITALIC_BOLD = this.ITALIC + this.BOLD;\r
+ this.BOLD_ITALIC = this.ITALIC_BOLD;\r
+}\r
+var Font = new jsgFont();\r
+\r
+function jsgStroke()\r
+{\r
+ this.DOTTED = -1;\r
+}\r
+var Stroke = new jsgStroke();\r
+\r
+function jsGraphics(cnv, wnd)\r
+{\r
+ this.setColor = function(x)\r
+ {\r
+ this.color = x.toLowerCase();\r
+ };\r
+\r
+ this.setStroke = function(x)\r
+ {\r
+ this.stroke = x;\r
+ if(!(x+1))\r
+ {\r
+ this.drawLine = _mkLinDott;\r
+ this._mkOv = _mkOvDott;\r
+ this.drawRect = _mkRectDott;\r
+ }\r
+ else if(x-1 > 0)\r
+ {\r
+ this.drawLine = _mkLin2D;\r
+ this._mkOv = _mkOv2D;\r
+ this.drawRect = _mkRect;\r
+ }\r
+ else\r
+ {\r
+ this.drawLine = _mkLin;\r
+ this._mkOv = _mkOv;\r
+ this.drawRect = _mkRect;\r
+ }\r
+ };\r
+\r
+ this.setPrintable = function(arg)\r
+ {\r
+ this.printable = arg;\r
+ if(jg_fast)\r
+ {\r
+ this._mkDiv = _mkDivIe;\r
+ this._htmRpc = arg? _htmPrtRpc : _htmRpc;\r
+ }\r
+ else this._mkDiv = arg? _mkDivPrt : _mkDiv;\r
+ };\r
+\r
+ this.setFont = function(fam, sz, sty)\r
+ {\r
+ this.ftFam = fam;\r
+ this.ftSz = sz;\r
+ this.ftSty = sty || Font.PLAIN;\r
+ };\r
+\r
+ this.drawPolyline = this.drawPolyLine = function(x, y)\r
+ {\r
+ for (var i=x.length - 1; i;)\r
+ {--i;\r
+ this.drawLine(x[i], y[i], x[i+1], y[i+1]);\r
+ }\r
+ };\r
+\r
+ this.fillRect = function(x, y, w, h)\r
+ {\r
+ this._mkDiv(x, y, w, h);\r
+ };\r
+\r
+ this.drawPolygon = function(x, y)\r
+ {\r
+ this.drawPolyline(x, y);\r
+ this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);\r
+ };\r
+\r
+ this.drawEllipse = this.drawOval = function(x, y, w, h)\r
+ {\r
+ this._mkOv(x, y, w, h);\r
+ };\r
+\r
+ this.fillEllipse = this.fillOval = function(left, top, w, h)\r
+ {\r
+ var a = w>>1, b = h>>1,\r
+ wod = w&1, hod = h&1,\r
+ cx = left+a, cy = top+b,\r
+ x = 0, y = b, oy = b,\r
+ aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
+ st = (aa2>>1)*(1-(b<<1)) + bb2,\r
+ tt = (bb2>>1) - aa2*((b<<1)-1),\r
+ xl, dw, dh;\r
+ if(w) while(y > 0)\r
+ {\r
+ if(st < 0)\r
+ {\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0)\r
+ {\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ xl = cx-x;\r
+ dw = (x<<1)+wod;\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ dh = oy-y;\r
+ this._mkDiv(xl, cy-oy, dw, dh);\r
+ this._mkDiv(xl, cy+y+hod, dw, dh);\r
+ oy = y;\r
+ }\r
+ else\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ }\r
+ }\r
+ this._mkDiv(cx-a, cy-oy, w, (oy<<1)+hod);\r
+ };\r
+\r
+ this.fillArc = function(iL, iT, iW, iH, fAngA, fAngZ)\r
+ {\r
+ var a = iW>>1, b = iH>>1,\r
+ iOdds = (iW&1) | ((iH&1) << 16),\r
+ cx = iL+a, cy = iT+b,\r
+ x = 0, y = b, ox = x, oy = y,\r
+ aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
+ st = (aa2>>1)*(1-(b<<1)) + bb2,\r
+ tt = (bb2>>1) - aa2*((b<<1)-1),\r
+ // Vars for radial boundary lines\r
+ xEndA, yEndA, xEndZ, yEndZ,\r
+ iSects = (1 << (Math.floor((fAngA %= 360.0)/180.0) << 3))\r
+ | (2 << (Math.floor((fAngZ %= 360.0)/180.0) << 3))\r
+ | ((fAngA >= fAngZ) << 16),\r
+ aBndA = new Array(b+1), aBndZ = new Array(b+1);\r
+ \r
+ // Set up radial boundary lines\r
+ fAngA *= Math.PI/180.0;\r
+ fAngZ *= Math.PI/180.0;\r
+ xEndA = cx+Math.round(a*Math.cos(fAngA));\r
+ yEndA = cy+Math.round(-b*Math.sin(fAngA));\r
+ _mkLinVirt(aBndA, cx, cy, xEndA, yEndA);\r
+ xEndZ = cx+Math.round(a*Math.cos(fAngZ));\r
+ yEndZ = cy+Math.round(-b*Math.sin(fAngZ));\r
+ _mkLinVirt(aBndZ, cx, cy, xEndZ, yEndZ);\r
+\r
+ while(y > 0)\r
+ {\r
+ if(st < 0) // Advance x\r
+ {\r
+ st += bb2*((x<<1)+3);\r
+ tt += bb4*(++x);\r
+ }\r
+ else if(tt < 0) // Advance x and y\r
+ {\r
+ st += bb2*((x<<1)+3) - aa4*(y-1);\r
+ ox = x;\r
+ tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
+ this._mkArcDiv(ox, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
+ oy = y;\r
+ }\r
+ else // Advance y\r
+ {\r
+ tt -= aa2*((y<<1)-3);\r
+ st -= aa4*(--y);\r
+ if(y && (aBndA[y] != aBndA[y-1] || aBndZ[y] != aBndZ[y-1]))\r
+ {\r
+ this._mkArcDiv(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
+ ox = x;\r
+ oy = y;\r
+ }\r
+ }\r
+ }\r
+ this._mkArcDiv(x, 0, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
+ if(iOdds >> 16) // Odd height\r
+ {\r
+ if(iSects >> 16) // Start-angle > end-angle\r
+ {\r
+ var xl = (yEndA <= cy || yEndZ > cy)? (cx - x) : cx;\r
+ this._mkDiv(xl, cy, x + cx - xl + (iOdds & 0xffff), 1);\r
+ }\r
+ else if((iSects & 0x01) && yEndZ > cy)\r
+ this._mkDiv(cx - x, cy, x, 1);\r
+ }\r
+ };\r
+\r
+/* fillPolygon method, implemented by Matthieu Haller.\r
+This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.\r
+C source of GD 1.8.4 found at http://www.boutell.com/gd/\r
+\r
+THANKS to Kirsten Schulz for the polygon fixes!\r
+\r
+The intersection finding technique of this code could be improved\r
+by remembering the previous intertersection, and by using the slope.\r
+That could help to adjust intersections to produce a nice\r
+interior_extrema. */\r
+ this.fillPolygon = function(array_x, array_y)\r
+ {\r
+ var i;\r
+ var y;\r
+ var miny, maxy;\r
+ var x1, y1;\r
+ var x2, y2;\r
+ var ind1, ind2;\r
+ var ints;\r
+\r
+ var n = array_x.length;\r
+ if(!n) return;\r
+\r
+ miny = array_y[0];\r
+ maxy = array_y[0];\r
+ for(i = 1; i < n; i++)\r
+ {\r
+ if(array_y[i] < miny)\r
+ miny = array_y[i];\r
+\r
+ if(array_y[i] > maxy)\r
+ maxy = array_y[i];\r
+ }\r
+ for(y = miny; y <= maxy; y++)\r
+ {\r
+ var polyInts = new Array();\r
+ ints = 0;\r
+ for(i = 0; i < n; i++)\r
+ {\r
+ if(!i)\r
+ {\r
+ ind1 = n-1;\r
+ ind2 = 0;\r
+ }\r
+ else\r
+ {\r
+ ind1 = i-1;\r
+ ind2 = i;\r
+ }\r
+ y1 = array_y[ind1];\r
+ y2 = array_y[ind2];\r
+ if(y1 < y2)\r
+ {\r
+ x1 = array_x[ind1];\r
+ x2 = array_x[ind2];\r
+ }\r
+ else if(y1 > y2)\r
+ {\r
+ y2 = array_y[ind1];\r
+ y1 = array_y[ind2];\r
+ x2 = array_x[ind1];\r
+ x1 = array_x[ind2];\r
+ }\r
+ else continue;\r
+\r
+ // Modified 11. 2. 2004 Walter Zorn\r
+ if((y >= y1) && (y < y2))\r
+ polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
+\r
+ else if((y == maxy) && (y > y1) && (y <= y2))\r
+ polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
+ }\r
+ polyInts.sort(_CompInt);\r
+ for(i = 0; i < ints; i+=2)\r
+ this._mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);\r
+ }\r
+ };\r
+\r
+ this.drawString = function(txt, x, y)\r
+ {\r
+ this.htm += '<div style="position:absolute;white-space:nowrap;'+\r
+ 'left:' + x + 'px;'+\r
+ 'top:' + y + 'px;'+\r
+ 'font-family:' + this.ftFam + ';'+\r
+ 'font-size:' + this.ftSz + ';'+\r
+ 'color:' + this.color + ';' + this.ftSty + '">'+\r
+ txt +\r
+ '<\/div>';\r
+ };\r
+\r
+/* drawStringRect() added by Rick Blommers.\r
+Allows to specify the size of the text rectangle and to align the\r
+text both horizontally (e.g. right) and vertically within that rectangle */\r
+ this.drawStringRect = function(txt, x, y, width, halign)\r
+ {\r
+ this.htm += '<div style="position:absolute;overflow:hidden;'+\r
+ 'left:' + x + 'px;'+\r
+ 'top:' + y + 'px;'+\r
+ 'width:'+width +'px;'+\r
+ 'text-align:'+halign+';'+\r
+ 'font-family:' + this.ftFam + ';'+\r
+ 'font-size:' + this.ftSz + ';'+\r
+ 'color:' + this.color + ';' + this.ftSty + '">'+\r
+ txt +\r
+ '<\/div>';\r
+ };\r
+\r
+ this.drawImage = function(imgSrc, x, y, w, h, a)\r
+ {\r
+ this.htm += '<div style="position:absolute;'+\r
+ 'left:' + x + 'px;'+\r
+ 'top:' + y + 'px;'+\r
+ // w (width) and h (height) arguments are now optional.\r
+ // Added by Mahmut Keygubatli, 14.1.2008\r
+ (w? ('width:' + w + 'px;') : '') +\r
+ (h? ('height:' + h + 'px;'):'')+'">'+\r
+ '<img src="' + imgSrc +'"'+ (w ? (' width="' + w + '"'):'')+ (h ? (' height="' + h + '"'):'') + (a? (' '+a) : '') + '>'+\r
+ '<\/div>';\r
+ };\r
+\r
+ this.clear = function()\r
+ {\r
+ this.htm = "";\r
+ if(this.cnv) this.cnv.innerHTML = "";\r
+ };\r
+\r
+ this._mkOvQds = function(cx, cy, x, y, w, h, wod, hod)\r
+ {\r
+ var xl = cx - x, xr = cx + x + wod - w, yt = cy - y, yb = cy + y + hod - h;\r
+ if(xr > xl+w)\r
+ {\r
+ this._mkDiv(xr, yt, w, h);\r
+ this._mkDiv(xr, yb, w, h);\r
+ }\r
+ else\r
+ w = xr - xl + w;\r
+ this._mkDiv(xl, yt, w, h);\r
+ this._mkDiv(xl, yb, w, h);\r
+ };\r
+ \r
+ this._mkArcDiv = function(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects)\r
+ {\r
+ var xrDef = cx + x + (iOdds & 0xffff), y2, h = oy - y, xl, xr, w;\r
+\r
+ if(!h) h = 1;\r
+ x = cx - x;\r
+\r
+ if(iSects & 0xff0000) // Start-angle > end-angle\r
+ {\r
+ y2 = cy - y - h;\r
+ if(iSects & 0x00ff)\r
+ {\r
+ if(iSects & 0x02)\r
+ {\r
+ xl = Math.max(x, aBndZ[y]);\r
+ w = xrDef - xl;\r
+ if(w > 0) this._mkDiv(xl, y2, w, h);\r
+ }\r
+ if(iSects & 0x01)\r
+ {\r
+ xr = Math.min(xrDef, aBndA[y]);\r
+ w = xr - x;\r
+ if(w > 0) this._mkDiv(x, y2, w, h);\r
+ }\r
+ }\r
+ else\r
+ this._mkDiv(x, y2, xrDef - x, h);\r
+ y2 = cy + y + (iOdds >> 16);\r
+ if(iSects & 0xff00)\r
+ {\r
+ if(iSects & 0x0100)\r
+ {\r
+ xl = Math.max(x, aBndA[y]);\r
+ w = xrDef - xl;\r
+ if(w > 0) this._mkDiv(xl, y2, w, h);\r
+ }\r
+ if(iSects & 0x0200)\r
+ {\r
+ xr = Math.min(xrDef, aBndZ[y]);\r
+ w = xr - x;\r
+ if(w > 0) this._mkDiv(x, y2, w, h);\r
+ }\r
+ }\r
+ else\r
+ this._mkDiv(x, y2, xrDef - x, h);\r
+ }\r
+ else\r
+ {\r
+ if(iSects & 0x00ff)\r
+ {\r
+ if(iSects & 0x02)\r
+ xl = Math.max(x, aBndZ[y]);\r
+ else\r
+ xl = x;\r
+ if(iSects & 0x01)\r
+ xr = Math.min(xrDef, aBndA[y]);\r
+ else\r
+ xr = xrDef;\r
+ y2 = cy - y - h;\r
+ w = xr - xl;\r
+ if(w > 0) this._mkDiv(xl, y2, w, h);\r
+ }\r
+ if(iSects & 0xff00)\r
+ {\r
+ if(iSects & 0x0100)\r
+ xl = Math.max(x, aBndA[y]);\r
+ else\r
+ xl = x;\r
+ if(iSects & 0x0200)\r
+ xr = Math.min(xrDef, aBndZ[y]);\r
+ else\r
+ xr = xrDef;\r
+ y2 = cy + y + (iOdds >> 16);\r
+ w = xr - xl;\r
+ if(w > 0) this._mkDiv(xl, y2, w, h);\r
+ }\r
+ }\r
+ };\r
+\r
+ this.setStroke(1);\r
+ this.setFont("verdana,geneva,helvetica,sans-serif", "12px", Font.PLAIN);\r
+ this.color = "#000000";\r
+ this.htm = "";\r
+ this.wnd = wnd || window;\r
+\r
+ if(!jg_ok) _chkDHTM();\r
+ if(jg_ok)\r
+ {\r
+ if(cnv)\r
+ {\r
+ if(typeof(cnv) == "string")\r
+ this.cont = document.all? (this.wnd.document.all[cnv] || null)\r
+ : document.getElementById? (this.wnd.document.getElementById(cnv) || null)\r
+ : null;\r
+ else if(cnv == window.document)\r
+ this.cont = document.getElementsByTagName("body")[0];\r
+ // If cnv is a direct reference to a canvas DOM node\r
+ // (option suggested by Andreas Luleich)\r
+ else this.cont = cnv;\r
+ // Create new canvas inside container DIV. Thus the drawing and clearing\r
+ // methods won't interfere with the container's inner html.\r
+ // Solution suggested by Vladimir.\r
+ this.cnv = this.wnd.document.createElement("div");\r
+ this.cnv.style.fontSize=0;\r
+ this.cont.appendChild(this.cnv);\r
+ this.paint = jg_dom? _pntCnvDom : _pntCnvIe;\r
+ }\r
+ else\r
+ this.paint = _pntDoc;\r
+ }\r
+ else\r
+ this.paint = _pntN;\r
+\r
+ this.setPrintable(false);\r
+}\r
+\r
+function _mkLinVirt(aLin, x1, y1, x2, y2)\r
+{\r
+ var dx = Math.abs(x2-x1), dy = Math.abs(y2-y1),\r
+ x = x1, y = y1,\r
+ xIncr = (x1 > x2)? -1 : 1,\r
+ yIncr = (y1 > y2)? -1 : 1,\r
+ p,\r
+ i = 0;\r
+ if(dx >= dy)\r
+ {\r
+ var pr = dy<<1,\r
+ pru = pr - (dx<<1);\r
+ p = pr-dx;\r
+ while(dx > 0)\r
+ {--dx;\r
+ if(p > 0) // Increment y\r
+ {\r
+ aLin[i++] = x;\r
+ y += yIncr;\r
+ p += pru;\r
+ }\r
+ else p += pr;\r
+ x += xIncr;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ var pr = dx<<1,\r
+ pru = pr - (dy<<1);\r
+ p = pr-dy;\r
+ while(dy > 0)\r
+ {--dy;\r
+ y += yIncr;\r
+ aLin[i++] = x;\r
+ if(p > 0) // Increment x\r
+ {\r
+ x += xIncr;\r
+ p += pru;\r
+ }\r
+ else p += pr;\r
+ }\r
+ }\r
+ for(var len = aLin.length, i = len-i; i;)\r
+ aLin[len-(i--)] = x;\r
+};\r
+\r
+function _CompInt(x, y)\r
+{\r
+ return(x - y);\r
+}\r
+\r
+++ /dev/null
-(function(){
-/*
- * jQuery 1.2.6 - New Wave Javascript
- *
- * Copyright (c) 2008 John Resig (jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
- * $Rev: 5685 $
- */
-
-// Map over jQuery in case of overwrite
-var _jQuery = window.jQuery,
-// Map over the $ in case of overwrite
- _$ = window.$;
-
-var jQuery = window.jQuery = window.$ = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context );
-};
-
-// A simple way to check for HTML strings or ID strings
-// (both of which we optimize for)
-var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
-
-// Is it a simple selector
- isSimple = /^.[^:#\[\.]*$/,
-
-// Will speed up references to undefined, and allows munging its name.
- undefined;
-
-jQuery.fn = jQuery.prototype = {
- init: function( selector, context ) {
- // Make sure that a selection was provided
- selector = selector || document;
-
- // Handle $(DOMElement)
- if ( selector.nodeType ) {
- this[0] = selector;
- this.length = 1;
- return this;
- }
- // Handle HTML strings
- if ( typeof selector == "string" ) {
- // Are we dealing with HTML string or an ID?
- var match = quickExpr.exec( selector );
-
- // Verify a match, and that no context was specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] )
- selector = jQuery.clean( [ match[1] ], context );
-
- // HANDLE: $("#id")
- else {
- var elem = document.getElementById( match[3] );
-
- // Make sure an element was located
- if ( elem ){
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id != match[3] )
- return jQuery().find( selector );
-
- // Otherwise, we inject the element directly into the jQuery object
- return jQuery( elem );
- }
- selector = [];
- }
-
- // HANDLE: $(expr, [context])
- // (which is just equivalent to: $(content).find(expr)
- } else
- return jQuery( context ).find( selector );
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) )
- return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
-
- return this.setArray(jQuery.makeArray(selector));
- },
-
- // The current version of jQuery being used
- jquery: "1.2.6",
-
- // The number of elements contained in the matched element set
- size: function() {
- return this.length;
- },
-
- // The number of elements contained in the matched element set
- length: 0,
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num == undefined ?
-
- // Return a 'clean' array
- jQuery.makeArray( this ) :
-
- // Return just the object
- this[ num ];
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
- // Build a new jQuery matched element set
- var ret = jQuery( elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Force the current matched set of elements to become
- // the specified array of elements (destroying the stack in the process)
- // You should use pushStack() in order to do this, but maintain the stack
- setArray: function( elems ) {
- // Resetting the length to 0, then using the native Array push
- // is a super-fast way to populate an object with array-like properties
- this.length = 0;
- Array.prototype.push.apply( this, elems );
-
- return this;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
- var ret = -1;
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem && elem.jquery ? elem[0] : elem
- , this );
- },
-
- attr: function( name, value, type ) {
- var options = name;
-
- // Look for the case where we're accessing a style value
- if ( name.constructor == String )
- if ( value === undefined )
- return this[0] && jQuery[ type || "attr" ]( this[0], name );
-
- else {
- options = {};
- options[ name ] = value;
- }
-
- // Check to see if we're setting style values
- return this.each(function(i){
- // Set all the styles
- for ( name in options )
- jQuery.attr(
- type ?
- this.style :
- this,
- name, jQuery.prop( this, options[ name ], type, i, name )
- );
- });
- },
-
- css: function( key, value ) {
- // ignore negative width and height values
- if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
- value = undefined;
- return this.attr( key, value, "curCSS" );
- },
-
- text: function( text ) {
- if ( typeof text != "object" && text != null )
- return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
- var ret = "";
-
- jQuery.each( text || this, function(){
- jQuery.each( this.childNodes, function(){
- if ( this.nodeType != 8 )
- ret += this.nodeType != 1 ?
- this.nodeValue :
- jQuery.fn.text( [ this ] );
- });
- });
-
- return ret;
- },
-
- wrapAll: function( html ) {
- if ( this[0] )
- // The elements to wrap the target around
- jQuery( html, this[0].ownerDocument )
- .clone()
- .insertBefore( this[0] )
- .map(function(){
- var elem = this;
-
- while ( elem.firstChild )
- elem = elem.firstChild;
-
- return elem;
- })
- .append(this);
-
- return this;
- },
-
- wrapInner: function( html ) {
- return this.each(function(){
- jQuery( this ).contents().wrapAll( html );
- });
- },
-
- wrap: function( html ) {
- return this.each(function(){
- jQuery( this ).wrapAll( html );
- });
- },
-
- append: function() {
- return this.domManip(arguments, true, false, function(elem){
- if (this.nodeType == 1)
- this.appendChild( elem );
- });
- },
-
- prepend: function() {
- return this.domManip(arguments, true, true, function(elem){
- if (this.nodeType == 1)
- this.insertBefore( elem, this.firstChild );
- });
- },
-
- before: function() {
- return this.domManip(arguments, false, false, function(elem){
- this.parentNode.insertBefore( elem, this );
- });
- },
-
- after: function() {
- return this.domManip(arguments, false, true, function(elem){
- this.parentNode.insertBefore( elem, this.nextSibling );
- });
- },
-
- end: function() {
- return this.prevObject || jQuery( [] );
- },
-
- find: function( selector ) {
- var elems = jQuery.map(this, function(elem){
- return jQuery.find( selector, elem );
- });
-
- return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
- jQuery.unique( elems ) :
- elems );
- },
-
- clone: function( events ) {
- // Do the clone
- var ret = this.map(function(){
- if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
- // IE copies events bound via attachEvent when
- // using cloneNode. Calling detachEvent on the
- // clone will also remove the events from the orignal
- // In order to get around this, we use innerHTML.
- // Unfortunately, this means some modifications to
- // attributes in IE that are actually only stored
- // as properties will not be copied (such as the
- // the name attribute on an input).
- var clone = this.cloneNode(true),
- container = document.createElement("div");
- container.appendChild(clone);
- return jQuery.clean([container.innerHTML])[0];
- } else
- return this.cloneNode(true);
- });
-
- // Need to set the expando to null on the cloned set if it exists
- // removeData doesn't work here, IE removes it from the original as well
- // this is primarily for IE but the data expando shouldn't be copied over in any browser
- var clone = ret.find("*").andSelf().each(function(){
- if ( this[ expando ] != undefined )
- this[ expando ] = null;
- });
-
- // Copy the events from the original to the clone
- if ( events === true )
- this.find("*").andSelf().each(function(i){
- if (this.nodeType == 3)
- return;
- var events = jQuery.data( this, "events" );
-
- for ( var type in events )
- for ( var handler in events[ type ] )
- jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
- });
-
- // Return the cloned set
- return ret;
- },
-
- filter: function( selector ) {
- return this.pushStack(
- jQuery.isFunction( selector ) &&
- jQuery.grep(this, function(elem, i){
- return selector.call( elem, i );
- }) ||
-
- jQuery.multiFilter( selector, this ) );
- },
-
- not: function( selector ) {
- if ( selector.constructor == String )
- // test special case where just one selector is passed in
- if ( isSimple.test( selector ) )
- return this.pushStack( jQuery.multiFilter( selector, this, true ) );
- else
- selector = jQuery.multiFilter( selector, this );
-
- var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
- return this.filter(function() {
- return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
- });
- },
-
- add: function( selector ) {
- return this.pushStack( jQuery.unique( jQuery.merge(
- this.get(),
- typeof selector == 'string' ?
- jQuery( selector ) :
- jQuery.makeArray( selector )
- )));
- },
-
- is: function( selector ) {
- return !!selector && jQuery.multiFilter( selector, this ).length > 0;
- },
-
- hasClass: function( selector ) {
- return this.is( "." + selector );
- },
-
- val: function( value ) {
- if ( value == undefined ) {
-
- if ( this.length ) {
- var elem = this[0];
-
- // We need to handle select boxes special
- if ( jQuery.nodeName( elem, "select" ) ) {
- var index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type == "select-one";
-
- // Nothing was selected
- if ( index < 0 )
- return null;
-
- // Loop through all the selected options
- for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
- var option = options[ i ];
-
- if ( option.selected ) {
- // Get the specifc value for the option
- value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
-
- // We don't need an array for one selects
- if ( one )
- return value;
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- return values;
-
- // Everything else, we just grab the value
- } else
- return (this[0].value || "").replace(/\r/g, "");
-
- }
-
- return undefined;
- }
-
- if( value.constructor == Number )
- value += '';
-
- return this.each(function(){
- if ( this.nodeType != 1 )
- return;
-
- if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
- this.checked = (jQuery.inArray(this.value, value) >= 0 ||
- jQuery.inArray(this.name, value) >= 0);
-
- else if ( jQuery.nodeName( this, "select" ) ) {
- var values = jQuery.makeArray(value);
-
- jQuery( "option", this ).each(function(){
- this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
- jQuery.inArray( this.text, values ) >= 0);
- });
-
- if ( !values.length )
- this.selectedIndex = -1;
-
- } else
- this.value = value;
- });
- },
-
- html: function( value ) {
- return value == undefined ?
- (this[0] ?
- this[0].innerHTML :
- null) :
- this.empty().append( value );
- },
-
- replaceWith: function( value ) {
- return this.after( value ).remove();
- },
-
- eq: function( i ) {
- return this.slice( i, i + 1 );
- },
-
- slice: function() {
- return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function(elem, i){
- return callback.call( elem, i, elem );
- }));
- },
-
- andSelf: function() {
- return this.add( this.prevObject );
- },
-
- data: function( key, value ){
- var parts = key.split(".");
- parts[1] = parts[1] ? "." + parts[1] : "";
-
- if ( value === undefined ) {
- var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
- if ( data === undefined && this.length )
- data = jQuery.data( this[0], key );
-
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
- } else
- return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
- jQuery.data( this, key, value );
- });
- },
-
- removeData: function( key ){
- return this.each(function(){
- jQuery.removeData( this, key );
- });
- },
-
- domManip: function( args, table, reverse, callback ) {
- var clone = this.length > 1, elems;
-
- return this.each(function(){
- if ( !elems ) {
- elems = jQuery.clean( args, this.ownerDocument );
-
- if ( reverse )
- elems.reverse();
- }
-
- var obj = this;
-
- if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
- obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
-
- var scripts = jQuery( [] );
-
- jQuery.each(elems, function(){
- var elem = clone ?
- jQuery( this ).clone( true )[0] :
- this;
-
- // execute all scripts after the elements have been injected
- if ( jQuery.nodeName( elem, "script" ) )
- scripts = scripts.add( elem );
- else {
- // Remove any inner scripts for later evaluation
- if ( elem.nodeType == 1 )
- scripts = scripts.add( jQuery( "script", elem ).remove() );
-
- // Inject the elements into the document
- callback.call( obj, elem );
- }
- });
-
- scripts.each( evalScript );
- });
- }
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-function evalScript( i, elem ) {
- if ( elem.src )
- jQuery.ajax({
- url: elem.src,
- async: false,
- dataType: "script"
- });
-
- else
- jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
- if ( elem.parentNode )
- elem.parentNode.removeChild( elem );
-}
-
-function now(){
- return +new Date;
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
- // copy reference to target object
- var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
- // Handle a deep copy situation
- if ( target.constructor == Boolean ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target != "object" && typeof target != "function" )
- target = {};
-
- // extend jQuery itself if only one argument is passed
- if ( length == i ) {
- target = this;
- --i;
- }
-
- for ( ; i < length; i++ )
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null )
- // Extend the base object
- for ( var name in options ) {
- var src = target[ name ], copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy )
- continue;
-
- // Recurse if we're merging object values
- if ( deep && copy && typeof copy == "object" && !copy.nodeType )
- target[ name ] = jQuery.extend( deep,
- // Never move original objects, clone them
- src || ( copy.length != null ? [ ] : { } )
- , copy );
-
- // Don't bring in undefined values
- else if ( copy !== undefined )
- target[ name ] = copy;
-
- }
-
- // Return the modified object
- return target;
-};
-
-var expando = "jQuery" + now(), uuid = 0, windowData = {},
- // exclude the following css properties to add px
- exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
- // cache defaultView
- defaultView = document.defaultView || {};
-
-jQuery.extend({
- noConflict: function( deep ) {
- window.$ = _$;
-
- if ( deep )
- window.jQuery = _jQuery;
-
- return jQuery;
- },
-
- // See test/unit/core.js for details concerning this function.
- isFunction: function( fn ) {
- return !!fn && typeof fn != "string" && !fn.nodeName &&
- fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
- },
-
- // check if an element is in a (or is an) XML document
- isXMLDoc: function( elem ) {
- return elem.documentElement && !elem.body ||
- elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
- },
-
- // Evalulates a script in a global context
- globalEval: function( data ) {
- data = jQuery.trim( data );
-
- if ( data ) {
- // Inspired by code by Andrea Giammarchi
- // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
- var head = document.getElementsByTagName("head")[0] || document.documentElement,
- script = document.createElement("script");
-
- script.type = "text/javascript";
- if ( jQuery.browser.msie )
- script.text = data;
- else
- script.appendChild( document.createTextNode( data ) );
-
- // Use insertBefore instead of appendChild to circumvent an IE6 bug.
- // This arises when a base node is used (#2709).
- head.insertBefore( script, head.firstChild );
- head.removeChild( script );
- }
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
- },
-
- cache: {},
-
- data: function( elem, name, data ) {
- elem = elem == window ?
- windowData :
- elem;
-
- var id = elem[ expando ];
-
- // Compute a unique ID for the element
- if ( !id )
- id = elem[ expando ] = ++uuid;
-
- // Only generate the data cache if we're
- // trying to access or manipulate it
- if ( name && !jQuery.cache[ id ] )
- jQuery.cache[ id ] = {};
-
- // Prevent overriding the named cache with undefined values
- if ( data !== undefined )
- jQuery.cache[ id ][ name ] = data;
-
- // Return the named cache data, or the ID for the element
- return name ?
- jQuery.cache[ id ][ name ] :
- id;
- },
-
- removeData: function( elem, name ) {
- elem = elem == window ?
- windowData :
- elem;
-
- var id = elem[ expando ];
-
- // If we want to remove a specific section of the element's data
- if ( name ) {
- if ( jQuery.cache[ id ] ) {
- // Remove the section of cache data
- delete jQuery.cache[ id ][ name ];
-
- // If we've removed all the data, remove the element's cache
- name = "";
-
- for ( name in jQuery.cache[ id ] )
- break;
-
- if ( !name )
- jQuery.removeData( elem );
- }
-
- // Otherwise, we want to remove all of the element's data
- } else {
- // Clean up the element expando
- try {
- delete elem[ expando ];
- } catch(e){
- // IE has trouble directly removing the expando
- // but it's ok with using removeAttribute
- if ( elem.removeAttribute )
- elem.removeAttribute( expando );
- }
-
- // Completely remove the data cache
- delete jQuery.cache[ id ];
- }
- },
-
- // args is for internal usage only
- each: function( object, callback, args ) {
- var name, i = 0, length = object.length;
-
- if ( args ) {
- if ( length == undefined ) {
- for ( name in object )
- if ( callback.apply( object[ name ], args ) === false )
- break;
- } else
- for ( ; i < length; )
- if ( callback.apply( object[ i++ ], args ) === false )
- break;
-
- // A special, fast, case for the most common use of each
- } else {
- if ( length == undefined ) {
- for ( name in object )
- if ( callback.call( object[ name ], name, object[ name ] ) === false )
- break;
- } else
- for ( var value = object[0];
- i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
- }
-
- return object;
- },
-
- prop: function( elem, value, type, i, name ) {
- // Handle executable functions
- if ( jQuery.isFunction( value ) )
- value = value.call( elem, i );
-
- // Handle passing in a number to a CSS property
- return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
- value + "px" :
- value;
- },
-
- className: {
- // internal only, use addClass("class")
- add: function( elem, classNames ) {
- jQuery.each((classNames || "").split(/\s+/), function(i, className){
- if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
- elem.className += (elem.className ? " " : "") + className;
- });
- },
-
- // internal only, use removeClass("class")
- remove: function( elem, classNames ) {
- if (elem.nodeType == 1)
- elem.className = classNames != undefined ?
- jQuery.grep(elem.className.split(/\s+/), function(className){
- return !jQuery.className.has( classNames, className );
- }).join(" ") :
- "";
- },
-
- // internal only, use hasClass("class")
- has: function( elem, className ) {
- return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
- }
- },
-
- // A method for quickly swapping in/out CSS properties to get correct calculations
- swap: function( elem, options, callback ) {
- var old = {};
- // Remember the old values, and insert the new ones
- for ( var name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- callback.call( elem );
-
- // Revert the old values
- for ( var name in options )
- elem.style[ name ] = old[ name ];
- },
-
- css: function( elem, name, force ) {
- if ( name == "width" || name == "height" ) {
- var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-
- function getWH() {
- val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
- var padding = 0, border = 0;
- jQuery.each( which, function() {
- padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
- border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
- });
- val -= Math.round(padding + border);
- }
-
- if ( jQuery(elem).is(":visible") )
- getWH();
- else
- jQuery.swap( elem, props, getWH );
-
- return Math.max(0, val);
- }
-
- return jQuery.curCSS( elem, name, force );
- },
-
- curCSS: function( elem, name, force ) {
- var ret, style = elem.style;
-
- // A helper method for determining if an element's values are broken
- function color( elem ) {
- if ( !jQuery.browser.safari )
- return false;
-
- // defaultView is cached
- var ret = defaultView.getComputedStyle( elem, null );
- return !ret || ret.getPropertyValue("color") == "";
- }
-
- // We need to handle opacity special in IE
- if ( name == "opacity" && jQuery.browser.msie ) {
- ret = jQuery.attr( style, "opacity" );
-
- return ret == "" ?
- "1" :
- ret;
- }
- // Opera sometimes will give the wrong display answer, this fixes it, see #2037
- if ( jQuery.browser.opera && name == "display" ) {
- var save = style.outline;
- style.outline = "0 solid black";
- style.outline = save;
- }
-
- // Make sure we're using the right name for getting the float value
- if ( name.match( /float/i ) )
- name = styleFloat;
-
- if ( !force && style && style[ name ] )
- ret = style[ name ];
-
- else if ( defaultView.getComputedStyle ) {
-
- // Only "float" is needed here
- if ( name.match( /float/i ) )
- name = "float";
-
- name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
- var computedStyle = defaultView.getComputedStyle( elem, null );
-
- if ( computedStyle && !color( elem ) )
- ret = computedStyle.getPropertyValue( name );
-
- // If the element isn't reporting its values properly in Safari
- // then some display: none elements are involved
- else {
- var swap = [], stack = [], a = elem, i = 0;
-
- // Locate all of the parent display: none elements
- for ( ; a && color(a); a = a.parentNode )
- stack.unshift(a);
-
- // Go through and make them visible, but in reverse
- // (It would be better if we knew the exact display type that they had)
- for ( ; i < stack.length; i++ )
- if ( color( stack[ i ] ) ) {
- swap[ i ] = stack[ i ].style.display;
- stack[ i ].style.display = "block";
- }
-
- // Since we flip the display style, we have to handle that
- // one special, otherwise get the value
- ret = name == "display" && swap[ stack.length - 1 ] != null ?
- "none" :
- ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
-
- // Finally, revert the display styles back
- for ( i = 0; i < swap.length; i++ )
- if ( swap[ i ] != null )
- stack[ i ].style.display = swap[ i ];
- }
-
- // We should always get a number back from opacity
- if ( name == "opacity" && ret == "" )
- ret = "1";
-
- } else if ( elem.currentStyle ) {
- var camelCase = name.replace(/\-(\w)/g, function(all, letter){
- return letter.toUpperCase();
- });
-
- ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
- // If we're not dealing with a regular pixel number
- // but a number that has a weird ending, we need to convert it to pixels
- if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
- // Remember the original values
- var left = style.left, rsLeft = elem.runtimeStyle.left;
-
- // Put in the new values to get a computed value out
- elem.runtimeStyle.left = elem.currentStyle.left;
- style.left = ret || 0;
- ret = style.pixelLeft + "px";
-
- // Revert the changed values
- style.left = left;
- elem.runtimeStyle.left = rsLeft;
- }
- }
-
- return ret;
- },
-
- clean: function( elems, context ) {
- var ret = [];
- context = context || document;
- // !context.createElement fails in IE with an error but returns typeof 'object'
- if (typeof context.createElement == 'undefined')
- context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
- jQuery.each(elems, function(i, elem){
- if ( !elem )
- return;
-
- if ( elem.constructor == Number )
- elem += '';
-
- // Convert html string into DOM nodes
- if ( typeof elem == "string" ) {
- // Fix "XHTML"-style tags in all browsers
- elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
- return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
- all :
- front + "></" + tag + ">";
- });
-
- // Trim whitespace, otherwise indexOf won't work as expected
- var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
-
- var wrap =
- // option or optgroup
- !tags.indexOf("<opt") &&
- [ 1, "<select multiple='multiple'>", "</select>" ] ||
-
- !tags.indexOf("<leg") &&
- [ 1, "<fieldset>", "</fieldset>" ] ||
-
- tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
- [ 1, "<table>", "</table>" ] ||
-
- !tags.indexOf("<tr") &&
- [ 2, "<table><tbody>", "</tbody></table>" ] ||
-
- // <thead> matched above
- (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
- [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-
- !tags.indexOf("<col") &&
- [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
- // IE can't serialize <link> and <script> tags normally
- jQuery.browser.msie &&
- [ 1, "div<div>", "</div>" ] ||
-
- [ 0, "", "" ];
-
- // Go to html and back, then peel off extra wrappers
- div.innerHTML = wrap[1] + elem + wrap[2];
-
- // Move to the right depth
- while ( wrap[0]-- )
- div = div.lastChild;
-
- // Remove IE's autoinserted <tbody> from table fragments
- if ( jQuery.browser.msie ) {
-
- // String was a <table>, *may* have spurious <tbody>
- var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
- div.firstChild && div.firstChild.childNodes :
-
- // String was a bare <thead> or <tfoot>
- wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
- div.childNodes :
- [];
-
- for ( var j = tbody.length - 1; j >= 0 ; --j )
- if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
- tbody[ j ].parentNode.removeChild( tbody[ j ] );
-
- // IE completely kills leading whitespace when innerHTML is used
- if ( /^\s/.test( elem ) )
- div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-
- }
-
- elem = jQuery.makeArray( div.childNodes );
- }
-
- if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
- return;
-
- if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
- ret.push( elem );
-
- else
- ret = jQuery.merge( ret, elem );
-
- });
-
- return ret;
- },
-
- attr: function( elem, name, value ) {
- // don't set attributes on text and comment nodes
- if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
- return undefined;
-
- var notxml = !jQuery.isXMLDoc( elem ),
- // Whether we are setting (or getting)
- set = value !== undefined,
- msie = jQuery.browser.msie;
-
- // Try to normalize/fix the name
- name = notxml && jQuery.props[ name ] || name;
-
- // Only do all the following if this is a node (faster for style)
- // IE elem.getAttribute passes even for style
- if ( elem.tagName ) {
-
- // These attributes require special treatment
- var special = /href|src|style/.test( name );
-
- // Safari mis-reports the default selected property of a hidden option
- // Accessing the parent's selectedIndex property fixes it
- if ( name == "selected" && jQuery.browser.safari )
- elem.parentNode.selectedIndex;
-
- // If applicable, access the attribute via the DOM 0 way
- if ( name in elem && notxml && !special ) {
- if ( set ){
- // We can't allow the type property to be changed (since it causes problems in IE)
- if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
- throw "type property can't be changed";
-
- elem[ name ] = value;
- }
-
- // browsers index elements by id/name on forms, give priority to attributes.
- if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
- return elem.getAttributeNode( name ).nodeValue;
-
- return elem[ name ];
- }
-
- if ( msie && notxml && name == "style" )
- return jQuery.attr( elem.style, "cssText", value );
-
- if ( set )
- // convert the value to a string (all browsers do this but IE) see #1070
- elem.setAttribute( name, "" + value );
-
- var attr = msie && notxml && special
- // Some attributes require a special call on IE
- ? elem.getAttribute( name, 2 )
- : elem.getAttribute( name );
-
- // Non-existent attributes return null, we normalize to undefined
- return attr === null ? undefined : attr;
- }
-
- // elem is actually elem.style ... set the style
-
- // IE uses filters for opacity
- if ( msie && name == "opacity" ) {
- if ( set ) {
- // IE has trouble with opacity if it does not have layout
- // Force it by setting the zoom level
- elem.zoom = 1;
-
- // Set the alpha filter to set the opacity
- elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
- (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
- }
-
- return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
- (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
- "";
- }
-
- name = name.replace(/-([a-z])/ig, function(all, letter){
- return letter.toUpperCase();
- });
-
- if ( set )
- elem[ name ] = value;
-
- return elem[ name ];
- },
-
- trim: function( text ) {
- return (text || "").replace( /^\s+|\s+$/g, "" );
- },
-
- makeArray: function( array ) {
- var ret = [];
-
- if( array != null ){
- var i = array.length;
- //the window, strings and functions also have 'length'
- if( i == null || array.split || array.setInterval || array.call )
- ret[0] = array;
- else
- while( i )
- ret[--i] = array[i];
- }
-
- return ret;
- },
-
- inArray: function( elem, array ) {
- for ( var i = 0, length = array.length; i < length; i++ )
- // Use === because on IE, window == document
- if ( array[ i ] === elem )
- return i;
-
- return -1;
- },
-
- merge: function( first, second ) {
- // We have to loop this way because IE & Opera overwrite the length
- // expando of getElementsByTagName
- var i = 0, elem, pos = first.length;
- // Also, we need to make sure that the correct elements are being returned
- // (IE returns comment nodes in a '*' query)
- if ( jQuery.browser.msie ) {
- while ( elem = second[ i++ ] )
- if ( elem.nodeType != 8 )
- first[ pos++ ] = elem;
-
- } else
- while ( elem = second[ i++ ] )
- first[ pos++ ] = elem;
-
- return first;
- },
-
- unique: function( array ) {
- var ret = [], done = {};
-
- try {
-
- for ( var i = 0, length = array.length; i < length; i++ ) {
- var id = jQuery.data( array[ i ] );
-
- if ( !done[ id ] ) {
- done[ id ] = true;
- ret.push( array[ i ] );
- }
- }
-
- } catch( e ) {
- ret = array;
- }
-
- return ret;
- },
-
- grep: function( elems, callback, inv ) {
- var ret = [];
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( var i = 0, length = elems.length; i < length; i++ )
- if ( !inv != !callback( elems[ i ], i ) )
- ret.push( elems[ i ] );
-
- return ret;
- },
-
- map: function( elems, callback ) {
- var ret = [];
-
- // Go through the array, translating each of the items to their
- // new value (or values).
- for ( var i = 0, length = elems.length; i < length; i++ ) {
- var value = callback( elems[ i ], i );
-
- if ( value != null )
- ret[ ret.length ] = value;
- }
-
- return ret.concat.apply( [], ret );
- }
-});
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
- version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
- safari: /webkit/.test( userAgent ),
- opera: /opera/.test( userAgent ),
- msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
- mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-var styleFloat = jQuery.browser.msie ?
- "styleFloat" :
- "cssFloat";
-
-jQuery.extend({
- // Check to see if the W3C box model is being used
- boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
-
- props: {
- "for": "htmlFor",
- "class": "className",
- "float": styleFloat,
- cssFloat: styleFloat,
- styleFloat: styleFloat,
- readonly: "readOnly",
- maxlength: "maxLength",
- cellspacing: "cellSpacing"
- }
-});
-
-jQuery.each({
- parent: function(elem){return elem.parentNode;},
- parents: function(elem){return jQuery.dir(elem,"parentNode");},
- next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
- prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
- nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
- prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
- siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
- children: function(elem){return jQuery.sibling(elem.firstChild);},
- contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
- jQuery.fn[ name ] = function( selector ) {
- var ret = jQuery.map( this, fn );
-
- if ( selector && typeof selector == "string" )
- ret = jQuery.multiFilter( selector, ret );
-
- return this.pushStack( jQuery.unique( ret ) );
- };
-});
-
-jQuery.each({
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
-}, function(name, original){
- jQuery.fn[ name ] = function() {
- var args = arguments;
-
- return this.each(function(){
- for ( var i = 0, length = args.length; i < length; i++ )
- jQuery( args[ i ] )[ original ]( this );
- });
- };
-});
-
-jQuery.each({
- removeAttr: function( name ) {
- jQuery.attr( this, name, "" );
- if (this.nodeType == 1)
- this.removeAttribute( name );
- },
-
- addClass: function( classNames ) {
- jQuery.className.add( this, classNames );
- },
-
- removeClass: function( classNames ) {
- jQuery.className.remove( this, classNames );
- },
-
- toggleClass: function( classNames ) {
- jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
- },
-
- remove: function( selector ) {
- if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
- // Prevent memory leaks
- jQuery( "*", this ).add(this).each(function(){
- jQuery.event.remove(this);
- jQuery.removeData(this);
- });
- if (this.parentNode)
- this.parentNode.removeChild( this );
- }
- },
-
- empty: function() {
- // Remove element nodes and prevent memory leaks
- jQuery( ">*", this ).remove();
-
- // Remove any remaining nodes
- while ( this.firstChild )
- this.removeChild( this.firstChild );
- }
-}, function(name, fn){
- jQuery.fn[ name ] = function(){
- return this.each( fn, arguments );
- };
-});
-
-jQuery.each([ "Height", "Width" ], function(i, name){
- var type = name.toLowerCase();
-
- jQuery.fn[ type ] = function( size ) {
- // Get window width or height
- return this[0] == window ?
- // Opera reports document.body.client[Width/Height] properly in both quirks and standards
- jQuery.browser.opera && document.body[ "client" + name ] ||
-
- // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
- jQuery.browser.safari && window[ "inner" + name ] ||
-
- // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
- document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
-
- // Get document width or height
- this[0] == document ?
- // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
- Math.max(
- Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
- Math.max(document.body["offset" + name], document.documentElement["offset" + name])
- ) :
-
- // Get or set width or height on the element
- size == undefined ?
- // Get width or height on the element
- (this.length ? jQuery.css( this[0], type ) : null) :
-
- // Set the width or height on the element (default to pixels if value is unitless)
- this.css( type, size.constructor == String ? size : size + "px" );
- };
-});
-
-// Helper function used by the dimensions and offset modules
-function num(elem, prop) {
- return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
-}var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
- "(?:[\\w*_-]|\\\\.)" :
- "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
- quickChild = new RegExp("^>\\s*(" + chars + "+)"),
- quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
- quickClass = new RegExp("^([#.]?)(" + chars + "*)");
-
-jQuery.extend({
- expr: {
- "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
- "#": function(a,i,m){return a.getAttribute("id")==m[2];},
- ":": {
- // Position Checks
- lt: function(a,i,m){return i<m[3]-0;},
- gt: function(a,i,m){return i>m[3]-0;},
- nth: function(a,i,m){return m[3]-0==i;},
- eq: function(a,i,m){return m[3]-0==i;},
- first: function(a,i){return i==0;},
- last: function(a,i,m,r){return i==r.length-1;},
- even: function(a,i){return i%2==0;},
- odd: function(a,i){return i%2;},
-
- // Child Checks
- "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
- "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
- "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
-
- // Parent Checks
- parent: function(a){return a.firstChild;},
- empty: function(a){return !a.firstChild;},
-
- // Text Check
- contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
-
- // Visibility
- visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
- hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
-
- // Form attributes
- enabled: function(a){return !a.disabled;},
- disabled: function(a){return a.disabled;},
- checked: function(a){return a.checked;},
- selected: function(a){return a.selected||jQuery.attr(a,"selected");},
-
- // Form elements
- text: function(a){return "text"==a.type;},
- radio: function(a){return "radio"==a.type;},
- checkbox: function(a){return "checkbox"==a.type;},
- file: function(a){return "file"==a.type;},
- password: function(a){return "password"==a.type;},
- submit: function(a){return "submit"==a.type;},
- image: function(a){return "image"==a.type;},
- reset: function(a){return "reset"==a.type;},
- button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
- input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
-
- // :has()
- has: function(a,i,m){return jQuery.find(m[3],a).length;},
-
- // :header
- header: function(a){return /h\d/i.test(a.nodeName);},
-
- // :animated
- animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
- }
- },
-
- // The regular expressions that power the parsing engine
- parse: [
- // Match: [@value='test'], [@foo]
- /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
-
- // Match: :contains('foo')
- /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
-
- // Match: :even, :last-child, #id, .class
- new RegExp("^([:.#]*)(" + chars + "+)")
- ],
-
- multiFilter: function( expr, elems, not ) {
- var old, cur = [];
-
- while ( expr && expr != old ) {
- old = expr;
- var f = jQuery.filter( expr, elems, not );
- expr = f.t.replace(/^\s*,\s*/, "" );
- cur = not ? elems = f.r : jQuery.merge( cur, f.r );
- }
-
- return cur;
- },
-
- find: function( t, context ) {
- // Quickly handle non-string expressions
- if ( typeof t != "string" )
- return [ t ];
-
- // check to make sure context is a DOM element or a document
- if ( context && context.nodeType != 1 && context.nodeType != 9)
- return [ ];
-
- // Set the correct context (if none is provided)
- context = context || document;
-
- // Initialize the search
- var ret = [context], done = [], last, nodeName;
-
- // Continue while a selector expression exists, and while
- // we're no longer looping upon ourselves
- while ( t && last != t ) {
- var r = [];
- last = t;
-
- t = jQuery.trim(t);
-
- var foundToken = false,
-
- // An attempt at speeding up child selectors that
- // point to a specific element tag
- re = quickChild,
-
- m = re.exec(t);
-
- if ( m ) {
- nodeName = m[1].toUpperCase();
-
- // Perform our own iteration and filter
- for ( var i = 0; ret[i]; i++ )
- for ( var c = ret[i].firstChild; c; c = c.nextSibling )
- if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
- r.push( c );
-
- ret = r;
- t = t.replace( re, "" );
- if ( t.indexOf(" ") == 0 ) continue;
- foundToken = true;
- } else {
- re = /^([>+~])\s*(\w*)/i;
-
- if ( (m = re.exec(t)) != null ) {
- r = [];
-
- var merge = {};
- nodeName = m[2].toUpperCase();
- m = m[1];
-
- for ( var j = 0, rl = ret.length; j < rl; j++ ) {
- var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
- for ( ; n; n = n.nextSibling )
- if ( n.nodeType == 1 ) {
- var id = jQuery.data(n);
-
- if ( m == "~" && merge[id] ) break;
-
- if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
- if ( m == "~" ) merge[id] = true;
- r.push( n );
- }
-
- if ( m == "+" ) break;
- }
- }
-
- ret = r;
-
- // And remove the token
- t = jQuery.trim( t.replace( re, "" ) );
- foundToken = true;
- }
- }
-
- // See if there's still an expression, and that we haven't already
- // matched a token
- if ( t && !foundToken ) {
- // Handle multiple expressions
- if ( !t.indexOf(",") ) {
- // Clean the result set
- if ( context == ret[0] ) ret.shift();
-
- // Merge the result sets
- done = jQuery.merge( done, ret );
-
- // Reset the context
- r = ret = [context];
-
- // Touch up the selector string
- t = " " + t.substr(1,t.length);
-
- } else {
- // Optimize for the case nodeName#idName
- var re2 = quickID;
- var m = re2.exec(t);
-
- // Re-organize the results, so that they're consistent
- if ( m ) {
- m = [ 0, m[2], m[3], m[1] ];
-
- } else {
- // Otherwise, do a traditional filter check for
- // ID, class, and element selectors
- re2 = quickClass;
- m = re2.exec(t);
- }
-
- m[2] = m[2].replace(/\\/g, "");
-
- var elem = ret[ret.length-1];
-
- // Try to do a global search by ID, where we can
- if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
- // Optimization for HTML document case
- var oid = elem.getElementById(m[2]);
-
- // Do a quick check for the existence of the actual ID attribute
- // to avoid selecting by the name attribute in IE
- // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
- if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
- oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
-
- // Do a quick check for node name (where applicable) so
- // that div#foo searches will be really fast
- ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
- } else {
- // We need to find all descendant elements
- for ( var i = 0; ret[i]; i++ ) {
- // Grab the tag name being searched for
- var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
-
- // Handle IE7 being really dumb about <object>s
- if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
- tag = "param";
-
- r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
- }
-
- // It's faster to filter by class and be done with it
- if ( m[1] == "." )
- r = jQuery.classFilter( r, m[2] );
-
- // Same with ID filtering
- if ( m[1] == "#" ) {
- var tmp = [];
-
- // Try to find the element with the ID
- for ( var i = 0; r[i]; i++ )
- if ( r[i].getAttribute("id") == m[2] ) {
- tmp = [ r[i] ];
- break;
- }
-
- r = tmp;
- }
-
- ret = r;
- }
-
- t = t.replace( re2, "" );
- }
-
- }
-
- // If a selector string still exists
- if ( t ) {
- // Attempt to filter it
- var val = jQuery.filter(t,r);
- ret = r = val.r;
- t = jQuery.trim(val.t);
- }
- }
-
- // An error occurred with the selector;
- // just return an empty set instead
- if ( t )
- ret = [];
-
- // Remove the root context
- if ( ret && context == ret[0] )
- ret.shift();
-
- // And combine the results
- done = jQuery.merge( done, ret );
-
- return done;
- },
-
- classFilter: function(r,m,not){
- m = " " + m + " ";
- var tmp = [];
- for ( var i = 0; r[i]; i++ ) {
- var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
- if ( !not && pass || not && !pass )
- tmp.push( r[i] );
- }
- return tmp;
- },
-
- filter: function(t,r,not) {
- var last;
-
- // Look for common filter expressions
- while ( t && t != last ) {
- last = t;
-
- var p = jQuery.parse, m;
-
- for ( var i = 0; p[i]; i++ ) {
- m = p[i].exec( t );
-
- if ( m ) {
- // Remove what we just matched
- t = t.substring( m[0].length );
-
- m[2] = m[2].replace(/\\/g, "");
- break;
- }
- }
-
- if ( !m )
- break;
-
- // :not() is a special case that can be optimized by
- // keeping it out of the expression list
- if ( m[1] == ":" && m[2] == "not" )
- // optimize if only one selector found (most common case)
- r = isSimple.test( m[3] ) ?
- jQuery.filter(m[3], r, true).r :
- jQuery( r ).not( m[3] );
-
- // We can get a big speed boost by filtering by class here
- else if ( m[1] == "." )
- r = jQuery.classFilter(r, m[2], not);
-
- else if ( m[1] == "[" ) {
- var tmp = [], type = m[3];
-
- for ( var i = 0, rl = r.length; i < rl; i++ ) {
- var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
-
- if ( z == null || /href|src|selected/.test(m[2]) )
- z = jQuery.attr(a,m[2]) || '';
-
- if ( (type == "" && !!z ||
- type == "=" && z == m[5] ||
- type == "!=" && z != m[5] ||
- type == "^=" && z && !z.indexOf(m[5]) ||
- type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
- (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
- tmp.push( a );
- }
-
- r = tmp;
-
- // We can get a speed boost by handling nth-child here
- } else if ( m[1] == ":" && m[2] == "nth-child" ) {
- var merge = {}, tmp = [],
- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
- test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
- m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
- !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
- // calculate the numbers (first)n+(last) including if they are negative
- first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
-
- // loop through all the elements left in the jQuery object
- for ( var i = 0, rl = r.length; i < rl; i++ ) {
- var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
-
- if ( !merge[id] ) {
- var c = 1;
-
- for ( var n = parentNode.firstChild; n; n = n.nextSibling )
- if ( n.nodeType == 1 )
- n.nodeIndex = c++;
-
- merge[id] = true;
- }
-
- var add = false;
-
- if ( first == 0 ) {
- if ( node.nodeIndex == last )
- add = true;
- } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
- add = true;
-
- if ( add ^ not )
- tmp.push( node );
- }
-
- r = tmp;
-
- // Otherwise, find the expression to execute
- } else {
- var fn = jQuery.expr[ m[1] ];
- if ( typeof fn == "object" )
- fn = fn[ m[2] ];
-
- if ( typeof fn == "string" )
- fn = eval("false||function(a,i){return " + fn + ";}");
-
- // Execute it against the current filter
- r = jQuery.grep( r, function(elem, i){
- return fn(elem, i, m, r);
- }, not );
- }
- }
-
- // Return an array of filtered elements (r)
- // and the modified expression string (t)
- return { r: r, t: t };
- },
-
- dir: function( elem, dir ){
- var matched = [],
- cur = elem[dir];
- while ( cur && cur != document ) {
- if ( cur.nodeType == 1 )
- matched.push( cur );
- cur = cur[dir];
- }
- return matched;
- },
-
- nth: function(cur,result,dir,elem){
- result = result || 1;
- var num = 0;
-
- for ( ; cur; cur = cur[dir] )
- if ( cur.nodeType == 1 && ++num == result )
- break;
-
- return cur;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType == 1 && n != elem )
- r.push( n );
- }
-
- return r;
- }
-});
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code orignated from
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
-
- // Bind an event to an element
- // Original by Dean Edwards
- add: function(elem, types, handler, data) {
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
-
- // For whatever reason, IE has trouble passing the window object
- // around, causing it to be cloned in the process
- if ( jQuery.browser.msie && elem.setInterval )
- elem = window;
-
- // Make sure that the function being executed has a unique ID
- if ( !handler.guid )
- handler.guid = this.guid++;
-
- // if data is passed, bind to handler
- if( data != undefined ) {
- // Create temporary function pointer to original handler
- var fn = handler;
-
- // Create unique handler function, wrapped around original handler
- handler = this.proxy( fn, function() {
- // Pass arguments and context to original handler
- return fn.apply(this, arguments);
- });
-
- // Store data in unique handler
- handler.data = data;
- }
-
- // Init the element's event structure
- var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
- handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
- // Handle the second event of a trigger and when
- // an event is called after a page has unloaded
- if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
- return jQuery.event.handle.apply(arguments.callee.elem, arguments);
- });
- // Add elem as a property of the handle function
- // This is to prevent a memory leak with non-native
- // event in IE.
- handle.elem = elem;
-
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type) {
- // Namespaced event handlers
- var parts = type.split(".");
- type = parts[0];
- handler.type = parts[1];
-
- // Get the current list of functions bound to this event
- var handlers = events[type];
-
- // Init the event handler queue
- if (!handlers) {
- handlers = events[type] = {};
-
- // Check for a special event handler
- // Only use addEventListener/attachEvent if the special
- // events handler returns false
- if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
- // Bind the global event handler to the element
- if (elem.addEventListener)
- elem.addEventListener(type, handle, false);
- else if (elem.attachEvent)
- elem.attachEvent("on" + type, handle);
- }
- }
-
- // Add the function to the element's handler list
- handlers[handler.guid] = handler;
-
- // Keep track of which events have been used, for global triggering
- jQuery.event.global[type] = true;
- });
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- guid: 1,
- global: {},
-
- // Detach an event or set of events from an element
- remove: function(elem, types, handler) {
- // don't do events on text and comment nodes
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
-
- var events = jQuery.data(elem, "events"), ret, index;
-
- if ( events ) {
- // Unbind all events for the element
- if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
- for ( var type in events )
- this.remove( elem, type + (types || "") );
- else {
- // types is actually an event object here
- if ( types.type ) {
- handler = types.handler;
- types = types.type;
- }
-
- // Handle multiple events seperated by a space
- // jQuery(...).unbind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type){
- // Namespaced event handlers
- var parts = type.split(".");
- type = parts[0];
-
- if ( events[type] ) {
- // remove the given handler for the given type
- if ( handler )
- delete events[type][handler.guid];
-
- // remove all handlers for the given type
- else
- for ( handler in events[type] )
- // Handle the removal of namespaced events
- if ( !parts[1] || events[type][handler].type == parts[1] )
- delete events[type][handler];
-
- // remove generic event handler if no more handlers exist
- for ( ret in events[type] ) break;
- if ( !ret ) {
- if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
- if (elem.removeEventListener)
- elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
- else if (elem.detachEvent)
- elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
- }
- ret = null;
- delete events[type];
- }
- }
- });
- }
-
- // Remove the expando if it's no longer used
- for ( ret in events ) break;
- if ( !ret ) {
- var handle = jQuery.data( elem, "handle" );
- if ( handle ) handle.elem = null;
- jQuery.removeData( elem, "events" );
- jQuery.removeData( elem, "handle" );
- }
- }
- },
-
- trigger: function(type, data, elem, donative, extra) {
- // Clone the incoming data, if any
- data = jQuery.makeArray(data);
-
- if ( type.indexOf("!") >= 0 ) {
- type = type.slice(0, -1);
- var exclusive = true;
- }
-
- // Handle a global trigger
- if ( !elem ) {
- // Only trigger if we've ever bound an event for it
- if ( this.global[type] )
- jQuery("*").add([window, document]).trigger(type, data);
-
- // Handle triggering a single element
- } else {
- // don't do events on text and comment nodes
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return undefined;
-
- var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
- // Check to see if we need to provide a fake event, or not
- event = !data[0] || !data[0].preventDefault;
-
- // Pass along a fake event
- if ( event ) {
- data.unshift({
- type: type,
- target: elem,
- preventDefault: function(){},
- stopPropagation: function(){},
- timeStamp: now()
- });
- data[0][expando] = true; // no need to fix fake event
- }
-
- // Enforce the right trigger type
- data[0].type = type;
- if ( exclusive )
- data[0].exclusive = true;
-
- // Trigger the event, it is assumed that "handle" is a function
- var handle = jQuery.data(elem, "handle");
- if ( handle )
- val = handle.apply( elem, data );
-
- // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
- if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
- val = false;
-
- // Extra functions don't get the custom event object
- if ( event )
- data.shift();
-
- // Handle triggering of extra function
- if ( extra && jQuery.isFunction( extra ) ) {
- // call the extra function and tack the current return value on the end for possible inspection
- ret = extra.apply( elem, val == null ? data : data.concat( val ) );
- // if anything is returned, give it precedence and have it overwrite the previous value
- if (ret !== undefined)
- val = ret;
- }
-
- // Trigger the native events (except for clicks on links)
- if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
- this.triggered = true;
- try {
- elem[ type ]();
- // prevent IE from throwing an error for some hidden elements
- } catch (e) {}
- }
-
- this.triggered = false;
- }
-
- return val;
- },
-
- handle: function(event) {
- // returned undefined or false
- var val, ret, namespace, all, handlers;
-
- event = arguments[0] = jQuery.event.fix( event || window.event );
-
- // Namespaced event handlers
- namespace = event.type.split(".");
- event.type = namespace[0];
- namespace = namespace[1];
- // Cache this now, all = true means, any handler
- all = !namespace && !event.exclusive;
-
- handlers = ( jQuery.data(this, "events") || {} )[event.type];
-
- for ( var j in handlers ) {
- var handler = handlers[j];
-
- // Filter the functions by class
- if ( all || handler.type == namespace ) {
- // Pass in a reference to the handler function itself
- // So that we can later remove it
- event.handler = handler;
- event.data = handler.data;
-
- ret = handler.apply( this, arguments );
-
- if ( val !== false )
- val = ret;
-
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
-
- return val;
- },
-
- fix: function(event) {
- if ( event[expando] == true )
- return event;
-
- // store a copy of the original event object
- // and "clone" to set read-only properties
- var originalEvent = event;
- event = { originalEvent: originalEvent };
- var props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");
- for ( var i=props.length; i; i-- )
- event[ props[i] ] = originalEvent[ props[i] ];
-
- // Mark it as fixed
- event[expando] = true;
-
- // add preventDefault and stopPropagation since
- // they will not work on the clone
- event.preventDefault = function() {
- // if preventDefault exists run it on the original event
- if (originalEvent.preventDefault)
- originalEvent.preventDefault();
- // otherwise set the returnValue property of the original event to false (IE)
- originalEvent.returnValue = false;
- };
- event.stopPropagation = function() {
- // if stopPropagation exists run it on the original event
- if (originalEvent.stopPropagation)
- originalEvent.stopPropagation();
- // otherwise set the cancelBubble property of the original event to true (IE)
- originalEvent.cancelBubble = true;
- };
-
- // Fix timeStamp
- event.timeStamp = event.timeStamp || now();
-
- // Fix target property, if necessary
- if ( !event.target )
- event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
-
- // check if target is a textnode (safari)
- if ( event.target.nodeType == 3 )
- event.target = event.target.parentNode;
-
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && event.fromElement )
- event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && event.clientX != null ) {
- var doc = document.documentElement, body = document.body;
- event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
- event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
- }
-
- // Add which for key events
- if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
- event.which = event.charCode || event.keyCode;
-
- // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
- if ( !event.metaKey && event.ctrlKey )
- event.metaKey = event.ctrlKey;
-
- // Add which for click: 1 == left; 2 == middle; 3 == right
- // Note: button is not normalized, so don't use it
- if ( !event.which && event.button )
- event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
-
- return event;
- },
-
- proxy: function( fn, proxy ){
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
- // So proxy can be declared as an argument
- return proxy;
- },
-
- special: {
- ready: {
- setup: function() {
- // Make sure the ready event is setup
- bindReady();
- return;
- },
-
- teardown: function() { return; }
- },
-
- mouseenter: {
- setup: function() {
- if ( jQuery.browser.msie ) return false;
- jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
- return true;
- },
-
- teardown: function() {
- if ( jQuery.browser.msie ) return false;
- jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
- return true;
- },
-
- handler: function(event) {
- // If we actually just moused on to a sub-element, ignore it
- if ( withinElement(event, this) ) return true;
- // Execute the right handlers by setting the event type to mouseenter
- event.type = "mouseenter";
- return jQuery.event.handle.apply(this, arguments);
- }
- },
-
- mouseleave: {
- setup: function() {
- if ( jQuery.browser.msie ) return false;
- jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
- return true;
- },
-
- teardown: function() {
- if ( jQuery.browser.msie ) return false;
- jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
- return true;
- },
-
- handler: function(event) {
- // If we actually just moused on to a sub-element, ignore it
- if ( withinElement(event, this) ) return true;
- // Execute the right handlers by setting the event type to mouseleave
- event.type = "mouseleave";
- return jQuery.event.handle.apply(this, arguments);
- }
- }
- }
-};
-
-jQuery.fn.extend({
- bind: function( type, data, fn ) {
- return type == "unload" ? this.one(type, data, fn) : this.each(function(){
- jQuery.event.add( this, type, fn || data, fn && data );
- });
- },
-
- one: function( type, data, fn ) {
- var one = jQuery.event.proxy( fn || data, function(event) {
- jQuery(this).unbind(event, one);
- return (fn || data).apply( this, arguments );
- });
- return this.each(function(){
- jQuery.event.add( this, type, one, fn && data);
- });
- },
-
- unbind: function( type, fn ) {
- return this.each(function(){
- jQuery.event.remove( this, type, fn );
- });
- },
-
- trigger: function( type, data, fn ) {
- return this.each(function(){
- jQuery.event.trigger( type, data, this, true, fn );
- });
- },
-
- triggerHandler: function( type, data, fn ) {
- return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
- },
-
- toggle: function( fn ) {
- // Save reference to arguments for access in closure
- var args = arguments, i = 1;
-
- // link all the functions, so any of them can unbind this click handler
- while( i < args.length )
- jQuery.event.proxy( fn, args[i++] );
-
- return this.click( jQuery.event.proxy( fn, function(event) {
- // Figure out which function to execute
- this.lastToggle = ( this.lastToggle || 0 ) % i;
-
- // Make sure that clicks stop
- event.preventDefault();
-
- // and execute the function
- return args[ this.lastToggle++ ].apply( this, arguments ) || false;
- }));
- },
-
- hover: function(fnOver, fnOut) {
- return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
- },
-
- ready: function(fn) {
- // Attach the listeners
- bindReady();
-
- // If the DOM is already ready
- if ( jQuery.isReady )
- // Execute the function immediately
- fn.call( document, jQuery );
-
- // Otherwise, remember the function for later
- else
- // Add the function to the wait list
- jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
-
- return this;
- }
-});
-
-jQuery.extend({
- isReady: false,
- readyList: [],
- // Handle when the DOM is ready
- ready: function() {
- // Make sure that the DOM is not already loaded
- if ( !jQuery.isReady ) {
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If there are functions bound, to execute
- if ( jQuery.readyList ) {
- // Execute all of them
- jQuery.each( jQuery.readyList, function(){
- this.call( document );
- });
-
- // Reset the list of functions
- jQuery.readyList = null;
- }
-
- // Trigger any bound ready events
- jQuery(document).triggerHandler("ready");
- }
- }
-});
-
-var readyBound = false;
-
-function bindReady(){
- if ( readyBound ) return;
- readyBound = true;
-
- // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
- if ( document.addEventListener && !jQuery.browser.opera)
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
-
- // If IE is used and is not in a frame
- // Continually check to see if the document is ready
- if ( jQuery.browser.msie && window == top ) (function(){
- if (jQuery.isReady) return;
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch( error ) {
- setTimeout( arguments.callee, 0 );
- return;
- }
- // and execute any waiting functions
- jQuery.ready();
- })();
-
- if ( jQuery.browser.opera )
- document.addEventListener( "DOMContentLoaded", function () {
- if (jQuery.isReady) return;
- for (var i = 0; i < document.styleSheets.length; i++)
- if (document.styleSheets[i].disabled) {
- setTimeout( arguments.callee, 0 );
- return;
- }
- // and execute any waiting functions
- jQuery.ready();
- }, false);
-
- if ( jQuery.browser.safari ) {
- var numStyles;
- (function(){
- if (jQuery.isReady) return;
- if ( document.readyState != "loaded" && document.readyState != "complete" ) {
- setTimeout( arguments.callee, 0 );
- return;
- }
- if ( numStyles === undefined )
- numStyles = jQuery("style, link[rel=stylesheet]").length;
- if ( document.styleSheets.length != numStyles ) {
- setTimeout( arguments.callee, 0 );
- return;
- }
- // and execute any waiting functions
- jQuery.ready();
- })();
- }
-
- // A fallback to window.onload, that will always work
- jQuery.event.add( window, "load", jQuery.ready );
-}
-
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
- "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
- "submit,keydown,keypress,keyup,error").split(","), function(i, name){
-
- // Handle event binding
- jQuery.fn[name] = function(fn){
- return fn ? this.bind(name, fn) : this.trigger(name);
- };
-});
-
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event, elem) {
- // Check if mouse(over|out) are still within the same parent element
- var parent = event.relatedTarget;
- // Traverse up the tree
- while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
- // Return true if we actually just moused on to a sub-element
- return parent == elem;
-};
-
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery(window).bind("unload", function() {
- jQuery("*").add(document).unbind();
-});
-jQuery.fn.extend({
- // Keep a copy of the old load
- _load: jQuery.fn.load,
-
- load: function( url, params, callback ) {
- if ( typeof url != 'string' )
- return this._load( url );
-
- var off = url.indexOf(" ");
- if ( off >= 0 ) {
- var selector = url.slice(off, url.length);
- url = url.slice(0, off);
- }
-
- callback = callback || function(){};
-
- // Default to a GET request
- var type = "GET";
-
- // If the second parameter was provided
- if ( params )
- // If it's a function
- if ( jQuery.isFunction( params ) ) {
- // We assume that it's the callback
- callback = params;
- params = null;
-
- // Otherwise, build a param string
- } else {
- params = jQuery.param( params );
- type = "POST";
- }
-
- var self = this;
-
- // Request the remote document
- jQuery.ajax({
- url: url,
- type: type,
- dataType: "html",
- data: params,
- complete: function(res, status){
- // If successful, inject the HTML into all the matched elements
- if ( status == "success" || status == "notmodified" )
- // See if a selector was specified
- self.html( selector ?
- // Create a dummy div to hold the results
- jQuery("<div/>")
- // inject the contents of the document in, removing the scripts
- // to avoid any 'Permission Denied' errors in IE
- .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
-
- // Locate the specified elements
- .find(selector) :
-
- // If not, just inject the full result
- res.responseText );
-
- self.each( callback, [res.responseText, status, res] );
- }
- });
- return this;
- },
-
- serialize: function() {
- return jQuery.param(this.serializeArray());
- },
- serializeArray: function() {
- return this.map(function(){
- return jQuery.nodeName(this, "form") ?
- jQuery.makeArray(this.elements) : this;
- })
- .filter(function(){
- return this.name && !this.disabled &&
- (this.checked || /select|textarea/i.test(this.nodeName) ||
- /text|hidden|password/i.test(this.type));
- })
- .map(function(i, elem){
- var val = jQuery(this).val();
- return val == null ? null :
- val.constructor == Array ?
- jQuery.map( val, function(val, i){
- return {name: elem.name, value: val};
- }) :
- {name: elem.name, value: val};
- }).get();
- }
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
- jQuery.fn[o] = function(f){
- return this.bind(o, f);
- };
-});
-
-var jsc = now();
-
-jQuery.extend({
- get: function( url, data, callback, type ) {
- // shift arguments if data argument was ommited
- if ( jQuery.isFunction( data ) ) {
- callback = data;
- data = null;
- }
-
- return jQuery.ajax({
- type: "GET",
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- },
-
- getScript: function( url, callback ) {
- return jQuery.get(url, null, callback, "script");
- },
-
- getJSON: function( url, data, callback ) {
- return jQuery.get(url, data, callback, "json");
- },
-
- post: function( url, data, callback, type ) {
- if ( jQuery.isFunction( data ) ) {
- callback = data;
- data = {};
- }
-
- return jQuery.ajax({
- type: "POST",
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- },
-
- ajaxSetup: function( settings ) {
- jQuery.extend( jQuery.ajaxSettings, settings );
- },
-
- ajaxSettings: {
- url: location.href,
- global: true,
- type: "GET",
- timeout: 0,
- contentType: "application/x-www-form-urlencoded",
- processData: true,
- async: true,
- data: null,
- username: null,
- password: null,
- accepts: {
- xml: "application/xml, text/xml",
- html: "text/html",
- script: "text/javascript, application/javascript",
- json: "application/json, text/javascript",
- text: "text/plain",
- _default: "*/*"
- }
- },
-
- // Last-Modified header cache for next request
- lastModified: {},
-
- ajax: function( s ) {
- // Extend the settings, but re-extend 's' so that it can be
- // checked again later (in the test suite, specifically)
- s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
- var jsonp, jsre = /=\?(&|$)/g, status, data,
- type = s.type.toUpperCase();
-
- // convert data if not already a string
- if ( s.data && s.processData && typeof s.data != "string" )
- s.data = jQuery.param(s.data);
-
- // Handle JSONP Parameter Callbacks
- if ( s.dataType == "jsonp" ) {
- if ( type == "GET" ) {
- if ( !s.url.match(jsre) )
- s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
- } else if ( !s.data || !s.data.match(jsre) )
- s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
- s.dataType = "json";
- }
-
- // Build temporary JSONP function
- if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
- jsonp = "jsonp" + jsc++;
-
- // Replace the =? sequence both in the query string and the data
- if ( s.data )
- s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
- s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-
- // We need to make sure
- // that a JSONP style response is executed properly
- s.dataType = "script";
-
- // Handle JSONP-style loading
- window[ jsonp ] = function(tmp){
- data = tmp;
- success();
- complete();
- // Garbage collect
- window[ jsonp ] = undefined;
- try{ delete window[ jsonp ]; } catch(e){}
- if ( head )
- head.removeChild( script );
- };
- }
-
- if ( s.dataType == "script" && s.cache == null )
- s.cache = false;
-
- if ( s.cache === false && type == "GET" ) {
- var ts = now();
- // try replacing _= if it is there
- var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
- // if nothing was replaced, add timestamp to the end
- s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
- }
-
- // If data is available, append data to url for get requests
- if ( s.data && type == "GET" ) {
- s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
- // IE likes to send both get and post data, prevent this
- s.data = null;
- }
-
- // Watch for a new set of requests
- if ( s.global && ! jQuery.active++ )
- jQuery.event.trigger( "ajaxStart" );
-
- // Matches an absolute URL, and saves the domain
- var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
-
- // If we're requesting a remote document
- // and trying to load JSON or Script with a GET
- if ( s.dataType == "script" && type == "GET"
- && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
- var head = document.getElementsByTagName("head")[0];
- var script = document.createElement("script");
- script.src = s.url;
- if (s.scriptCharset)
- script.charset = s.scriptCharset;
-
- // Handle Script loading
- if ( !jsonp ) {
- var done = false;
-
- // Attach handlers for all browsers
- script.onload = script.onreadystatechange = function(){
- if ( !done && (!this.readyState ||
- this.readyState == "loaded" || this.readyState == "complete") ) {
- done = true;
- success();
- complete();
- head.removeChild( script );
- }
- };
- }
-
- head.appendChild(script);
-
- // We handle everything using the script element injection
- return undefined;
- }
-
- var requestDone = false;
-
- // Create the request object; Microsoft failed to properly
- // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
- var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
-
- // Open the socket
- // Passing null username, generates a login popup on Opera (#2865)
- if( s.username )
- xhr.open(type, s.url, s.async, s.username, s.password);
- else
- xhr.open(type, s.url, s.async);
-
- // Need an extra try/catch for cross domain requests in Firefox 3
- try {
- // Set the correct header, if data is being sent
- if ( s.data )
- xhr.setRequestHeader("Content-Type", s.contentType);
-
- // Set the If-Modified-Since header, if ifModified mode.
- if ( s.ifModified )
- xhr.setRequestHeader("If-Modified-Since",
- jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
-
- // Set header so the called script knows that it's an XMLHttpRequest
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-
- // Set the Accepts header for the server, depending on the dataType
- xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
- s.accepts[ s.dataType ] + ", */*" :
- s.accepts._default );
- } catch(e){}
-
- // Allow custom headers/mimetypes
- if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
- // cleanup active request counter
- s.global && jQuery.active--;
- // close opended socket
- xhr.abort();
- return false;
- }
-
- if ( s.global )
- jQuery.event.trigger("ajaxSend", [xhr, s]);
-
- // Wait for a response to come back
- var onreadystatechange = function(isTimeout){
- // The transfer is complete and the data is available, or the request timed out
- if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
- requestDone = true;
-
- // clear poll interval
- if (ival) {
- clearInterval(ival);
- ival = null;
- }
-
- status = isTimeout == "timeout" && "timeout" ||
- !jQuery.httpSuccess( xhr ) && "error" ||
- s.ifModified && jQuery.httpNotModified( xhr, s.url ) && "notmodified" ||
- "success";
-
- if ( status == "success" ) {
- // Watch for, and catch, XML document parse errors
- try {
- // process the data (runs the xml through httpData regardless of callback)
- data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
- } catch(e) {
- status = "parsererror";
- }
- }
-
- // Make sure that the request was successful or notmodified
- if ( status == "success" ) {
- // Cache Last-Modified header, if ifModified mode.
- var modRes;
- try {
- modRes = xhr.getResponseHeader("Last-Modified");
- } catch(e) {} // swallow exception thrown by FF if header is not available
-
- if ( s.ifModified && modRes )
- jQuery.lastModified[s.url] = modRes;
-
- // JSONP handles its own success callback
- if ( !jsonp )
- success();
- } else
- jQuery.handleError(s, xhr, status);
-
- // Fire the complete handlers
- complete();
-
- // Stop memory leaks
- if ( s.async )
- xhr = null;
- }
- };
-
- if ( s.async ) {
- // don't attach the handler to the request, just poll it instead
- var ival = setInterval(onreadystatechange, 13);
-
- // Timeout checker
- if ( s.timeout > 0 )
- setTimeout(function(){
- // Check to see if the request is still happening
- if ( xhr ) {
- // Cancel the request
- xhr.abort();
-
- if( !requestDone )
- onreadystatechange( "timeout" );
- }
- }, s.timeout);
- }
-
- // Send the data
- try {
- xhr.send(s.data);
- } catch(e) {
- jQuery.handleError(s, xhr, null, e);
- }
-
- // firefox 1.5 doesn't fire statechange for sync requests
- if ( !s.async )
- onreadystatechange();
-
- function success(){
- // If a local callback was specified, fire it and pass it the data
- if ( s.success )
- s.success( data, status );
-
- // Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
- }
-
- function complete(){
- // Process result
- if ( s.complete )
- s.complete(xhr, status);
-
- // The request was completed
- if ( s.global )
- jQuery.event.trigger( "ajaxComplete", [xhr, s] );
-
- // Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
- jQuery.event.trigger( "ajaxStop" );
- }
-
- // return XMLHttpRequest to allow aborting the request etc.
- return xhr;
- },
-
- handleError: function( s, xhr, status, e ) {
- // If a local callback was specified, fire it
- if ( s.error ) s.error( xhr, status, e );
-
- // Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxError", [xhr, s, e] );
- },
-
- // Counter for holding the number of active queries
- active: 0,
-
- // Determines if an XMLHttpRequest was successful or not
- httpSuccess: function( xhr ) {
- try {
- // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
- return !xhr.status && location.protocol == "file:" ||
- ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
- jQuery.browser.safari && xhr.status == undefined;
- } catch(e){}
- return false;
- },
-
- // Determines if an XMLHttpRequest returns NotModified
- httpNotModified: function( xhr, url ) {
- try {
- var xhrRes = xhr.getResponseHeader("Last-Modified");
-
- // Firefox always returns 200. check Last-Modified date
- return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
- jQuery.browser.safari && xhr.status == undefined;
- } catch(e){}
- return false;
- },
-
- httpData: function( xhr, type, filter ) {
- var ct = xhr.getResponseHeader("content-type"),
- xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
- data = xml ? xhr.responseXML : xhr.responseText;
-
- if ( xml && data.documentElement.tagName == "parsererror" )
- throw "parsererror";
-
- // Allow a pre-filtering function to sanitize the response
- if( filter )
- data = filter( data, type );
-
- // If the type is "script", eval it in global context
- if ( type == "script" )
- jQuery.globalEval( data );
-
- // Get the JavaScript object, if JSON is used.
- if ( type == "json" )
- data = eval("(" + data + ")");
-
- return data;
- },
-
- // Serialize an array of form elements or a set of
- // key/values into a query string
- param: function( a ) {
- var s = [];
-
- // If an array was passed in, assume that it is an array
- // of form elements
- if ( a.constructor == Array || a.jquery )
- // Serialize the form elements
- jQuery.each( a, function(){
- s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
- });
-
- // Otherwise, assume that it's an object of key/value pairs
- else
- // Serialize the key/values
- for ( var j in a )
- // If the value is an array then the key names need to be repeated
- if ( a[j] && a[j].constructor == Array )
- jQuery.each( a[j], function(){
- s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
- });
- else
- s.push( encodeURIComponent(j) + "=" + encodeURIComponent( jQuery.isFunction(a[j]) ? a[j]() : a[j] ) );
-
- // Return the resulting serialization
- return s.join("&").replace(/%20/g, "+");
- }
-
-});
-jQuery.fn.extend({
- show: function(speed,callback){
- return speed ?
- this.animate({
- height: "show", width: "show", opacity: "show"
- }, speed, callback) :
-
- this.filter(":hidden").each(function(){
- this.style.display = this.oldblock || "";
- if ( jQuery.css(this,"display") == "none" ) {
- var elem = jQuery("<" + this.tagName + " />").appendTo("body");
- this.style.display = elem.css("display");
- // handle an edge condition where css is - div { display:none; } or similar
- if (this.style.display == "none")
- this.style.display = "block";
- elem.remove();
- }
- }).end();
- },
-
- hide: function(speed,callback){
- return speed ?
- this.animate({
- height: "hide", width: "hide", opacity: "hide"
- }, speed, callback) :
-
- this.filter(":visible").each(function(){
- this.oldblock = this.oldblock || jQuery.css(this,"display");
- this.style.display = "none";
- }).end();
- },
-
- // Save the old toggle function
- _toggle: jQuery.fn.toggle,
-
- toggle: function( fn, fn2 ){
- return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
- this._toggle.apply( this, arguments ) :
- fn ?
- this.animate({
- height: "toggle", width: "toggle", opacity: "toggle"
- }, fn, fn2) :
- this.each(function(){
- jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
- });
- },
-
- slideDown: function(speed,callback){
- return this.animate({height: "show"}, speed, callback);
- },
-
- slideUp: function(speed,callback){
- return this.animate({height: "hide"}, speed, callback);
- },
-
- slideToggle: function(speed, callback){
- return this.animate({height: "toggle"}, speed, callback);
- },
-
- fadeIn: function(speed, callback){
- return this.animate({opacity: "show"}, speed, callback);
- },
-
- fadeOut: function(speed, callback){
- return this.animate({opacity: "hide"}, speed, callback);
- },
-
- fadeTo: function(speed,to,callback){
- return this.animate({opacity: to}, speed, callback);
- },
-
- animate: function( prop, speed, easing, callback ) {
- var optall = jQuery.speed(speed, easing, callback);
-
- return this[ optall.queue === false ? "each" : "queue" ](function(){
- if ( this.nodeType != 1)
- return false;
-
- var opt = jQuery.extend({}, optall), p,
- hidden = jQuery(this).is(":hidden"), self = this;
-
- for ( p in prop ) {
- if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
- return opt.complete.call(this);
-
- if ( p == "height" || p == "width" ) {
- // Store display property
- opt.display = jQuery.css(this, "display");
-
- // Make sure that nothing sneaks out
- opt.overflow = this.style.overflow;
- }
- }
-
- if ( opt.overflow != null )
- this.style.overflow = "hidden";
-
- opt.curAnim = jQuery.extend({}, prop);
-
- jQuery.each( prop, function(name, val){
- var e = new jQuery.fx( self, opt, name );
-
- if ( /toggle|show|hide/.test(val) )
- e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
- else {
- var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
- start = e.cur(true) || 0;
-
- if ( parts ) {
- var end = parseFloat(parts[2]),
- unit = parts[3] || "px";
-
- // We need to compute starting value
- if ( unit != "px" ) {
- self.style[ name ] = (end || 1) + unit;
- start = ((end || 1) / e.cur(true)) * start;
- self.style[ name ] = start + unit;
- }
-
- // If a +=/-= token was provided, we're doing a relative animation
- if ( parts[1] )
- end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
-
- e.custom( start, end, unit );
- } else
- e.custom( start, val, "" );
- }
- });
-
- // For JS strict compliance
- return true;
- });
- },
-
- queue: function(type, fn){
- if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
- fn = type;
- type = "fx";
- }
-
- if ( !type || (typeof type == "string" && !fn) )
- return queue( this[0], type );
-
- return this.each(function(){
- if ( fn.constructor == Array )
- queue(this, type, fn);
- else {
- queue(this, type).push( fn );
-
- if ( queue(this, type).length == 1 )
- fn.call(this);
- }
- });
- },
-
- stop: function(clearQueue, gotoEnd){
- var timers = jQuery.timers;
-
- if (clearQueue)
- this.queue([]);
-
- this.each(function(){
- // go in reverse order so anything added to the queue during the loop is ignored
- for ( var i = timers.length - 1; i >= 0; i-- )
- if ( timers[i].elem == this ) {
- if (gotoEnd)
- // force the next step to be the last
- timers[i](true);
- timers.splice(i, 1);
- }
- });
-
- // start the next in the queue if the last step wasn't forced
- if (!gotoEnd)
- this.dequeue();
-
- return this;
- }
-
-});
-
-var queue = function( elem, type, array ) {
- if ( elem ){
-
- type = type || "fx";
-
- var q = jQuery.data( elem, type + "queue" );
-
- if ( !q || array )
- q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
-
- }
- return q;
-};
-
-jQuery.fn.dequeue = function(type){
- type = type || "fx";
-
- return this.each(function(){
- var q = queue(this, type);
-
- q.shift();
-
- if ( q.length )
- q[0].call( this );
- });
-};
-
-jQuery.extend({
-
- speed: function(speed, easing, fn) {
- var opt = speed && speed.constructor == Object ? speed : {
- complete: fn || !fn && easing ||
- jQuery.isFunction( speed ) && speed,
- duration: speed,
- easing: fn && easing || easing && easing.constructor != Function && easing
- };
-
- opt.duration = (opt.duration && opt.duration.constructor == Number ?
- opt.duration :
- jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
-
- // Queueing
- opt.old = opt.complete;
- opt.complete = function(){
- if ( opt.queue !== false )
- jQuery(this).dequeue();
- if ( jQuery.isFunction( opt.old ) )
- opt.old.call( this );
- };
-
- return opt;
- },
-
- easing: {
- linear: function( p, n, firstNum, diff ) {
- return firstNum + diff * p;
- },
- swing: function( p, n, firstNum, diff ) {
- return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
- }
- },
-
- timers: [],
- timerId: null,
-
- fx: function( elem, options, prop ){
- this.options = options;
- this.elem = elem;
- this.prop = prop;
-
- if ( !options.orig )
- options.orig = {};
- }
-
-});
-
-jQuery.fx.prototype = {
-
- // Simple function for setting a style value
- update: function(){
- if ( this.options.step )
- this.options.step.call( this.elem, this.now, this );
-
- (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-
- // Set display property to block for height/width animations
- if ( this.prop == "height" || this.prop == "width" )
- this.elem.style.display = "block";
- },
-
- // Get the current size
- cur: function(force){
- if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
- return this.elem[ this.prop ];
-
- var r = parseFloat(jQuery.css(this.elem, this.prop, force));
- return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
- },
-
- // Start an animation from one number to another
- custom: function(from, to, unit){
- this.startTime = now();
- this.start = from;
- this.end = to;
- this.unit = unit || this.unit || "px";
- this.now = this.start;
- this.pos = this.state = 0;
- this.update();
-
- var self = this;
- function t(gotoEnd){
- return self.step(gotoEnd);
- }
-
- t.elem = this.elem;
-
- jQuery.timers.push(t);
-
- if ( jQuery.timerId == null ) {
- jQuery.timerId = setInterval(function(){
- var timers = jQuery.timers;
-
- for ( var i = 0; i < timers.length; i++ )
- if ( !timers[i]() )
- timers.splice(i--, 1);
-
- if ( !timers.length ) {
- clearInterval( jQuery.timerId );
- jQuery.timerId = null;
- }
- }, 13);
- }
- },
-
- // Simple 'show' function
- show: function(){
- // Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
- this.options.show = true;
-
- // Begin the animation
- this.custom(0, this.cur());
-
- // Make sure that we start at a small width/height to avoid any
- // flash of content
- if ( this.prop == "width" || this.prop == "height" )
- this.elem.style[this.prop] = "1px";
-
- // Start by showing the element
- jQuery(this.elem).show();
- },
-
- // Simple 'hide' function
- hide: function(){
- // Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
- this.options.hide = true;
-
- // Begin the animation
- this.custom(this.cur(), 0);
- },
-
- // Each step of an animation
- step: function(gotoEnd){
- var t = now();
-
- if ( gotoEnd || t > this.options.duration + this.startTime ) {
- this.now = this.end;
- this.pos = this.state = 1;
- this.update();
-
- this.options.curAnim[ this.prop ] = true;
-
- var done = true;
- for ( var i in this.options.curAnim )
- if ( this.options.curAnim[i] !== true )
- done = false;
-
- if ( done ) {
- if ( this.options.display != null ) {
- // Reset the overflow
- this.elem.style.overflow = this.options.overflow;
-
- // Reset the display
- this.elem.style.display = this.options.display;
- if ( jQuery.css(this.elem, "display") == "none" )
- this.elem.style.display = "block";
- }
-
- // Hide the element if the "hide" operation was done
- if ( this.options.hide )
- this.elem.style.display = "none";
-
- // Reset the properties, if the item has been hidden or shown
- if ( this.options.hide || this.options.show )
- for ( var p in this.options.curAnim )
- jQuery.attr(this.elem.style, p, this.options.orig[p]);
- }
-
- if ( done )
- // Execute the complete function
- this.options.complete.call( this.elem );
-
- return false;
- } else {
- var n = t - this.startTime;
- this.state = n / this.options.duration;
-
- // Perform the easing function, defaults to swing
- this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
- this.now = this.start + ((this.end - this.start) * this.pos);
-
- // Perform the next step of the animation
- this.update();
- }
-
- return true;
- }
-
-};
-
-jQuery.extend( jQuery.fx, {
- speeds:{
- slow: 600,
- fast: 200,
- // Default speed
- def: 400
- },
- step: {
- scrollLeft: function(fx){
- fx.elem.scrollLeft = fx.now;
- },
-
- scrollTop: function(fx){
- fx.elem.scrollTop = fx.now;
- },
-
- opacity: function(fx){
- jQuery.attr(fx.elem.style, "opacity", fx.now);
- },
-
- _default: function(fx){
- fx.elem.style[ fx.prop ] = fx.now + fx.unit;
- }
- }
-});
-// The Offset Method
-// Originally By Brandon Aaron, part of the Dimension Plugin
-// http://jquery.com/plugins/project/dimensions
-jQuery.fn.offset = function() {
- var left = 0, top = 0, elem = this[0], results;
-
- if ( elem ) with ( jQuery.browser ) {
- var parent = elem.parentNode,
- offsetChild = elem,
- offsetParent = elem.offsetParent,
- doc = elem.ownerDocument,
- safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
- css = jQuery.curCSS,
- fixed = css(elem, "position") == "fixed";
-
- // Use getBoundingClientRect if available
- if ( elem.getBoundingClientRect ) {
- var box = elem.getBoundingClientRect();
-
- // Add the document scroll offsets
- add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
- box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
-
- // IE adds the HTML element's border, by default it is medium which is 2px
- // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
- // IE 7 standards mode, the border is always 2px
- // This border/offset is typically represented by the clientLeft and clientTop properties
- // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
- // Therefore this method will be off by 2px in IE while in quirksmode
- add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
-
- // Otherwise loop through the offsetParents and parentNodes
- } else {
-
- // Initial element offsets
- add( elem.offsetLeft, elem.offsetTop );
-
- // Get parent offsets
- while ( offsetParent ) {
- // Add offsetParent offsets
- add( offsetParent.offsetLeft, offsetParent.offsetTop );
-
- // Mozilla and Safari > 2 does not include the border on offset parents
- // However Mozilla adds the border for table or table cells
- if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
- border( offsetParent );
-
- // Add the document scroll offsets if position is fixed on any offsetParent
- if ( !fixed && css(offsetParent, "position") == "fixed" )
- fixed = true;
-
- // Set offsetChild to previous offsetParent unless it is the body element
- offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
- // Get next offsetParent
- offsetParent = offsetParent.offsetParent;
- }
-
- // Get parent scroll offsets
- while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
- // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
- if ( !/^inline|table.*$/i.test(css(parent, "display")) )
- // Subtract parent scroll offsets
- add( -parent.scrollLeft, -parent.scrollTop );
-
- // Mozilla does not add the border for a parent that has overflow != visible
- if ( mozilla && css(parent, "overflow") != "visible" )
- border( parent );
-
- // Get next parent
- parent = parent.parentNode;
- }
-
- // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
- // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
- if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
- (mozilla && css(offsetChild, "position") != "absolute") )
- add( -doc.body.offsetLeft, -doc.body.offsetTop );
-
- // Add the document scroll offsets if position is fixed
- if ( fixed )
- add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
- Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
- }
-
- // Return an object with top and left properties
- results = { top: top, left: left };
- }
-
- function border(elem) {
- add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
- }
-
- function add(l, t) {
- left += parseInt(l, 10) || 0;
- top += parseInt(t, 10) || 0;
- }
-
- return results;
-};
-
-
-jQuery.fn.extend({
- position: function() {
- var left = 0, top = 0, results;
-
- if ( this[0] ) {
- // Get *real* offsetParent
- var offsetParent = this.offsetParent(),
-
- // Get correct offsets
- offset = this.offset(),
- parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
-
- // Subtract element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
- offset.top -= num( this, 'marginTop' );
- offset.left -= num( this, 'marginLeft' );
-
- // Add offsetParent borders
- parentOffset.top += num( offsetParent, 'borderTopWidth' );
- parentOffset.left += num( offsetParent, 'borderLeftWidth' );
-
- // Subtract the two offsets
- results = {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
- };
- }
-
- return results;
- },
-
- offsetParent: function() {
- var offsetParent = this[0].offsetParent;
- while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
- offsetParent = offsetParent.offsetParent;
- return jQuery(offsetParent);
- }
-});
-
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( ['Left', 'Top'], function(i, name) {
- var method = 'scroll' + name;
-
- jQuery.fn[ method ] = function(val) {
- if (!this[0]) return;
-
- return val != undefined ?
-
- // Set the scroll offset
- this.each(function() {
- this == window || this == document ?
- window.scrollTo(
- !i ? val : jQuery(window).scrollLeft(),
- i ? val : jQuery(window).scrollTop()
- ) :
- this[ method ] = val;
- }) :
-
- // Return the scroll offset
- this[0] == window || this[0] == document ?
- self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
- jQuery.boxModel && document.documentElement[ method ] ||
- document.body[ method ] :
- this[0][ method ];
- };
-});
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each([ "Height", "Width" ], function(i, name){
-
- var tl = i ? "Left" : "Top", // top or left
- br = i ? "Right" : "Bottom"; // bottom or right
-
- // innerHeight and innerWidth
- jQuery.fn["inner" + name] = function(){
- return this[ name.toLowerCase() ]() +
- num(this, "padding" + tl) +
- num(this, "padding" + br);
- };
-
- // outerHeight and outerWidth
- jQuery.fn["outer" + name] = function(margin) {
- return this["inner" + name]() +
- num(this, "border" + tl + "Width") +
- num(this, "border" + br + "Width") +
- (margin ?
- num(this, "margin" + tl) + num(this, "margin" + br) : 0);
- };
-
-});})();
+++ /dev/null
-/*!\r
- SoundManager 2: Javascript Sound for the Web\r
- --------------------------------------------\r
- http://schillmania.com/projects/soundmanager2/\r
-\r
- Copyright (c) 2008, Scott Schiller. All rights reserved.\r
- Code licensed under the BSD License:\r
- http://schillmania.com/projects/soundmanager2/license.txt\r
-\r
- V2.90a.20081028\r
-*/\r
-\r
-function SoundManager(smURL,smID) {\r
- \r
- this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9.\r
- this.debugMode = true; // enable debugging output (div#soundmanager-debug, OR console if available + configured)\r
- this.useConsole = true; // use firebug/safari console.log()-type debug console if available\r
- this.consoleOnly = false; // if console is being used, do not create/write to #soundmanager-debug\r
- this.waitForWindowLoad = false; // force SM2 to wait for window.onload() before trying to call soundManager.onload()\r
- this.nullURL = 'null.mp3'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)\r
- this.allowPolling = true; // allow flash to poll for status update (required for "while playing", peak, sound spectrum functions to work.)\r
- this.useMovieStar = false; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio + video formats (AAC, M4V, FLV, MOV etc.)\r
- this.useHighPerformance = true; // flash positioning trick, improves JS/flash callback speed, minimizes delay\r
- this.bgColor = '#ffffff'; // movie (.swf) background color, useful if showing on-screen for video etc.\r
-\r
- this.defaultOptions = {\r
- 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)\r
- 'stream': true, // allows playing before entire file has loaded (recommended)\r
- 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)\r
- 'onid3': null, // callback function for "ID3 data is added/available"\r
- 'onload': null, // callback function for "load finished"\r
- 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)\r
- 'onplay': null, // callback for "play" start\r
- 'onpause': null, // callback for "pause"\r
- 'onresume': null, // callback for "resume" (pause toggle)\r
- 'whileplaying': null, // callback during play (position update)\r
- 'onstop': null, // callback for "user stop"\r
- 'onfinish': null, // callback function for "sound finished playing"\r
- 'onbeforefinish': null, // callback for "before sound finished playing (at [time])"\r
- 'onbeforefinishtime': 5000, // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)\r
- 'onbeforefinishcomplete':null, // function to call when said sound finishes playing\r
- 'onjustbeforefinish':null, // callback for [n] msec before end of current sound\r
- 'onjustbeforefinishtime':200, // [n] - if not using, set to 0 (or null handler) and event will not fire.\r
- 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time\r
- 'position': null, // offset (milliseconds) to seek to within loaded sound data.\r
- 'pan': 0, // "pan" settings, left-to-right, -100 to 100\r
- 'volume': 100 // self-explanatory. 0-100, the latter being the max.\r
- };\r
-\r
- this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used\r
- 'isMovieStar': null, // "MovieStar" MPEG4 audio/video mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL\r
- 'usePeakData': false, // enable left/right channel peak (level) data\r
- 'useWaveformData': false, // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.\r
- 'useEQData': false // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.\r
- };\r
-\r
- this.movieStarOptions = { // flash 9.0r115+ MPEG4 audio/video options, merged into defaultOptions if flash 9 + movieStar mode is enabled\r
- 'onmetadata': null, // callback for when video width/height etc. are received\r
- 'useVideo': false // if loading movieStar content, whether to show video\r
- }\r
-\r
- this.flashBlockHelper = {\r
- 'enabled': false, // experimental, removed with >v2.80\r
- 'message': [] // "nag bar" to show when messaging the user, if SM2 fails on firefox etc.\r
- };\r
-\r
- var _s = this; \r
- this.version = null;\r
- this.versionNumber = 'V2.90a.20081028';\r
- this.movieURL = null;\r
- this.url = null;\r
- this.altURL = null;\r
- this.swfLoaded = false;\r
- this.enabled = false;\r
- this.o = null;\r
- this.id = (smID||'sm2movie');\r
- this.oMC = null;\r
- this.sounds = [];\r
- this.soundIDs = [];\r
- this.muted = false;\r
- this.isIE = (navigator.userAgent.match(/MSIE/i));\r
- this.isSafari = (navigator.userAgent.match(/safari/i));\r
- this.isGecko = (navigator.userAgent.match(/gecko/i));\r
- this.debugID = 'soundmanager-debug';\r
- this._debugOpen = true;\r
- this._didAppend = false;\r
- this._appendSuccess = false;\r
- this._didInit = false;\r
- this._disabled = false;\r
- this._windowLoaded = false;\r
- this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined');\r
- this._debugLevels = ['log','info','warn','error'];\r
- this._defaultFlashVersion = 8;\r
- this.filePatterns = {\r
- flash8: /\.(mp3)/i,\r
- flash9: /\.(mp3)/i\r
- };\r
- this.netStreamTypes = ['aac','flv','mov','mp4','m4v','f4v','m4a','mp4v','3gp','3g2']; // Flash v9.0r115+ "moviestar" formats\r
- this.netStreamPattern = new RegExp('.('+this.netStreamTypes.join('|')+')','i');\r
- this.filePattern = null;\r
- this.features = {\r
- peakData: false,\r
- waveformData: false,\r
- eqData: false\r
- };\r
-\r
- this.sandbox = {\r
- 'type': null,\r
- 'types': {\r
- 'remote': 'remote (domain-based) rules',\r
- 'localWithFile': 'local with file access (no internet access)',\r
- 'localWithNetwork': 'local with network (internet access only, no local access)',\r
- 'localTrusted': 'local, trusted (local + internet access)'\r
- },\r
- 'description': null,\r
- 'noRemote': null,\r
- 'noLocal': null\r
- };\r
-\r
- this._setVersionInfo = function() {\r
- if (_s.flashVersion != 8 && _s.flashVersion != 9) {\r
- alert('soundManager.flashVersion must be 8 or 9. "'+_s.flashVersion+'" is invalid. Reverting to '+_s._defaultFlashVersion+'.');\r
- _s.flashVersion = _s._defaultFlashVersion;\r
- }\r
- _s.version = _s.versionNumber+(_s.flashVersion==9?' (AS3/Flash 9)':' (AS2/Flash 8)');\r
- // set up default options\r
- if (_s.flashVersion > 8) {\r
- _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.flash9Options);\r
- }\r
- if (_s.flashVersion > 8 && _s.useMovieStar) {\r
- _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.movieStarOptions);\r
- _s.filePatterns.flash9 = new RegExp('.(mp3|'+_s.netStreamTypes.join('|')+')','i');\r
- } else {\r
- _s.useMovieStar = false;\r
- }\r
- _s.filePattern = _s.filePatterns[(_s.flashVersion!=8?'flash9':'flash8')];\r
- _s.movieURL = (_s.flashVersion==8?'soundmanager2.swf':'soundmanager2_flash9.swf');\r
- _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_s.flashVersion==9);\r
- }\r
-\r
- this._overHTTP = (document.location?document.location.protocol.match(/http/i):null);\r
- this._waitingforEI = false;\r
- this._initPending = false;\r
- this._tryInitOnFocus = (this.isSafari && typeof document.hasFocus == 'undefined');\r
- this._isFocused = (typeof document.hasFocus != 'undefined'?document.hasFocus():null);\r
- this._okToDisable = !this._tryInitOnFocus;\r
-\r
- this.useAltURL = !this._overHTTP; // use altURL if not "online"\r
-\r
- var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html';\r
-\r
- // --- public methods ---\r
- \r
- this.supported = function() {\r
- return (_s._didInit && !_s._disabled);\r
- };\r
-\r
- this.getMovie = function(smID) {\r
- return _s.isIE?window[smID]:(_s.isSafari?document.getElementById(smID)||document[smID]:document.getElementById(smID));\r
- };\r
-\r
- this.loadFromXML = function(sXmlUrl) {\r
- try {\r
- _s.o._loadFromXML(sXmlUrl);\r
- } catch(e) {\r
- _s._failSafely();\r
- return true;\r
- };\r
- };\r
-\r
- this.createSound = function(oOptions) {\r
- if (!_s._didInit) throw new Error('soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods');\r
- if (arguments.length==2) {\r
- // function overloading in JS! :) ..assume simple createSound(id,url) use case\r
- var oOptions = {'id':arguments[0],'url':arguments[1]};\r
- };\r
- var thisOptions = _s._mergeObjects(oOptions); // inherit SM2 defaults\r
- var _tO = thisOptions; // alias\r
- _s._wD('soundManager.createSound(): '+_tO.id+' ('+_tO.url+')',1);\r
- if (_s._idCheck(_tO.id,true)) {\r
- _s._wD('soundManager.createSound(): '+_tO.id+' exists',1);\r
- return _s.sounds[_tO.id];\r
- };\r
- if (_s.flashVersion > 8 && _s.useMovieStar) {\r
- if (_tO.isMovieStar == null) {\r
- _tO.isMovieStar = (_tO.url.match(_s.netStreamPattern)?true:false);\r
- }\r
- if (_tO.isMovieStar) {\r
- _s._wD('soundManager.createSound(): using MovieStar handling');\r
- }\r
- if (_tO.isMovieStar && (_tO.usePeakData || _tO.useWaveformData || _tO.useEQData)) {\r
- _s._wD('Warning: peak/waveform/eqData features unsupported for non-MP3 formats');\r
- _tO.usePeakData = false;\r
- _tO.useWaveformData = false;\r
- _tO.useEQData = false;\r
- }\r
- };\r
- _s.sounds[_tO.id] = new SMSound(_tO);\r
- _s.soundIDs[_s.soundIDs.length] = _tO.id;\r
- // AS2:\r
- if (_s.flashVersion == 8) {\r
- _s.o._createSound(_tO.id,_tO.onjustbeforefinishtime);\r
- } else {\r
- _s.o._createSound(_tO.id,_tO.url,_tO.onjustbeforefinishtime,_tO.usePeakData,_tO.useWaveformData,_tO.useEQData,_tO.isMovieStar,(_tO.isMovieStar?_tO.useVideo:false));\r
- };\r
- if (_tO.autoLoad || _tO.autoPlay) {\r
- window.setTimeout(function() {\r
- if (_s.sounds[_tO.id]) {\r
- _s.sounds[_tO.id].load(_tO);\r
- }\r
- },20);\r
- }\r
- if (_tO.autoPlay) {\r
- if (_s.flashVersion == 8) {\r
- _s.sounds[_tO.id].playState = 1; // we can only assume this sound will be playing soon.\r
- } else {\r
- _s.sounds[_tO.id].play(); \r
- }\r
- }\r
- return _s.sounds[_tO.id];\r
- };\r
-\r
- this.createVideo = function(oOptions) {\r
- if (arguments.length==2) {\r
- var oOptions = {'id':arguments[0],'url':arguments[1]};\r
- };\r
- if (_s.flashVersion >= 9) {\r
- oOptions.isMovieStar = true;\r
- oOptions.useVideo = true;\r
- } else {\r
- _s._wD('soundManager.createVideo(): flash 9 required for video. Exiting.',2);\r
- return false;\r
- }\r
- if (!_s.useMovieStar) {\r
- _s._wD('soundManager.createVideo(): MovieStar mode not enabled. Exiting.',2);\r
- }\r
- return _s.createSound(oOptions);\r
- }\r
-\r
- this.destroySound = function(sID,bFromSound) {\r
- // explicitly destroy a sound before normal page unload, etc.\r
- if (!_s._idCheck(sID)) return false;\r
- for (var i=0; i<_s.soundIDs.length; i++) {\r
- if (_s.soundIDs[i] == sID) {\r
- _s.soundIDs.splice(i,1);\r
- continue;\r
- };\r
- };\r
- // conservative option: avoid crash with ze flash 8\r
- // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP + flash 8??\r
- // if (_s.flashVersion != 8) {\r
- _s.sounds[sID].unload();\r
- // }\r
- if (!bFromSound) {\r
- // ignore if being called from SMSound instance\r
- _s.sounds[sID].destruct();\r
- };\r
- delete _s.sounds[sID];\r
- };\r
-\r
- this.destroyVideo = this.destroySound;\r
-\r
- this.load = function(sID,oOptions) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].load(oOptions);\r
- };\r
-\r
- this.unload = function(sID) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].unload();\r
- };\r
-\r
- this.play = function(sID,oOptions) {\r
- if (!_s._idCheck(sID)) {\r
- if (typeof oOptions != 'Object') oOptions = {url:oOptions}; // overloading use case: play('mySound','/path/to/some.mp3');\r
- if (oOptions && oOptions.url) {\r
- // overloading use case, creation + playing of sound: .play('someID',{url:'/path/to.mp3'});\r
- _s._wD('soundController.play(): attempting to create "'+sID+'"',1);\r
- oOptions.id = sID;\r
- _s.createSound(oOptions);\r
- } else {\r
- return false;\r
- };\r
- };\r
- _s.sounds[sID].play(oOptions);\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.setPosition = function(sID,nMsecOffset) {\r
- if (!_s._idCheck(sID)) return false;\r
- nMsecOffset = Math.min((nMsecOffset||0),_s.duration); // don't allow seek past loaded duration\r
- _s.sounds[sID].setPosition(nMsecOffset);\r
- };\r
-\r
- this.stop = function(sID) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s._wD('soundManager.stop('+sID+')',1);\r
- _s.sounds[sID].stop(); \r
- };\r
-\r
- this.stopAll = function() {\r
- _s._wD('soundManager.stopAll()',1);\r
- for (var oSound in _s.sounds) {\r
- if (_s.sounds[oSound] instanceof SMSound) _s.sounds[oSound].stop(); // apply only to sound objects\r
- };\r
- };\r
-\r
- this.pause = function(sID) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].pause();\r
- };\r
-\r
- this.pauseAll = function() {\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].pause();\r
- }\r
- };\r
-\r
- this.resume = function(sID) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].resume();\r
- };\r
-\r
- this.resumeAll = function() {\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].resume();\r
- }\r
- };\r
-\r
- this.togglePause = function(sID) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].togglePause();\r
- };\r
-\r
- this.setPan = function(sID,nPan) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].setPan(nPan);\r
- };\r
-\r
- this.setVolume = function(sID,nVol) {\r
- if (!_s._idCheck(sID)) return false;\r
- _s.sounds[sID].setVolume(nVol);\r
- };\r
-\r
- this.mute = function(sID) {\r
- if (typeof sID != 'string') sID = null;\r
- if (!sID) {\r
- var o = null;\r
- _s._wD('soundManager.mute(): Muting all sounds');\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].mute();\r
- }\r
- _s.muted = true;\r
- } else {\r
- if (!_s._idCheck(sID)) return false;\r
- _s._wD('soundManager.mute(): Muting "'+sID+'"');\r
- _s.sounds[sID].mute();\r
- }\r
- };\r
-\r
- this.muteAll = function() {\r
- _s.mute();\r
- };\r
-\r
- this.unmute = function(sID) {\r
- if (typeof sID != 'string') sID = null;\r
- if (!sID) {\r
- var o = null;\r
- _s._wD('soundManager.unmute(): Unmuting all sounds');\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].unmute();\r
- }\r
- _s.muted = false;\r
- } else {\r
- if (!_s._idCheck(sID)) return false;\r
- _s._wD('soundManager.unmute(): Unmuting "'+sID+'"');\r
- _s.sounds[sID].unmute();\r
- }\r
- };\r
-\r
- this.unmuteAll = function() {\r
- _s.unmute();\r
- };\r
-\r
- this.setPolling = function(bPolling) {\r
- if (!_s.o || !_s.allowPolling) return false;\r
- // _s._wD('soundManager.setPolling('+bPolling+')');\r
- _s.o._setPolling(bPolling);\r
- };\r
-\r
- this.disable = function(bUnload) {\r
- // destroy all functions\r
- if (_s._disabled) return false;\r
- _s._disabled = true;\r
- _s._wD('soundManager.disable(): Disabling all functions - future calls will return false.',1);\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s._disableObject(_s.sounds[_s.soundIDs[i]]);\r
- };\r
- _s.initComplete(); // fire "complete", despite fail\r
- _s._disableObject(_s);\r
- };\r
-\r
- this.handleFlashBlock = function(bForce) {\r
- // experimental, removed with >v2.80.\r
- return false;\r
- };\r
-\r
- this.canPlayURL = function(sURL) {\r
- return (sURL?(sURL.match(_s.filePattern)?true:false):null); \r
- };\r
-\r
- this.getSoundById = function(sID,suppressDebug) {\r
- if (!sID) throw new Error('SoundManager.getSoundById(): sID is null/undefined');\r
- var result = _s.sounds[sID];\r
- if (!result && !suppressDebug) {\r
- _s._wD('"'+sID+'" is an invalid sound ID.',2);\r
- // soundManager._wD('trace: '+arguments.callee.caller);\r
- };\r
- return result;\r
- };\r
-\r
- this.onload = function() {\r
- // window.onload() equivalent for SM2, ready to create sounds etc.\r
- // this is a stub - you can override this in your own external script, eg. soundManager.onload = function() {}\r
- soundManager._wD('<em>Warning</em>: soundManager.onload() is undefined.',2);\r
- };\r
-\r
- this.onerror = function() {\r
- // stub for user handler, called when SM2 fails to load/init\r
- };\r
-\r
- // --- "private" methods ---\r
-\r
- this._idCheck = this.getSoundById;\r
-\r
- this._disableObject = function(o) {\r
- for (var oProp in o) {\r
- if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') o[oProp] = function(){return false;};\r
- };\r
- oProp = null;\r
- };\r
-\r
- this._failSafely = function() {\r
- // exception handler for "object doesn't support this property or method" or general failure\r
- var fpgssTitle = 'You may need to whitelist this location/domain eg. file:///C:/ or C:/ or mysite.com, or set ALWAYS ALLOW under the Flash Player Global Security Settings page. The latter is probably less-secure.';\r
- var flashCPL = '<a href="'+flashCPLink+'" title="'+fpgssTitle+'">view/edit</a>';\r
- var FPGSS = '<a href="'+flashCPLink+'" title="Flash Player Global Security Settings">FPGSS</a>';\r
- if (!_s._disabled) {\r
- _s._wD('soundManager: Failed to initialise.',2);\r
- _s.disable();\r
- };\r
- };\r
- \r
- this._normalizeMovieURL = function(smURL) {\r
- if (smURL) {\r
- if (smURL.match(/\.swf/)) {\r
- smURL = smURL.substr(0,smURL.lastIndexOf('.swf'));\r
- }\r
- if (smURL.lastIndexOf('/') != smURL.length-1) {\r
- smURL = smURL+'/';\r
- }\r
- }\r
- return(smURL && smURL.lastIndexOf('/')!=-1?smURL.substr(0,smURL.lastIndexOf('/')+1):'./')+_s.movieURL;\r
- };\r
-\r
- this._getDocument = function() {\r
- return (document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName('div')[0]));\r
- };\r
-\r
- this._getDocument._protected = true;\r
-\r
- this._createMovie = function(smID,smURL) {\r
- if (_s._didAppend && _s._appendSuccess) return false; // ignore if already succeeded\r
- if (window.location.href.indexOf('debug=1')+1) _s.debugMode = true; // allow force of debug mode via URL\r
- _s._didAppend = true;\r
- \r
- // safety check for legacy (change to Flash 9 URL)\r
- _s._setVersionInfo();\r
- var remoteURL = (smURL?smURL:_s.url);\r
- var localURL = (_s.altURL?_s.altURL:remoteURL);\r
- _s.url = _s._normalizeMovieURL(_s._overHTTP?remoteURL:localURL);\r
- smURL = _s.url;\r
-\r
- var htmlEmbed = '<embed name="'+smID+'" id="'+smID+'" src="'+smURL+'" width="100%" height="100%" quality="high" allowScriptAccess="always" quality="high" '+(_s.useHighPerformance && !_s.useMovieStar?'wmode="transparent" ':'')+'bgcolor="'+_s.bgColor+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"></embed>';\r
- var htmlObject = '<object id="'+smID+'" data="'+smURL+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+smURL+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(_s.useHighPerformance && !_s.useMovieStar?'<param name="wmode" value="transparent" /> ':'')+'<param name="bgcolor" value="'+_s.bgColor+'" /><!-- --></object>';\r
- var html = (!_s.isIE?htmlEmbed:htmlObject);\r
-\r
- var toggleElement = '<div id="'+_s.debugID+'-toggle" style="position:fixed;_position:absolute;right:0px;bottom:0px;_top:0px;width:1.2em;height:1.2em;line-height:1.2em;margin:2px;padding:0px;text-align:center;border:1px solid #999;cursor:pointer;background:#fff;color:#333;z-index:10001" title="Toggle SM2 debug console" onclick="soundManager._toggleDebug()">-</div>';\r
- var debugHTML = '<div id="'+_s.debugID+'" style="display:'+(_s.debugMode && ((!_s._hasConsole||!_s.useConsole)||(_s.useConsole && _s._hasConsole && !_s.consoleOnly))?'block':'none')+';opacity:0.85"></div>';\r
- var appXHTML = 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.';\r
-\r
- var oTarget = _s._getDocument();\r
- if (oTarget) {\r
- \r
- _s.oMC = document.getElementById('sm2-container')?document.getElementById('sm2-container'):document.createElement('div');\r
- if (!_s.oMC.id) {\r
- _s.oMC.id = 'sm2-container';\r
- _s.oMC.className = 'movieContainer';\r
- // "hide" flash movie\r
- var s = null;\r
- if (_s.useHighPerformance) {\r
- s = {\r
- position: 'fixed',\r
- width: '8px',\r
- height: '8px', // must be at least 6px for flash to run fast. odd? yes.\r
- bottom: '0px',\r
- left: '0px',\r
- zIndex:-1 // sit behind everything else\r
- }\r
- } else {\r
- s = {\r
- position: 'absolute',\r
- width: '1px',\r
- height: '1px',\r
- bottom: '0px',\r
- left: '0px'\r
- }\r
- }\r
- var x = null;\r
- for (x in s) {\r
- _s.oMC.style[x] = s[x];\r
- }\r
- try {\r
- oTarget.appendChild(_s.oMC);\r
- _s.oMC.innerHTML = html;\r
- _s._appendSuccess = true;\r
- } catch(e) {\r
- throw new Error(appXHTML);\r
- }\r
- } else {\r
- // it's already in the document.\r
- _s.oMC.innerHTML = html;\r
- _s._appendSuccess = true;\r
- }\r
- if (!document.getElementById(_s.debugID) && ((!_s._hasConsole||!_s.useConsole)||(_s.useConsole && _s._hasConsole && !_s.consoleOnly))) {\r
- var oDebug = document.createElement('div');\r
- oDebug.id = _s.debugID;\r
- oDebug.style.display = (_s.debugMode?'block':'none');\r
- if (_s.debugMode) {\r
- try {\r
- var oD = document.createElement('div');\r
- oTarget.appendChild(oD);\r
- oD.innerHTML = toggleElement;\r
- } catch(e) {\r
- throw new Error(appXHTML);\r
- };\r
- };\r
- oTarget.appendChild(oDebug);\r
- };\r
- oTarget = null;\r
- };\r
- _s._wD('-- SoundManager 2 '+_s.version+(_s.useMovieStar?', MovieStar mode':'')+(_s._wD?', high performance mode':'')+' --',1);\r
- _s._wD('soundManager._createMovie(): Trying to load '+smURL+(!_s._overHTTP && _s.altURL?'(alternate URL)':''),1);\r
- };\r
-\r
- // aliased to this._wD()\r
- this._writeDebug = function(sText,sType,bTimestamp) {\r
- if (!_s.debugMode) return false;\r
- if (typeof bTimestamp != 'undefined' && bTimestamp) {\r
- sText = sText + ' | '+new Date().getTime();\r
- };\r
- if (_s._hasConsole && _s.useConsole) {\r
- var sMethod = _s._debugLevels[sType];\r
- if (typeof console[sMethod] != 'undefined') {\r
- console[sMethod](sText);\r
- } else {\r
- console.log(sText);\r
- };\r
- if (_s.useConsoleOnly) return true;\r
- };\r
- var sDID = 'soundmanager-debug';\r
- try {\r
- var o = document.getElementById(sDID);\r
- if (!o) return false;\r
- var oItem = document.createElement('div');\r
- sText = sText.replace(/\n/g,'<br />');\r
- if (typeof sType == 'undefined') {\r
- var sType = 0;\r
- } else {\r
- sType = parseInt(sType);\r
- };\r
- oItem.innerHTML = sText;\r
- if (sType) {\r
- if (sType >= 2) oItem.style.fontWeight = 'bold';\r
- if (sType == 3) oItem.style.color = '#ff3333';\r
- };\r
- // o.appendChild(oItem); // top-to-bottom\r
- o.insertBefore(oItem,o.firstChild); // bottom-to-top\r
- } catch(e) {\r
- // oh well\r
- };\r
- o = null;\r
- };\r
- this._writeDebug._protected = true;\r
- this._wD = this._writeDebug;\r
-\r
- this._wDAlert = function(sText) { alert(sText); };\r
-\r
- if (window.location.href.indexOf('debug=alert')+1 && _s.debugMode) {\r
- _s._wD = _s._wDAlert;\r
- };\r
-\r
- this._toggleDebug = function() {\r
- var o = document.getElementById(_s.debugID);\r
- var oT = document.getElementById(_s.debugID+'-toggle');\r
- if (!o) return false;\r
- if (_s._debugOpen) {\r
- // minimize\r
- oT.innerHTML = '+';\r
- o.style.display = 'none';\r
- } else {\r
- oT.innerHTML = '-';\r
- o.style.display = 'block';\r
- };\r
- _s._debugOpen = !_s._debugOpen;\r
- };\r
-\r
- this._toggleDebug._protected = true;\r
-\r
- this._debug = function() {\r
- _s._wD('--- soundManager._debug(): Current sound objects ---',1);\r
- for (var i=0,j=_s.soundIDs.length; i<j; i++) {\r
- _s.sounds[_s.soundIDs[i]]._debug();\r
- };\r
- };\r
-\r
- this._mergeObjects = function(oMain,oAdd) {\r
- // non-destructive merge\r
- var o1 = {}; // clone o1\r
- for (var i in oMain) {\r
- o1[i] = oMain[i];\r
- }\r
- var o2 = (typeof oAdd == 'undefined'?_s.defaultOptions:oAdd);\r
- for (var o in o2) {\r
- if (typeof o1[o] == 'undefined') o1[o] = o2[o];\r
- };\r
- return o1;\r
- };\r
-\r
- this.createMovie = function(sURL) {\r
- if (sURL) _s.url = sURL;\r
- _s._initMovie();\r
- };\r
-\r
- this.go = this.createMovie; // nice alias\r
-\r
- this._initMovie = function() {\r
- // attempt to get, or create, movie\r
- if (_s.o) return false; // pre-init may have fired this function before window.onload(), may already exist\r
- _s.o = _s.getMovie(_s.id); // try to get flash movie (inline markup)\r
- if (!_s.o) {\r
- // try to create\r
- _s._createMovie(_s.id,_s.url);\r
- _s.o = _s.getMovie(_s.id);\r
- };\r
- if (_s.o) {\r
- _s._wD('soundManager._initMovie(): Got '+_s.o.nodeName+' element ('+(_s._didAppend?'created via JS':'static HTML')+')',1);\r
- _s._wD('soundManager._initMovie(): Waiting for ExternalInterface call from Flash..');\r
- };\r
- };\r
-\r
- this.waitForExternalInterface = function() {\r
- if (_s._waitingForEI) return false;\r
- _s._waitingForEI = true;\r
- if (_s._tryInitOnFocus && !_s._isFocused) {\r
- _s._wD('soundManager: Special case: Flash may not have started due to non-focused tab (Safari is lame), and/or focus cannot be detected. Waiting for focus-related event..');\r
- return false;\r
- };\r
- if (!_s._didInit) {\r
- _s._wD('soundManager: Getting impatient, still waiting for Flash.. ;)');\r
- };\r
- setTimeout(function() {\r
- if (!_s._didInit) {\r
- _s._wD('soundManager: No Flash response within reasonable time after document load.\nPossible causes: Flash version under 8, no support, or Flash security denying JS-Flash communication.',2);\r
- if (!_s._overHTTP) {\r
- _s._wD('soundManager: Loading this page from local/network file system (not over HTTP?) Flash security likely restricting JS-Flash access. Consider adding current URL to "trusted locations" in the Flash player security settings manager at '+flashCPLink+', or simply serve this content over HTTP.',2);\r
- };\r
- };\r
- // if still not initialized and no other options, give up\r
- if (!_s._didInit && _s._okToDisable) _s._failSafely();\r
- },750);\r
- };\r
-\r
- this.handleFocus = function() {\r
- if (_s._isFocused || !_s._tryInitOnFocus) return true;\r
- _s._okToDisable = true;\r
- _s._isFocused = true;\r
- _s._wD('soundManager.handleFocus()');\r
- if (_s._tryInitOnFocus) {\r
- // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented.\r
- window.removeEventListener('mousemove',_s.handleFocus,false);\r
- };\r
- // allow init to restart\r
- _s._waitingForEI = false;\r
- setTimeout(_s.waitForExternalInterface,500);\r
- // detach event\r
- if (window.removeEventListener) {\r
- window.removeEventListener('focus',_s.handleFocus,false);\r
- } else if (window.detachEvent) {\r
- window.detachEvent('onfocus',_s.handleFocus);\r
- };\r
- };\r
-\r
- this.initComplete = function() {\r
- if (_s._didInit) return false;\r
- _s._didInit = true;\r
- _s._wD('-- SoundManager 2 '+(_s._disabled?'failed to load':'loaded')+' ('+(_s._disabled?'security/load error':'OK')+') --',1);\r
- if (_s._disabled) {\r
- _s._wD('soundManager.initComplete(): calling soundManager.onerror()',1);\r
- _s.onerror.apply(window);\r
- return false;\r
- };\r
- if (_s.waitForWindowLoad && !_s._windowLoaded) {\r
- _s._wD('soundManager: Waiting for window.onload()');\r
- if (window.addEventListener) {\r
- window.addEventListener('load',_s.initUserOnload,false);\r
- } else if (window.attachEvent) {\r
- window.attachEvent('onload',_s.initUserOnload);\r
- };\r
- return false;\r
- } else {\r
- if (_s.waitForWindowLoad && _s._windowLoaded) {\r
- _s._wD('soundManager: Document already loaded');\r
- };\r
- _s.initUserOnload();\r
- };\r
- };\r
-\r
- this.initUserOnload = function() {\r
- _s._wD('soundManager.initComplete(): calling soundManager.onload()',1);\r
- // call user-defined "onload", scoped to window\r
- //try {\r
- _s.onload.apply(window);\r
- /*\r
- } catch(e) {\r
- // something broke (likely JS error in user function)\r
- _s._wD('soundManager.onload() threw an exception: '+e.message,2);\r
- setTimeout(function(){throw new Error(e)},20);\r
- return false;\r
- };\r
- */\r
- _s._wD('soundManager.onload() complete',1);\r
- };\r
-\r
- this.init = function() {\r
- _s._wD('-- soundManager.init() --');\r
- // called after onload()\r
- _s._initMovie();\r
- if (_s._didInit) {\r
- _s._wD('soundManager.init(): Already called?');\r
- return false;\r
- };\r
- // event cleanup\r
- if (window.removeEventListener) {\r
- window.removeEventListener('load',_s.beginDelayedInit,false);\r
- } else if (window.detachEvent) {\r
- window.detachEvent('onload',_s.beginDelayedInit);\r
- };\r
- try {\r
- _s._wD('Attempting to call JS -> Flash..');\r
- _s.o._externalInterfaceTest(false); // attempt to talk to Flash\r
- // _s._wD('Flash ExternalInterface call (JS-Flash) OK',1);\r
- if (!_s.allowPolling) {\r
- _s._wD('Polling (whileloading/whileplaying support) is disabled.',1);\r
- }\r
- _s.setPolling(true);\r
- if (!_s.debugMode) _s.o._disableDebug();\r
- _s.enabled = true;\r
- } catch(e) {\r
- _s._failSafely();\r
- _s.initComplete();\r
- return false;\r
- };\r
- _s.initComplete();\r
- };\r
-\r
- this.beginDelayedInit = function() {\r
- _s._wD('soundManager.beginDelayedInit(): Document loaded');\r
- _s._windowLoaded = true;\r
- setTimeout(_s.waitForExternalInterface,500);\r
- setTimeout(_s.beginInit,20);\r
- };\r
-\r
- this.beginInit = function() {\r
- if (_s._initPending) return false;\r
- _s.createMovie(); // ensure creation if not already done\r
- _s._initMovie();\r
- _s._initPending = true;\r
- return true;\r
- };\r
-\r
- this.domContentLoaded = function() {\r
- _s._wD('soundManager.domContentLoaded()');\r
- if (document.removeEventListener) document.removeEventListener('DOMContentLoaded',_s.domContentLoaded,false);\r
- _s.go();\r
- };\r
-\r
- this._externalInterfaceOK = function() {\r
- // callback from flash for confirming that movie loaded, EI is working etc.\r
- if (_s.swfLoaded) return false;\r
- _s._wD('soundManager._externalInterfaceOK()');\r
- _s.swfLoaded = true;\r
- _s._tryInitOnFocus = false;\r
- if (_s.isIE) {\r
- // IE needs a timeout OR delay until window.onload - may need TODO: investigating\r
- setTimeout(_s.init,100);\r
- } else {\r
- _s.init();\r
- };\r
- };\r
-\r
- this._setSandboxType = function(sandboxType) {\r
- var sb = _s.sandbox;\r
- sb.type = sandboxType;\r
- sb.description = sb.types[(typeof sb.types[sandboxType] != 'undefined'?sandboxType:'unknown')];\r
- _s._wD('Flash security sandbox type: '+sb.type);\r
- if (sb.type == 'localWithFile') {\r
- sb.noRemote = true;\r
- sb.noLocal = false;\r
- _s._wD('Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html',2);\r
- } else if (sb.type == 'localWithNetwork') {\r
- sb.noRemote = false;\r
- sb.noLocal = true;\r
- } else if (sb.type == 'localTrusted') {\r
- sb.noRemote = false;\r
- sb.noLocal = false;\r
- };\r
- };\r
-\r
- this.destruct = function() {\r
- _s._wD('soundManager.destruct()');\r
- _s.disable(true);\r
- };\r
- \r
- // SMSound (sound object)\r
- \r
- function SMSound(oOptions) {\r
- var _t = this;\r
- this.sID = oOptions.id;\r
- this.url = oOptions.url;\r
- this.options = _s._mergeObjects(oOptions);\r
- this.instanceOptions = this.options; // per-play-instance-specific options\r
- this._iO = this.instanceOptions; // short alias\r
-\r
- this._debug = function() {\r
- if (_s.debugMode) {\r
- var stuff = null;\r
- var msg = [];\r
- var sF = null;\r
- var sfBracket = null;\r
- var maxLength = 64; // # of characters of function code to show before truncating\r
- for (stuff in _t.options) {\r
- if (_t.options[stuff] != null) {\r
- if (_t.options[stuff] instanceof Function) {\r
- // handle functions specially\r
- sF = _t.options[stuff].toString();\r
- sF = sF.replace(/\s\s+/g,' '); // normalize spaces\r
- sfBracket = sF.indexOf('{');\r
- msg[msg.length] = ' '+stuff+': {'+sF.substr(sfBracket+1,(Math.min(Math.max(sF.indexOf('\n')-1,maxLength),maxLength))).replace(/\n/g,'')+'... }';\r
- } else {\r
- msg[msg.length] = ' '+stuff+': '+_t.options[stuff];\r
- };\r
- };\r
- };\r
- _s._wD('SMSound() merged options: {\n'+msg.join(', \n')+'\n}');\r
- };\r
- };\r
-\r
- this._debug();\r
-\r
- this.id3 = {\r
- /* \r
- Name/value pairs set via Flash when available - see reference for names:\r
- http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html\r
- (eg., this.id3.songname or this.id3['songname'])\r
- */\r
- };\r
-\r
- this.resetProperties = function(bLoaded) {\r
- _t.bytesLoaded = null;\r
- _t.bytesTotal = null;\r
- _t.position = null;\r
- _t.duration = null;\r
- _t.durationEstimate = null;\r
- _t.loaded = false;\r
- _t.playState = 0;\r
- _t.paused = false;\r
- _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success\r
- _t.muted = false;\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- _t.instanceOptions = {};\r
- _t.instanceCount = 0;\r
- _t.peakData = {\r
- left: 0,\r
- right: 0\r
- };\r
- _t.waveformData = [];\r
- _t.eqData = [];\r
- };\r
-\r
- _t.resetProperties();\r
-\r
- // --- public methods ---\r
-\r
- this.load = function(oOptions) {\r
- if (typeof oOptions != 'undefined') {\r
- _t._iO = _s._mergeObjects(oOptions);\r
- _t.instanceOptions = _t._iO;\r
- } else {\r
- var oOptions = _t.options;\r
- _t._iO = oOptions;\r
- _t.instanceOptions = _t._iO;\r
- } \r
- if (typeof _t._iO.url == 'undefined') _t._iO.url = _t.url;\r
- _s._wD('soundManager.load(): '+_t._iO.url,1);\r
- if (_t._iO.url == _t.url && _t.readyState != 0 && _t.readyState != 2) {\r
- _s._wD('soundManager.load(): current URL already assigned.',1);\r
- return false;\r
- }\r
- _t.loaded = false;\r
- _t.readyState = 1;\r
- _t.playState = (oOptions.autoPlay?1:0); // if autoPlay, assume "playing" is true (no way to detect when it actually starts in Flash unless onPlay is watched?)\r
- try {\r
- if (_s.flashVersion==8) {\r
- _s.o._load(_t.sID,_t._iO.url,_t._iO.stream,_t._iO.autoPlay,(_t._iO.whileloading?1:0));\r
- } else {\r
- _s.o._load(_t.sID,_t._iO.url,_t._iO.stream?true:false,_t._iO.autoPlay?true:false); // ,(_tO.whileloading?true:false)\r
- if (_t._iO.isMovieStar && _t._iO.autoLoad && !_t._iO.autoPlay) {\r
- // special case: MPEG4 content must start playing to load, then pause to prevent playing.\r
- _t.pause();\r
- }\r
- };\r
- } catch(e) {\r
- _s._wD('SMSound.load(): Exception: JS-Flash communication failed, or JS error.',2);\r
- _s.onerror();\r
- _s.disable();\r
- };\r
- };\r
-\r
- this.unload = function() {\r
- // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3\r
- // Flash 9/AS3: Close stream, preventing further load\r
- if (_t.readyState != 0) {\r
- _s._wD('SMSound.unload(): "'+_t.sID+'"');\r
- if (_t.readyState != 2) { // reset if not error\r
- _t.setPosition(0); // reset current sound positioning\r
- }\r
- _s.o._unload(_t.sID,_s.nullURL);\r
- // reset load/status flags\r
- _t.resetProperties();\r
- }\r
- };\r
-\r
- this.destruct = function() {\r
- // kill sound within Flash\r
- _s._wD('SMSound.destruct(): "'+_t.sID+'"');\r
- _s.o._destroySound(_t.sID);\r
- _s.destroySound(_t.sID,true); // ensure deletion from controller\r
- }\r
-\r
- this.play = function(oOptions) {\r
- if (!oOptions) oOptions = {};\r
- _t._iO = _s._mergeObjects(oOptions,_t._iO);\r
- _t._iO = _s._mergeObjects(_t._iO,_t.options);\r
- _t.instanceOptions = _t._iO;\r
- if (_t.playState == 1) {\r
- var allowMulti = _t._iO.multiShot;\r
- if (!allowMulti) {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" already playing (one-shot)',1);\r
- return false;\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" already playing (multi-shot)',1);\r
- };\r
- };\r
- if (!_t.loaded) {\r
- if (_t.readyState == 0) {\r
- _s._wD('SMSound.play(): Attempting to load "'+_t.sID+'"',1);\r
- // try to get this sound playing ASAP\r
- _t._iO.stream = true;\r
- _t._iO.autoPlay = true;\r
- // TODO: need to investigate when false, double-playing\r
- // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here\r
- _t.load(_t._iO); // try to get this sound playing ASAP\r
- } else if (_t.readyState == 2) {\r
- _s._wD('SMSound.play(): Could not load "'+_t.sID+'" - exiting',2);\r
- return false;\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" is loading - attempting to play..',1);\r
- };\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'"');\r
- };\r
- if (_t.paused) {\r
- _t.resume();\r
- } else {\r
- _t.playState = 1;\r
- if (!_t.instanceCount || _s.flashVersion == 9) _t.instanceCount++;\r
- _t.position = (typeof _t._iO.position != 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);\r
- if (_t._iO.onplay) _t._iO.onplay.apply(_t);\r
- _t.setVolume(_t._iO.volume);\r
- _t.setPan(_t._iO.pan);\r
- _s.o._start(_t.sID,_t._iO.loop||1,(_s.flashVersion==9?_t.position:_t.position/1000));\r
- };\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.stop = function(bAll) {\r
- if (_t.playState == 1) {\r
- _t.playState = 0;\r
- _t.paused = false;\r
- // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);\r
- if (_t._iO.onstop) _t._iO.onstop.apply(_t);\r
- _s.o._stop(_t.sID,bAll);\r
- _t.instanceCount = 0;\r
- _t._iO = {};\r
- // _t.instanceOptions = _t._iO;\r
- };\r
- };\r
-\r
- this.setPosition = function(nMsecOffset) {\r
- _t._iO.position = nMsecOffset;\r
- _s._wD('SMSound.setPosition('+nMsecOffset+')');\r
- _s.o._setPosition(_t.sID,(_s.flashVersion==9?_t._iO.position:_t._iO.position/1000),(_t.paused||!_t.playState)); // if paused or not playing, will not resume (by playing)\r
- };\r
-\r
- this.pause = function() {\r
- if (_t.paused || _t.playState == 0) return false;\r
- _s._wD('SMSound.pause()');\r
- _t.paused = true;\r
- _s.o._pause(_t.sID);\r
- if (_t._iO.onpause) _t._iO.onpause.apply(_t);\r
- };\r
-\r
- this.resume = function() {\r
- if (!_t.paused || _t.playState == 0) return false;\r
- _s._wD('SMSound.resume()');\r
- _t.paused = false;\r
- _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)\r
- if (_t._iO.onresume) _t._iO.onresume.apply(_t);\r
- };\r
-\r
- this.togglePause = function() {\r
- _s._wD('SMSound.togglePause()');\r
- if (!_t.playState) {\r
- _t.play({position:(_s.flashVersion==9?_t.position:_t.position/1000)});\r
- return false;\r
- };\r
- if (_t.paused) {\r
- _t.resume();\r
- } else {\r
- _t.pause();\r
- };\r
- };\r
-\r
- this.setPan = function(nPan) {\r
- if (typeof nPan == 'undefined') nPan = 0;\r
- _s.o._setPan(_t.sID,nPan);\r
- _t._iO.pan = nPan;\r
- };\r
-\r
- this.setVolume = function(nVol) {\r
- if (typeof nVol == 'undefined') nVol = 100;\r
- _s.o._setVolume(_t.sID,(_s.muted&&!_t.muted)||_t.muted?0:nVol);\r
- _t._iO.volume = nVol;\r
- };\r
-\r
- this.mute = function() {\r
- _t.muted = true;\r
- _s.o._setVolume(_t.sID,0);\r
- };\r
-\r
- this.unmute = function() {\r
- _t.muted = false;\r
- _s.o._setVolume(_t.sID,typeof _t._iO.volume != 'undefined'?_t._iO.volume:_t.options.volume);\r
- };\r
-\r
- // --- "private" methods called by Flash ---\r
-\r
- this._whileloading = function(nBytesLoaded,nBytesTotal,nDuration) {\r
- if (!_t._iO.isMovieStar) {\r
- _t.bytesLoaded = nBytesLoaded;\r
- _t.bytesTotal = nBytesTotal;\r
- _t.duration = Math.floor(nDuration);\r
- _t.durationEstimate = parseInt((_t.bytesTotal/_t.bytesLoaded)*_t.duration); // estimate total time (will only be accurate with CBR MP3s.)\r
- if (_t.readyState != 3 && _t._iO.whileloading) _t._iO.whileloading.apply(_t);\r
- } else {\r
- _t.bytesLoaded = nBytesLoaded;\r
- _t.bytesTotal = nBytesTotal;\r
- _t.duration = Math.floor(nDuration);\r
- _t.durationEstimate = _t.duration;\r
- if (_t.readyState != 3 && _t._iO.whileloading) _t._iO.whileloading.apply(_t);\r
- }\r
- };\r
-\r
- this._onid3 = function(oID3PropNames,oID3Data) {\r
- // oID3PropNames: string array (names)\r
- // ID3Data: string array (data)\r
- _s._wD('SMSound._onid3(): "'+this.sID+'" ID3 data received.');\r
- var oData = [];\r
- for (var i=0,j=oID3PropNames.length; i<j; i++) {\r
- oData[oID3PropNames[i]] = oID3Data[i];\r
- // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);\r
- };\r
- _t.id3 = _s._mergeObjects(_t.id3,oData);\r
- if (_t._iO.onid3) _t._iO.onid3.apply(_t);\r
- };\r
-\r
- this._whileplaying = function(nPosition,oPeakData,oWaveformData,oEQData) {\r
- if (isNaN(nPosition) || nPosition == null) return false; // Flash may return NaN at times\r
- _t.position = nPosition;\r
- if (_t._iO.usePeakData && typeof oPeakData != 'undefined' && oPeakData) {\r
- _t.peakData = {\r
- left: oPeakData.leftPeak,\r
- right: oPeakData.rightPeak\r
- };\r
- };\r
- if (_t._iO.useWaveformData && typeof oWaveformData != 'undefined' && oWaveformData) {\r
- _t.waveformData = oWaveformData;\r
- /*\r
- _t.spectrumData = {\r
- left: oSpectrumData.left.split(','),\r
- right: oSpectrumData.right.split(',')\r
- }\r
- */\r
- };\r
- if (_t._iO.useEQData && typeof oEQData != 'undefined' && oEQData) {\r
- _t.eqData = oEQData;\r
- };\r
- if (_t.playState == 1) {\r
- if (_t._iO.whileplaying) {\r
- _t._iO.whileplaying.apply(_t); // flash may call after actual finish\r
- };\r
- if (_t.loaded && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration-_t.position <= _t._iO.onbeforefinishtime) {\r
- _s._wD('duration-position <= onbeforefinishtime: '+_t.duration+' - '+_t.position+' <= '+_t._iO.onbeforefinishtime+' ('+(_t.duration-_t.position)+')');\r
- _t._onbeforefinish();\r
- };\r
- };\r
- };\r
-\r
- this._onload = function(bSuccess) {\r
- bSuccess = (bSuccess==1?true:false);\r
- _s._wD('SMSound._onload(): "'+_t.sID+'"'+(bSuccess?' loaded.':' failed to load? - '+_t.url));\r
- if (!bSuccess) {\r
- if (_s.sandbox.noRemote == true) {\r
- _s._wD('SMSound._onload(): Reminder: Flash security is denying network/internet access',1);\r
- };\r
- if (_s.sandbox.noLocal == true) {\r
- _s._wD('SMSound._onload(): Reminder: Flash security is denying local access',1);\r
- };\r
- };\r
- _t.loaded = bSuccess;\r
- _t.readyState = bSuccess?3:2;\r
- if (_t._iO.onload) {\r
- _t._iO.onload.apply(_t);\r
- };\r
- };\r
-\r
- this._onbeforefinish = function() {\r
- if (!_t.didBeforeFinish) {\r
- _t.didBeforeFinish = true;\r
- if (_t._iO.onbeforefinish) {\r
- _s._wD('SMSound._onbeforefinish(): "'+_t.sID+'"');\r
- _t._iO.onbeforefinish.apply(_t);\r
- }\r
- };\r
- };\r
-\r
- this._onjustbeforefinish = function(msOffset) {\r
- // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187)\r
- if (!_t.didJustBeforeFinish) {\r
- _t.didJustBeforeFinish = true;\r
- if (_t._iO.onjustbeforefinish) {\r
- _s._wD('SMSound._onjustbeforefinish(): "'+_t.sID+'"');\r
- _t._iO.onjustbeforefinish.apply(_t);\r
- }\r
- };\r
- };\r
-\r
- this._onfinish = function() {\r
- // sound has finished playing\r
- _t.playState = 0;\r
- _t.paused = false;\r
- if (_t._iO.onfinish) {\r
- _s._wD('SMSound._onfinish(): "'+_t.sID+'"');\r
- _t._iO.onfinish.apply(_t);\r
- }\r
- if (_t._iO.onbeforefinishcomplete) _t._iO.onbeforefinishcomplete.apply(_t);\r
- // reset some state items\r
- _t.setPosition(0);\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- if (_t.instanceCount) {\r
- _t.instanceCount--;\r
- if (!_t.instanceCount) {\r
- // reset instance options\r
- _t.instanceCount = 0;\r
- _t.instanceOptions = {};\r
- }\r
- }\r
- };\r
-\r
- this._onmetadata = function(oMetaData) {\r
- // movieStar mode only\r
- _s._wD('SMSound.onmetadata()');\r
- // Contains a subset of metadata. Note that files may have their own unique metadata.\r
- // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html\r
- if (!oMetaData.width && !oMetaData.height) {\r
- _s._wD('No width/height given, assuming defaults');\r
- oMetaData.width = 320;\r
- oMetaData.height = 240;\r
- };\r
- _t.metadata = oMetaData; // potentially-large object from flash\r
- _t.width = oMetaData.width;\r
- _t.height = oMetaData.height;\r
- if (_t._iO.onmetadata) {\r
- _s._wD('SMSound._onmetadata(): "'+_t.sID+'"');\r
- _t._iO.onmetadata.apply(_t);\r
- }\r
- _s.wD('SMSound.onmetadata() complete');\r
- };\r
-\r
- }; // SMSound()\r
-\r
- // register a few event handlers\r
- if (window.addEventListener) {\r
- window.addEventListener('focus',_s.handleFocus,false);\r
- window.addEventListener('load',_s.beginDelayedInit,false);\r
- window.addEventListener('unload',_s.destruct,false);\r
- if (_s._tryInitOnFocus) window.addEventListener('mousemove',_s.handleFocus,false); // massive Safari focus hack\r
- } else if (window.attachEvent) {\r
- window.attachEvent('onfocus',_s.handleFocus);\r
- window.attachEvent('onload',_s.beginDelayedInit);\r
- window.attachEvent('unload',_s.destruct);\r
- } else {\r
- // no add/attachevent support - safe to assume no JS -> Flash either.\r
- soundManager.onerror();\r
- soundManager.disable();\r
- };\r
-\r
- if (document.addEventListener) document.addEventListener('DOMContentLoaded',_s.domContentLoaded,false);\r
-\r
-}; // SoundManager()\r
-\r
-var soundManager = new SoundManager();\r
+++ /dev/null
-/* This notice must be untouched at all times.\r
-\r
-wz_jsgraphics.js v. 3.03\r
-The latest version is available at\r
-http://www.walterzorn.com\r
-or http://www.devira.com\r
-or http://www.walterzorn.de\r
-\r
-Copyright (c) 2002-2004 Walter Zorn. All rights reserved.\r
-Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )\r
-Last modified: 28. 1. 2008\r
-\r
-Performance optimizations for Internet Explorer\r
-by Thomas Frank and John Holdsworth.\r
-fillPolygon method implemented by Matthieu Haller.\r
-\r
-High Performance JavaScript Graphics Library.\r
-Provides methods\r
-- to draw lines, rectangles, ellipses, polygons\r
- with specifiable line thickness,\r
-- to fill rectangles, polygons, ellipses and arcs\r
-- to draw text.\r
-NOTE: Operations, functions and branching have rather been optimized\r
-to efficiency and speed than to shortness of source code.\r
-\r
-LICENSE: LGPL\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License (LGPL) as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,\r
-or see http://www.gnu.org/copyleft/lesser.html\r
-*/\r
-\r
-\r
-var jg_ok, jg_ie, jg_fast, jg_dom, jg_moz;\r
-\r
-\r
-function _chkDHTM(x, i)\r
-{\r
- x = document.body || null;\r
- jg_ie = x && typeof x.insertAdjacentHTML != "undefined" && document.createElement;\r
- jg_dom = (x && !jg_ie &&\r
- typeof x.appendChild != "undefined" &&\r
- typeof document.createRange != "undefined" &&\r
- typeof (i = document.createRange()).setStartBefore != "undefined" &&\r
- typeof i.createContextualFragment != "undefined");\r
- jg_fast = jg_ie && document.all && !window.opera;\r
- jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";\r
- jg_ok = !!(jg_ie || jg_dom);\r
-}\r
-\r
-function _pntCnvDom()\r
-{\r
- var x = this.wnd.document.createRange();\r
- x.setStartBefore(this.cnv);\r
- x = x.createContextualFragment(jg_fast? this._htmRpc() : this.htm);\r
- if(this.cnv) this.cnv.appendChild(x);\r
- this.htm = "";\r
-}\r
-\r
-function _pntCnvIe()\r
-{\r
- if(this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this._htmRpc() : this.htm);\r
- this.htm = "";\r
-}\r
-\r
-function _pntDoc()\r
-{\r
- this.wnd.document.write(jg_fast? this._htmRpc() : this.htm);\r
- this.htm = '';\r
-}\r
-\r
-function _pntN()\r
-{\r
- ;\r
-}\r
-\r
-function _mkDiv(x, y, w, h)\r
-{\r
- this.htm += '<div style="position:absolute;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:' + w + 'px;'+\r
- 'height:' + h + 'px;'+\r
- 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
- 'background-color:' + this.color +\r
- (!jg_moz? ';overflow:hidden' : '')+\r
- ';"><\/div>';\r
-}\r
-\r
-function _mkDivIe(x, y, w, h)\r
-{\r
- this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';\r
-}\r
-\r
-function _mkDivPrt(x, y, w, h)\r
-{\r
- this.htm += '<div style="position:absolute;'+\r
- 'border-left:' + w + 'px solid ' + this.color + ';'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:0px;'+\r
- 'height:' + h + 'px;'+\r
- 'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
- 'background-color:' + this.color +\r
- (!jg_moz? ';overflow:hidden' : '')+\r
- ';"><\/div>';\r
-}\r
-\r
-var _regex = /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;\r
-function _htmRpc()\r
-{\r
- return this.htm.replace(\r
- _regex,\r
- '<div style="overflow:hidden;position:absolute;background-color:'+\r
- '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');\r
-}\r
-\r
-function _htmPrtRpc()\r
-{\r
- return this.htm.replace(\r
- _regex,\r
- '<div style="overflow:hidden;position:absolute;background-color:'+\r
- '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');\r
-}\r
-\r
-function _mkLin(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1;\r
-\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx,\r
- ox = x;\r
- while(dx > 0)\r
- {--dx;\r
- ++x;\r
- if(p > 0)\r
- {\r
- this._mkDiv(ox, y, x-ox, 1);\r
- y += yIncr;\r
- p += pru;\r
- ox = x;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(ox, y, x2-ox+1, 1);\r
- }\r
-\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy,\r
- oy = y;\r
- if(y2 <= y1)\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, y, 1, oy-y+1);\r
- y += yIncr;\r
- p += pru;\r
- oy = y;\r
- }\r
- else\r
- {\r
- y += yIncr;\r
- p += pr;\r
- }\r
- }\r
- this._mkDiv(x2, y2, 1, oy-y2+1);\r
- }\r
- else\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, oy, 1, y-oy);\r
- p += pru;\r
- oy = y;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(x2, oy, 1, y2-oy+1);\r
- }\r
- }\r
-}\r
-\r
-function _mkLin2D(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1;\r
-\r
- var s = this.stroke;\r
- if(dx >= dy)\r
- {\r
- if(dx > 0 && s-3 > 0)\r
- {\r
- var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;\r
- _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
- }\r
- else var _s = s;\r
- var ad = Math.ceil(s/2);\r
-\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx,\r
- ox = x;\r
- while(dx > 0)\r
- {--dx;\r
- ++x;\r
- if(p > 0)\r
- {\r
- this._mkDiv(ox, y, x-ox+ad, _s);\r
- y += yIncr;\r
- p += pru;\r
- ox = x;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(ox, y, x2-ox+ad+1, _s);\r
- }\r
-\r
- else\r
- {\r
- if(s-3 > 0)\r
- {\r
- var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;\r
- _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
- }\r
- else var _s = s;\r
- var ad = Math.round(s/2);\r
-\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy,\r
- oy = y;\r
- if(y2 <= y1)\r
- {\r
- ++ad;\r
- while(dy > 0)\r
- {--dy;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, y, _s, oy-y+ad);\r
- y += yIncr;\r
- p += pru;\r
- oy = y;\r
- }\r
- else\r
- {\r
- y += yIncr;\r
- p += pr;\r
- }\r
- }\r
- this._mkDiv(x2, y2, _s, oy-y2+ad);\r
- }\r
- else\r
- {\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- this._mkDiv(x++, oy, _s, y-oy+ad);\r
- p += pru;\r
- oy = y;\r
- }\r
- else p += pr;\r
- }\r
- this._mkDiv(x2, oy, _s, y2-oy+ad+1);\r
- }\r
- }\r
-}\r
-\r
-function _mkLinDott(x1, y1, x2, y2)\r
-{\r
- if(x1 > x2)\r
- {\r
- var _x2 = x2;\r
- var _y2 = y2;\r
- x2 = x1;\r
- y2 = y1;\r
- x1 = _x2;\r
- y1 = _y2;\r
- }\r
- var dx = x2-x1, dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- yIncr = (y1 > y2)? -1 : 1,\r
- drw = true;\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1),\r
- p = pr-dx;\r
- while(dx > 0)\r
- {--dx;\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
- drw = !drw;\r
- if(p > 0)\r
- {\r
- y += yIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- ++x;\r
- }\r
- }\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1),\r
- p = pr-dy;\r
- while(dy > 0)\r
- {--dy;\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
- drw = !drw;\r
- y += yIncr;\r
- if(p > 0)\r
- {\r
- ++x;\r
- p += pru;\r
- }\r
- else p += pr;\r
- }\r
- }\r
- if(drw) this._mkDiv(x, y, 1, 1);\r
-}\r
-\r
-function _mkOv(left, top, width, height)\r
-{\r
- var a = (++width)>>1, b = (++height)>>1,\r
- wod = width&1, hod = height&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- ox = 0, oy = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- w, h;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- w = x-ox;\r
- h = oy-y;\r
- if((w&2) && (h&2))\r
- {\r
- this._mkOvQds(cx, cy, x-2, y+2, 1, 1, wod, hod);\r
- this._mkOvQds(cx, cy, x-1, y+1, 1, 1, wod, hod);\r
- }\r
- else this._mkOvQds(cx, cy, x-1, oy, w, h, wod, hod);\r
- ox = x;\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- w = a-ox+1;\r
- h = (oy<<1)+hod;\r
- y = cy-oy;\r
- this._mkDiv(cx-a, y, w, h);\r
- this._mkDiv(cx+ox+wod-1, y, w, h);\r
-}\r
-\r
-function _mkOv2D(left, top, width, height)\r
-{\r
- var s = this.stroke;\r
- width += s+1;\r
- height += s+1;\r
- var a = width>>1, b = height>>1,\r
- wod = width&1, hod = height&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1);\r
-\r
- if(s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))\r
- {\r
- var ox = 0, oy = b,\r
- w, h,\r
- pxw;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- w = x-ox;\r
- h = oy-y;\r
-\r
- if(w-1)\r
- {\r
- pxw = w+1+(s&1);\r
- h = s;\r
- }\r
- else if(h-1)\r
- {\r
- pxw = s;\r
- h += 1+(s&1);\r
- }\r
- else pxw = h = s;\r
- this._mkOvQds(cx, cy, x-1, oy, pxw, h, wod, hod);\r
- ox = x;\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);\r
- this._mkDiv(cx+a+wod-s, cy-oy, s, (oy<<1)+hod);\r
- }\r
-\r
- else\r
- {\r
- var _a = (width-(s<<1))>>1,\r
- _b = (height-(s<<1))>>1,\r
- _x = 0, _y = _b,\r
- _aa2 = (_a*_a)<<1, _aa4 = _aa2<<1, _bb2 = (_b*_b)<<1, _bb4 = _bb2<<1,\r
- _st = (_aa2>>1)*(1-(_b<<1)) + _bb2,\r
- _tt = (_bb2>>1) - _aa2*((_b<<1)-1),\r
-\r
- pxl = new Array(),\r
- pxt = new Array(),\r
- _pxb = new Array();\r
- pxl[0] = 0;\r
- pxt[0] = b;\r
- _pxb[0] = _b-1;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- pxl[pxl.length] = x;\r
- pxt[pxt.length] = y;\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- pxl[pxl.length] = x;\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- pxt[pxt.length] = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
-\r
- if(_y > 0)\r
- {\r
- if(_st < 0)\r
- {\r
- _st += _bb2*((_x<<1)+3);\r
- _tt += _bb4*(++_x);\r
- _pxb[_pxb.length] = _y-1;\r
- }\r
- else if(_tt < 0)\r
- {\r
- _st += _bb2*((_x<<1)+3) - _aa4*(_y-1);\r
- _tt += _bb4*(++_x) - _aa2*(((_y--)<<1)-3);\r
- _pxb[_pxb.length] = _y-1;\r
- }\r
- else\r
- {\r
- _tt -= _aa2*((_y<<1)-3);\r
- _st -= _aa4*(--_y);\r
- _pxb[_pxb.length-1]--;\r
- }\r
- }\r
- }\r
-\r
- var ox = -wod, oy = b,\r
- _oy = _pxb[0],\r
- l = pxl.length,\r
- w, h;\r
- for(var i = 0; i < l; i++)\r
- {\r
- if(typeof _pxb[i] != "undefined")\r
- {\r
- if(_pxb[i] < _oy || pxt[i] < oy)\r
- {\r
- x = pxl[i];\r
- this._mkOvQds(cx, cy, x, oy, x-ox, oy-_oy, wod, hod);\r
- ox = x;\r
- oy = pxt[i];\r
- _oy = _pxb[i];\r
- }\r
- }\r
- else\r
- {\r
- x = pxl[i];\r
- this._mkDiv(cx-x, cy-oy, 1, (oy<<1)+hod);\r
- this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
- ox = x;\r
- oy = pxt[i];\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);\r
- this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
- }\r
-}\r
-\r
-function _mkOvDott(left, top, width, height)\r
-{\r
- var a = (++width)>>1, b = (++height)>>1,\r
- wod = width&1, hod = height&1, hodu = hod^1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- drw = true;\r
- while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- if(drw && y >= hodu) this._mkOvQds(cx, cy, x, y, 1, 1, wod, hod);\r
- drw = !drw;\r
- }\r
-}\r
-\r
-function _mkRect(x, y, w, h)\r
-{\r
- var s = this.stroke;\r
- this._mkDiv(x, y, w, s);\r
- this._mkDiv(x+w, y, s, h);\r
- this._mkDiv(x, y+h, w+s, s);\r
- this._mkDiv(x, y+s, s, h-s);\r
-}\r
-\r
-function _mkRectDott(x, y, w, h)\r
-{\r
- this.drawLine(x, y, x+w, y);\r
- this.drawLine(x+w, y, x+w, y+h);\r
- this.drawLine(x, y+h, x+w, y+h);\r
- this.drawLine(x, y, x, y+h);\r
-}\r
-\r
-function jsgFont()\r
-{\r
- this.PLAIN = 'font-weight:normal;';\r
- this.BOLD = 'font-weight:bold;';\r
- this.ITALIC = 'font-style:italic;';\r
- this.ITALIC_BOLD = this.ITALIC + this.BOLD;\r
- this.BOLD_ITALIC = this.ITALIC_BOLD;\r
-}\r
-var Font = new jsgFont();\r
-\r
-function jsgStroke()\r
-{\r
- this.DOTTED = -1;\r
-}\r
-var Stroke = new jsgStroke();\r
-\r
-function jsGraphics(cnv, wnd)\r
-{\r
- this.setColor = function(x)\r
- {\r
- this.color = x.toLowerCase();\r
- };\r
-\r
- this.setStroke = function(x)\r
- {\r
- this.stroke = x;\r
- if(!(x+1))\r
- {\r
- this.drawLine = _mkLinDott;\r
- this._mkOv = _mkOvDott;\r
- this.drawRect = _mkRectDott;\r
- }\r
- else if(x-1 > 0)\r
- {\r
- this.drawLine = _mkLin2D;\r
- this._mkOv = _mkOv2D;\r
- this.drawRect = _mkRect;\r
- }\r
- else\r
- {\r
- this.drawLine = _mkLin;\r
- this._mkOv = _mkOv;\r
- this.drawRect = _mkRect;\r
- }\r
- };\r
-\r
- this.setPrintable = function(arg)\r
- {\r
- this.printable = arg;\r
- if(jg_fast)\r
- {\r
- this._mkDiv = _mkDivIe;\r
- this._htmRpc = arg? _htmPrtRpc : _htmRpc;\r
- }\r
- else this._mkDiv = arg? _mkDivPrt : _mkDiv;\r
- };\r
-\r
- this.setFont = function(fam, sz, sty)\r
- {\r
- this.ftFam = fam;\r
- this.ftSz = sz;\r
- this.ftSty = sty || Font.PLAIN;\r
- };\r
-\r
- this.drawPolyline = this.drawPolyLine = function(x, y)\r
- {\r
- for (var i=x.length - 1; i;)\r
- {--i;\r
- this.drawLine(x[i], y[i], x[i+1], y[i+1]);\r
- }\r
- };\r
-\r
- this.fillRect = function(x, y, w, h)\r
- {\r
- this._mkDiv(x, y, w, h);\r
- };\r
-\r
- this.drawPolygon = function(x, y)\r
- {\r
- this.drawPolyline(x, y);\r
- this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);\r
- };\r
-\r
- this.drawEllipse = this.drawOval = function(x, y, w, h)\r
- {\r
- this._mkOv(x, y, w, h);\r
- };\r
-\r
- this.fillEllipse = this.fillOval = function(left, top, w, h)\r
- {\r
- var a = w>>1, b = h>>1,\r
- wod = w&1, hod = h&1,\r
- cx = left+a, cy = top+b,\r
- x = 0, y = b, oy = b,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- xl, dw, dh;\r
- if(w) while(y > 0)\r
- {\r
- if(st < 0)\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0)\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- xl = cx-x;\r
- dw = (x<<1)+wod;\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- dh = oy-y;\r
- this._mkDiv(xl, cy-oy, dw, dh);\r
- this._mkDiv(xl, cy+y+hod, dw, dh);\r
- oy = y;\r
- }\r
- else\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- }\r
- }\r
- this._mkDiv(cx-a, cy-oy, w, (oy<<1)+hod);\r
- };\r
-\r
- this.fillArc = function(iL, iT, iW, iH, fAngA, fAngZ)\r
- {\r
- var a = iW>>1, b = iH>>1,\r
- iOdds = (iW&1) | ((iH&1) << 16),\r
- cx = iL+a, cy = iT+b,\r
- x = 0, y = b, ox = x, oy = y,\r
- aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,\r
- st = (aa2>>1)*(1-(b<<1)) + bb2,\r
- tt = (bb2>>1) - aa2*((b<<1)-1),\r
- // Vars for radial boundary lines\r
- xEndA, yEndA, xEndZ, yEndZ,\r
- iSects = (1 << (Math.floor((fAngA %= 360.0)/180.0) << 3))\r
- | (2 << (Math.floor((fAngZ %= 360.0)/180.0) << 3))\r
- | ((fAngA >= fAngZ) << 16),\r
- aBndA = new Array(b+1), aBndZ = new Array(b+1);\r
- \r
- // Set up radial boundary lines\r
- fAngA *= Math.PI/180.0;\r
- fAngZ *= Math.PI/180.0;\r
- xEndA = cx+Math.round(a*Math.cos(fAngA));\r
- yEndA = cy+Math.round(-b*Math.sin(fAngA));\r
- _mkLinVirt(aBndA, cx, cy, xEndA, yEndA);\r
- xEndZ = cx+Math.round(a*Math.cos(fAngZ));\r
- yEndZ = cy+Math.round(-b*Math.sin(fAngZ));\r
- _mkLinVirt(aBndZ, cx, cy, xEndZ, yEndZ);\r
-\r
- while(y > 0)\r
- {\r
- if(st < 0) // Advance x\r
- {\r
- st += bb2*((x<<1)+3);\r
- tt += bb4*(++x);\r
- }\r
- else if(tt < 0) // Advance x and y\r
- {\r
- st += bb2*((x<<1)+3) - aa4*(y-1);\r
- ox = x;\r
- tt += bb4*(++x) - aa2*(((y--)<<1)-3);\r
- this._mkArcDiv(ox, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- oy = y;\r
- }\r
- else // Advance y\r
- {\r
- tt -= aa2*((y<<1)-3);\r
- st -= aa4*(--y);\r
- if(y && (aBndA[y] != aBndA[y-1] || aBndZ[y] != aBndZ[y-1]))\r
- {\r
- this._mkArcDiv(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- ox = x;\r
- oy = y;\r
- }\r
- }\r
- }\r
- this._mkArcDiv(x, 0, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);\r
- if(iOdds >> 16) // Odd height\r
- {\r
- if(iSects >> 16) // Start-angle > end-angle\r
- {\r
- var xl = (yEndA <= cy || yEndZ > cy)? (cx - x) : cx;\r
- this._mkDiv(xl, cy, x + cx - xl + (iOdds & 0xffff), 1);\r
- }\r
- else if((iSects & 0x01) && yEndZ > cy)\r
- this._mkDiv(cx - x, cy, x, 1);\r
- }\r
- };\r
-\r
-/* fillPolygon method, implemented by Matthieu Haller.\r
-This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.\r
-C source of GD 1.8.4 found at http://www.boutell.com/gd/\r
-\r
-THANKS to Kirsten Schulz for the polygon fixes!\r
-\r
-The intersection finding technique of this code could be improved\r
-by remembering the previous intertersection, and by using the slope.\r
-That could help to adjust intersections to produce a nice\r
-interior_extrema. */\r
- this.fillPolygon = function(array_x, array_y)\r
- {\r
- var i;\r
- var y;\r
- var miny, maxy;\r
- var x1, y1;\r
- var x2, y2;\r
- var ind1, ind2;\r
- var ints;\r
-\r
- var n = array_x.length;\r
- if(!n) return;\r
-\r
- miny = array_y[0];\r
- maxy = array_y[0];\r
- for(i = 1; i < n; i++)\r
- {\r
- if(array_y[i] < miny)\r
- miny = array_y[i];\r
-\r
- if(array_y[i] > maxy)\r
- maxy = array_y[i];\r
- }\r
- for(y = miny; y <= maxy; y++)\r
- {\r
- var polyInts = new Array();\r
- ints = 0;\r
- for(i = 0; i < n; i++)\r
- {\r
- if(!i)\r
- {\r
- ind1 = n-1;\r
- ind2 = 0;\r
- }\r
- else\r
- {\r
- ind1 = i-1;\r
- ind2 = i;\r
- }\r
- y1 = array_y[ind1];\r
- y2 = array_y[ind2];\r
- if(y1 < y2)\r
- {\r
- x1 = array_x[ind1];\r
- x2 = array_x[ind2];\r
- }\r
- else if(y1 > y2)\r
- {\r
- y2 = array_y[ind1];\r
- y1 = array_y[ind2];\r
- x2 = array_x[ind1];\r
- x1 = array_x[ind2];\r
- }\r
- else continue;\r
-\r
- // Modified 11. 2. 2004 Walter Zorn\r
- if((y >= y1) && (y < y2))\r
- polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
-\r
- else if((y == maxy) && (y > y1) && (y <= y2))\r
- polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
- }\r
- polyInts.sort(_CompInt);\r
- for(i = 0; i < ints; i+=2)\r
- this._mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);\r
- }\r
- };\r
-\r
- this.drawString = function(txt, x, y)\r
- {\r
- this.htm += '<div style="position:absolute;white-space:nowrap;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'font-family:' + this.ftFam + ';'+\r
- 'font-size:' + this.ftSz + ';'+\r
- 'color:' + this.color + ';' + this.ftSty + '">'+\r
- txt +\r
- '<\/div>';\r
- };\r
-\r
-/* drawStringRect() added by Rick Blommers.\r
-Allows to specify the size of the text rectangle and to align the\r
-text both horizontally (e.g. right) and vertically within that rectangle */\r
- this.drawStringRect = function(txt, x, y, width, halign)\r
- {\r
- this.htm += '<div style="position:absolute;overflow:hidden;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- 'width:'+width +'px;'+\r
- 'text-align:'+halign+';'+\r
- 'font-family:' + this.ftFam + ';'+\r
- 'font-size:' + this.ftSz + ';'+\r
- 'color:' + this.color + ';' + this.ftSty + '">'+\r
- txt +\r
- '<\/div>';\r
- };\r
-\r
- this.drawImage = function(imgSrc, x, y, w, h, a)\r
- {\r
- this.htm += '<div style="position:absolute;'+\r
- 'left:' + x + 'px;'+\r
- 'top:' + y + 'px;'+\r
- // w (width) and h (height) arguments are now optional.\r
- // Added by Mahmut Keygubatli, 14.1.2008\r
- (w? ('width:' + w + 'px;') : '') +\r
- (h? ('height:' + h + 'px;'):'')+'">'+\r
- '<img src="' + imgSrc +'"'+ (w ? (' width="' + w + '"'):'')+ (h ? (' height="' + h + '"'):'') + (a? (' '+a) : '') + '>'+\r
- '<\/div>';\r
- };\r
-\r
- this.clear = function()\r
- {\r
- this.htm = "";\r
- if(this.cnv) this.cnv.innerHTML = "";\r
- };\r
-\r
- this._mkOvQds = function(cx, cy, x, y, w, h, wod, hod)\r
- {\r
- var xl = cx - x, xr = cx + x + wod - w, yt = cy - y, yb = cy + y + hod - h;\r
- if(xr > xl+w)\r
- {\r
- this._mkDiv(xr, yt, w, h);\r
- this._mkDiv(xr, yb, w, h);\r
- }\r
- else\r
- w = xr - xl + w;\r
- this._mkDiv(xl, yt, w, h);\r
- this._mkDiv(xl, yb, w, h);\r
- };\r
- \r
- this._mkArcDiv = function(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects)\r
- {\r
- var xrDef = cx + x + (iOdds & 0xffff), y2, h = oy - y, xl, xr, w;\r
-\r
- if(!h) h = 1;\r
- x = cx - x;\r
-\r
- if(iSects & 0xff0000) // Start-angle > end-angle\r
- {\r
- y2 = cy - y - h;\r
- if(iSects & 0x00ff)\r
- {\r
- if(iSects & 0x02)\r
- {\r
- xl = Math.max(x, aBndZ[y]);\r
- w = xrDef - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0x01)\r
- {\r
- xr = Math.min(xrDef, aBndA[y]);\r
- w = xr - x;\r
- if(w > 0) this._mkDiv(x, y2, w, h);\r
- }\r
- }\r
- else\r
- this._mkDiv(x, y2, xrDef - x, h);\r
- y2 = cy + y + (iOdds >> 16);\r
- if(iSects & 0xff00)\r
- {\r
- if(iSects & 0x0100)\r
- {\r
- xl = Math.max(x, aBndA[y]);\r
- w = xrDef - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0x0200)\r
- {\r
- xr = Math.min(xrDef, aBndZ[y]);\r
- w = xr - x;\r
- if(w > 0) this._mkDiv(x, y2, w, h);\r
- }\r
- }\r
- else\r
- this._mkDiv(x, y2, xrDef - x, h);\r
- }\r
- else\r
- {\r
- if(iSects & 0x00ff)\r
- {\r
- if(iSects & 0x02)\r
- xl = Math.max(x, aBndZ[y]);\r
- else\r
- xl = x;\r
- if(iSects & 0x01)\r
- xr = Math.min(xrDef, aBndA[y]);\r
- else\r
- xr = xrDef;\r
- y2 = cy - y - h;\r
- w = xr - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- if(iSects & 0xff00)\r
- {\r
- if(iSects & 0x0100)\r
- xl = Math.max(x, aBndA[y]);\r
- else\r
- xl = x;\r
- if(iSects & 0x0200)\r
- xr = Math.min(xrDef, aBndZ[y]);\r
- else\r
- xr = xrDef;\r
- y2 = cy + y + (iOdds >> 16);\r
- w = xr - xl;\r
- if(w > 0) this._mkDiv(xl, y2, w, h);\r
- }\r
- }\r
- };\r
-\r
- this.setStroke(1);\r
- this.setFont("verdana,geneva,helvetica,sans-serif", "12px", Font.PLAIN);\r
- this.color = "#000000";\r
- this.htm = "";\r
- this.wnd = wnd || window;\r
-\r
- if(!jg_ok) _chkDHTM();\r
- if(jg_ok)\r
- {\r
- if(cnv)\r
- {\r
- if(typeof(cnv) == "string")\r
- this.cont = document.all? (this.wnd.document.all[cnv] || null)\r
- : document.getElementById? (this.wnd.document.getElementById(cnv) || null)\r
- : null;\r
- else if(cnv == window.document)\r
- this.cont = document.getElementsByTagName("body")[0];\r
- // If cnv is a direct reference to a canvas DOM node\r
- // (option suggested by Andreas Luleich)\r
- else this.cont = cnv;\r
- // Create new canvas inside container DIV. Thus the drawing and clearing\r
- // methods won't interfere with the container's inner html.\r
- // Solution suggested by Vladimir.\r
- this.cnv = this.wnd.document.createElement("div");\r
- this.cnv.style.fontSize=0;\r
- this.cont.appendChild(this.cnv);\r
- this.paint = jg_dom? _pntCnvDom : _pntCnvIe;\r
- }\r
- else\r
- this.paint = _pntDoc;\r
- }\r
- else\r
- this.paint = _pntN;\r
-\r
- this.setPrintable(false);\r
-}\r
-\r
-function _mkLinVirt(aLin, x1, y1, x2, y2)\r
-{\r
- var dx = Math.abs(x2-x1), dy = Math.abs(y2-y1),\r
- x = x1, y = y1,\r
- xIncr = (x1 > x2)? -1 : 1,\r
- yIncr = (y1 > y2)? -1 : 1,\r
- p,\r
- i = 0;\r
- if(dx >= dy)\r
- {\r
- var pr = dy<<1,\r
- pru = pr - (dx<<1);\r
- p = pr-dx;\r
- while(dx > 0)\r
- {--dx;\r
- if(p > 0) // Increment y\r
- {\r
- aLin[i++] = x;\r
- y += yIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- x += xIncr;\r
- }\r
- }\r
- else\r
- {\r
- var pr = dx<<1,\r
- pru = pr - (dy<<1);\r
- p = pr-dy;\r
- while(dy > 0)\r
- {--dy;\r
- y += yIncr;\r
- aLin[i++] = x;\r
- if(p > 0) // Increment x\r
- {\r
- x += xIncr;\r
- p += pru;\r
- }\r
- else p += pr;\r
- }\r
- }\r
- for(var len = aLin.length, i = len-i; i;)\r
- aLin[len-(i--)] = x;\r
-};\r
-\r
-function _CompInt(x, y)\r
-{\r
- return(x - y);\r
-}\r
-\r
+++ /dev/null
-/**
- * TimeSide - Web Audio Components
- * Copyright (c) 2011 Parisson
- * Author: Riccardo Zaccarelli
- * License: GNU General Public License version 2.0
- */
-
-/**
- * Class for showing/editing a marker on details.
- */
-var MarkerMapDiv = TimesideArray.extend({
- init:function(currentUserName){
- this._super();
- this.div = this.$J("#markers_div_id");
- this.getCurrentUserName = function(){
- return currentUserName;
- }
- },
- //overridden
- add: function(marker, index, isNew){
-
- var div = this.createMarkerDiv(index, marker);
- if(index==this.length){
- this.div.append(div);
- }else{
- this.$J( this.div.children()[index] ).before(div);
- }
- //this.setIndex(this.length-1,d); //length has been increased when calling super
- this._super(div,index);
- if(isNew){
- this.setEditMode(index,true);
- this.setFocus(index,true);
- }
- if(index<this.length){
- //update indices. Note that this is NOT done at startup as index == this.length ALWAYS
- var t = this;
- var setIdx = t.setIndex;
- this.each(index, function(i, div){
- setIdx.apply(t,[div,i]);
- });
- }
- this.stretch(div.find('.markersdivTitle'));
- this.stretch(div.find('.markersdivDescription'));
- return div;
- },
- //overridden
- move: function(from, to, newOffset){
-
- //call super method
- var realIndex = this._super(from,to);
- //reflect the same changes in the document:
- var me = this.toArray();
- if(realIndex!=from){
- var div = me[realIndex]; //me has already been updated
- div.detach();
- var parent = this.div;
- if(to==this.length){
- parent.append(div);
- }else{
- this.$J( parent.children()[realIndex] ).before(div);
- }
- }
-
- var t = this;
- var setIdx = t.setIndex;
-
- this.each(Math.min(from,realIndex),Math.max(from,realIndex)+1, function(i, div){
- setIdx.apply(t,[div,i]);
- });
-
- this.setOffset(me[realIndex],newOffset);
-
- //TODO: create a function?
- this.setEditMode(realIndex,true);
- this.setFocus(realIndex,true);
- return realIndex;
- },
- //overridden
- remove : function(index){
- var div = this._super(index);
- div.remove();
- var me = this;
- this.each(index,function(i, div){
- me.setIndex.apply(me,[div,i]);
- });
- },
- //overridden
- makeTimeLabel: function(time){
- return this._super(time,['hh','mm','ss','C']);
- },
- //overridden
- clear: function(){
- var divs = this._super();
- for(var i=0; i< divs.length; i++){
- divs[i].empty().remove();
- }
- return divs;
- },
- //if value is missing, toggles edit mode
- //if editbutton is not present (marker not editable), this method does nothing
- setEditMode: function(index, value){
-
- var div = this.toArray()[index];
- var editButton = div.find('.markersdivEdit');
- if(!((editButton) && (editButton.length))){
- return;
- }
- var visible = editButton.is(':visible');
-
- if(arguments.length==1){ //toggle
- value = visible; //if edit visible, editmode = true, otherwise false
- }else if(value!=visible){
- //value is defined. if true and edit mode is NOT visible, we return cause we are already in edit mode
- //same if false (dont edit) and edit mode is visible (not edit mode)
- return;
- }
- var e_okButton = div.find('.markersdivSave');
- var e_descriptionText = div.find('.markersdivDescription');
- var e_titleText = div.find('.markersdivTitle');
- if(value){
- this.debug('setting editmode');
- div.css('backgroundColor','#E65911');
- e_descriptionText.removeAttr('readonly').removeClass('markersdivUneditable');
- e_titleText.removeAttr('readonly').removeClass('markersdivUneditable');
- e_okButton.add(e_okButton.parent()).show(); //hiding also the parent div saves space (padding bottom hidden)
- e_titleText.select(); //TODO: this does NOT set the focus on the div. Why?
- editButton.hide();
- //e_titleText.focus();
- }else{
- e_descriptionText.attr('readonly','readonly').addClass('markersdivUneditable');
- e_titleText.attr('readonly','readonly').addClass('markersdivUneditable');
- consolelog(e_okButton.parent());
- e_okButton.add(e_okButton.parent()).hide(); //hiding also the parent div saves space (padding bottom hidden)
- editButton.show();
- div.css('backgroundColor','');
- }
-
- //var e_addplaylistButton = div.find('.markersdivAddPlaylist');
-
- this.setFocus(index,value);
- this.stretch(e_titleText);
- },
-
-
-
- setFocus: function(index,value){
- // this.each(function(i,div){
- // if(i==index && value){
- // div.css('backgroundColor','#E65911'); //'#f5cf23'
- // }else{
- // div.css('backgroundColor','');
- // }
- // });
- },
-
-
- setIndex: function(div,index){
- //div.attr('id','_markerdiv'+index);
- div.find('.ts-marker').html(index+1);
- var me = this;
- var e_indexLabel = div.find('.ts-marker');
- var e_offsetLabel =div.find('.markersdivOffset');
- e_indexLabel.add(e_offsetLabel).unbind('click').click(function(){
- me.setFocus(index,true);
- me.fire('focus', {
- 'index': index
- });
- return false;
- });
- div.find('.markersdivEdit').unbind('click').click( function(){
- me.setEditMode(index);
- return false; //avoid scrolling of the page on anchor click
- });
- },
- /**
- * stretches jQueryElm the whole possible width. Note that text nodes are not considered!!!!
- */
- stretch: function(jQueryElm){
- var siblings = jQueryElm.siblings(":visible");
- siblings = siblings.add(jQueryElm);
- var spaceStretchable = jQueryElm.parent().width();
- var $J = this.$J;
- siblings.each(function(i,elm){
- spaceStretchable -= $J(elm).outerWidth(true);
- //consolelog("\t"+spaceStretchable+' elm:'+$J(elm).attr('class')+" left: "+$J(elm).position().left+" outerw:" +$J(elm).outerWidth(true)+" w: "+$J(elm).width());
- });
- //consolelog('w'+ jQueryElm.parent().width()+' elm.w: '+jQueryElm.width()+' spacestretchable: '+spaceStretchable);
- var w = jQueryElm.width() + spaceStretchable;
- jQueryElm.css('width', w+'px');
- },
-
- setOffset: function(div,offset){
- div.find('.markersdivOffset').html(this.makeTimeLabel(offset));
- },
- createMarkerDiv : function(index, marker){
- //TODO: why class 'ts-marker' does not work?
- //for the moment we set the style manually, remove
- //TODO: table width with CSS?
- var div = this.$J('<div/>').attr('tabindex','0').addClass("markerdiv").html('<div>'+
- '<a href=# class="ts-marker"></a>'+
- '<a href=# class="markersdivOffset" type="text"></a>'+
- '<input class="markersdivTitle" type="text"/>'+
- '<a class="markersdivAddPlaylist" title="add to playlist"></a>'+
- '<a class="markersdivEdit" title="edit">EDIT</a>'+
- '<a class="markersdivDelete" title="delete"></a>'+
- '</div>'+
- '<div zero_top_padding><textarea class="markersdivDescription"></textarea></div>'+
- '<div zero_top_padding><a class="markersdivSave">OK</a></div>'+
- '<div zero_top_padding><span style="font-size:75%;color:#999">'+gettrans('author')+': '+marker.author+'</span></div>'); //TODO: avoid text nodes
- div.find('a').attr('href','#');
- //todo: remove markerlabel from css!!!!!!!
- //new RulerMarker(div.find('.markerlbl'),div.find('.markercanvas'),'marker',false);
-
- var e_indexLabel = div.find('.ts-marker');
- //var e_offsetLabel =div.find('.markersdivOffset');
- var e_okButton = div.find('.markersdivSave');
- var e_editButton = div.find('.markersdivEdit');
- var e_deleteButton = div.find('.markersdivDelete');
- var e_addplaylistButton = div.find('.markersdivAddPlaylist');
- var e_descriptionText = div.find('.markersdivDescription');
- var e_titleText = div.find('.markersdivTitle');
-
- //set defualt element values regardeless of the marker state
- e_indexLabel.attr('title',marker.toString());
- this.setIndex(div, index);
-
- //e_offsetLabel.html(this.makeTimeLabel(marker.offset));
- this.setOffset(div,marker.offset);
- //set visibility and attach events according to the marker state:
- //first, is editing or not
- //var isEditing = marker.isEditable && marker.isModified;
- // (!marker.isSavedOnServer || !(this.e_editButton.is(':visible')));
-
- //if(!isEditing){
- e_descriptionText.val(marker.desc ? marker.desc : "");
- e_titleText.val(marker.title ? marker.title : "");
- //}
-
- e_okButton.add(e_okButton.parent()).hide(); //hiding also the parent div saves space (padding bottom hidden)
- e_editButton.show();
- e_deleteButton.show();
- e_addplaylistButton.show();
- e_descriptionText.attr('readonly','readonly').addClass('markersdivUneditable').unbind('focus');
- e_titleText.attr('readonly','readonly').addClass('markersdivUneditable').unbind('focus');
-
- //add to playlist always visible, provided that it is saved on server AND current user is logged
- //(getCurrentUserName evaluates to true)
- // if(!marker.isSavedOnServer || !this.getCurrentUserName()){
- // e_addplaylistButton.hide();
- // }else{
- e_addplaylistButton.unbind('click').bind('click',function(evtObj_){
- if(!marker.isSavedOnServer){
- return false;
- }
- //make a request to the server to get the pk (id)
- //note that marker.id (client side) is marker.public_id (server side)
- json([marker.id],"telemeta.get_marker_id", function(data){
- consolelog('received');
- consolelog(data);
- var id = data.result;
- playlistUtils.showAddResourceToPlaylist(e_addplaylistButton,'marker',""+id,gettrans('marker added to the selected playlist'));
- });
- return false;
- });
-
- if(!this.getCurrentUserName()){
- e_addplaylistButton.hide();
- }
-
-
- if(!marker.isEditable){ //marker is editable means that author == getCurrentUserName(). addToPlaylist
- //visibility is skipped because it depends on other circumstances (see above)
- e_editButton.hide();
- e_deleteButton.hide();
- //we unbind events to be sure
- //e_addplaylistButton.unbind('click').hide();
- e_okButton.unbind('click')
- e_deleteButton.unbind('click').hide();
- e_editButton.remove(); //so that if edit button is not present, we do not edit (safety reasons) see this.setEditMode
- return div;
- }
-
-
-
- var me = this;
-
- e_deleteButton.unbind('click').click( function(){
- if(!(marker.isSavedOnServer) || confirm(gettrans('delete the marker permanently?'))){
- me.fire('remove',{
- 'marker':marker
- });
- }
- return false; //avoid scrolling of the page on anchor click
- })
-
-
-
- //action for ok button
- e_okButton.unbind('click').click( function(){
- //if(marker.desc !== descriptionText.val()){ //strict equality needed. See note below
- marker.desc = e_descriptionText.val();
- marker.title = e_titleText.val();
- me.fire('save',{
- 'marker':marker
- });
- return false; //avoid scrolling of the page on anchor click
- });
-
-
- e_titleText.keydown(function(event){
- if(e_okButton.is(':visible')){
- if (event.keyCode == '13') {
- event.preventDefault();
- e_okButton.trigger('click');
- }
- }
- });
-
- return div;
- }
-
-});
\ No newline at end of file
+++ /dev/null
-/**
- * TimeSide - Web Audio Components
- * Copyright (c) 2011 Parisson
- * Author: Riccardo Zaccarelli
- * License: GNU General Public License version 2.0
- */
-
-/**
- * class fior managing markers in the player. Markers on the ruler (ruler.js) or on the divs (divmarker.js)
- * are not included here, they are separate classes. See player.js (loadMarkers method) where the bindings
- * between this class, ruler and divmarker are set
- */
-var MarkerMap = TimesideArray.extend({
-
- init: function(itemId, currentUserName) {
- this._super();
- var ui = uniqid; //defined in application.js (global vars and functions)
- this.uniqid = function(){
- return ui();
- };
- this.getItemId = function(){
- return itemId;
- }
- this.getCurrentUserName = function(){
- return currentUserName;
- }
-
- var me = this;
- var confirmExit = function(){
- var markerUnsaved=0;
- me.each(function(i,marker){
- if(!marker.isSavedOnServer){
- markerUnsaved++;
- }
- });
- consolelog(markerUnsaved);
- if(markerUnsaved>0){
- return gettrans('there is at least one unsaved marker') +' ('+ markerUnsaved+ '). '+
- gettrans('If you exit the page you will loose your changes');
- }
-
- };
- window.onbeforeunload = confirmExit;
- },
-
- //overridden
- add: function(obj) {
- //var markers = this.toArray();
- var marker = this.createMarker(obj);
- var idx = this.insertionIndex(marker);
- if(idx>=0){ //it exists? there is a problem....
- this.debug('adding a marker already existing!!'); //should not happen. however...
- return -1;
- }
-
- idx = -idx-1;
- //we do not call the super add cause we want to insert at a specified index
- this._super(marker,idx);
- //notifies controller.onMarkerMapAdd
-
- this.fire('add', {
- marker: marker,
- index: idx,
- isNew: (typeof obj == 'number' || typeof obj == 'string')
- });
- //var temp = new MarkerDiv();
- // this.debug(this.createMarkerDiv());
-
-
- return idx;
- },
- //TODO: remove from here
-
-
- //argument is either an object loaded from server or a number specifying the marker offset
- createMarker: function(argument){
- var marker = null;
- var pFloat = parseFloat;
- if(typeof argument == 'string'){ //to be sure, it might be that we pass an offset in string format
- argument = pFloat(argument);
- }
- var currentUserName = this.getCurrentUserName();
- if(typeof argument == 'object'){
- var editable = currentUserName === argument.author;
- marker = {
- id: argument.public_id,
- offset: pFloat(argument.time), //IMPORTANT: IT IS A STRING!!!!!!
- desc: argument.description,
- title: argument.title,
- author: argument.author,
- isEditable: editable,
- isSavedOnServer: true
- };
- }else if(typeof argument == 'number'){
- marker = {
- id: this.uniqid(),
- offset: pFloat(argument),
- desc: "",
- title: "",
- author: currentUserName,
- isEditable: true,
- isSavedOnServer: false
- };
- }
- marker.toString = function(){
- var props = [];
- for(var prop in this){
- if(!(prop == 'toString')){
- props.push(prop+': '+this[prop]);
- }
- }
- return props.sort().join("\n");
- }
- return marker;
-
- },
-
- //overridden
- //markerOrIndex can be an number (marker index) or a marker (the index will be aearched)
- remove: function(identifier) {
- var idx = -1;
- if(typeof index == 'number'){
- idx = identifier;
- }else{
- idx = this.insertionIndex(identifier);
- }
- if(idx<0 || idx>=this.length){
- this.each(function(i,m){
- consolelog(m);
- });
- consolelog(identifier);
- //TODO: handle error
- this.debug('remove: marker not found');
- return;
- }
-
- //build the function to be called if the marker is deleted
- //if the marker is NOT saved on server, call the function immediately
- var marker = this.toArray()[idx];
- var me = this;
- var superRemove = me._super;
- var functionOnSuccess = function(){
- superRemove.apply(me,[idx]);
- me.fire('remove',{
- 'index':idx
- })
- }
-
- if(marker.isSavedOnServer){
- //json(param,method,onSuccessFcn,onErrorFcn){
- json([marker.id], "telemeta.del_marker",functionOnSuccess);
- }else{
- functionOnSuccess();
- }
- },
-
- save: function(marker){
- var idx = this.insertionIndex(marker);
- if(idx<0 || idx>=this.length){
- //TODO: habdle error
- this.debug('marker not found');
- }
-
- //TODO: item public id defined elsewhere up, not here inside
- var itemid = this.getItemId();
- var isSavedOnServer = marker.isSavedOnServer;
- var method = isSavedOnServer ? "telemeta.update_marker" : "telemeta.add_marker";
- var param = {
- 'item_id':itemid,
- 'public_id': marker.id,
- 'time':marker.offset,
- 'author': marker.author,
- 'title':marker.title,
- 'description':marker.desc
- };
-
- //function on success:
- var me = this;
- var success = function(){
- if(!isSavedOnServer){
- marker.isSavedOnServer = true;
- marker.isModified = false;
- }
- me.fire('save',{
- 'index':idx
- });
- };
- //json(param,method,onSuccessFcn,onErrorFcn){
- json([param], method, success);
-
- },
-
- //overridden method
- move: function(markerIndex, newOffset){
- var newIndex = this.insertionIndex(newOffset);
- //select the case:
- if(newIndex<0){
- //we didn't move the marker on another marker (newOffset does not correspond to any marker)
- //just return the real insertionIndex
- newIndex = -newIndex-1;
- }
- // var markers = this.getMarkers();
- // //TODO: remove move from array prototype!!!!
- var realIndex = this._super(markerIndex,newIndex);
- // //var realIndex = markers.move(markerIndex,newIndex);
- // this.debug('fromindex '+markerIndex+' to: '+newIndex+' results in '+realIndex);
- var markers = this.toArray();
- var marker = markers[realIndex];
- marker.offset = newOffset;
- marker.isModified = true;
- this.fire('move', {
- fromIndex: markerIndex,
- toIndex: newIndex,
- newOffset: newOffset
- //,newIndex: realIndex
- });
- },
-
-
- //returns the insertion index of object in this sorted array by means of a binary search algorithm.
- // A) If object is a marker and:
- // a1) Is found (ie, there is a marker in this map
- // with same offset and same id), returns the index of the marker found, in the range [0, this.length-1]. Otherwise, if
- // a2) Is not found, then returns -(insertionIndex-1), where insertionIndex is the
- // index at which object would be inserted preserving the array order. Note that this assures that a
- // number lower than zero means that object is not present in the array, and viceversa
- // B) If object is a number or a string number (eg, "12.567"), then a marker with offset = object is built and compared
- // against the markers in the map. Note however that in this case that equality between marker's offset is sufficient,
- // as object is not provided with an id. THEREFORE, IF THE MAP CONTAINS SEVERAL MARKERS AT INDICES i, i+1, ... i+n
- // WITH SAME OFFSET == object, THERE IS NO WAY TO DETERMINE WHICH INDEX IN [i, i+1, ... i+n] WILL BE RETURNED.
- // See player.forward and player.rewind for an example of the B) case.
- //LAST NOTE: BE SURE object is either a number (float) or object.offset is a number (float).
- //In case it is not known, If it is a string number such as
- //"4.562" the comparison falis (eg, "2.567" > "10.544") but obviously, no error is thrown in javascript
- //
- insertionIndex: function(object){
- //default comparator function:
- //returns 1 as the first argument is greater than the second
- //returns -1 as the first argument is lower than the second
- //returns 0 if the arguments are equal
- var comparatorFunction = function(markerInMap,newMarker){
- var a = markerInMap.offset;
- var b = newMarker.offset;
- if(a<b){
- return -1;
- }else if(a >b){
- return 1;
- }else{
- var a1 = markerInMap.id;
- var b1 = newMarker.id;
- if(a1<b1){
- return -1;
- }else if(a1>b1){
- return 1;
- }
- }
- return 0;
- //var ret = a < b ? -1 : (a>b ? 1 : (markerInMap.id === newMarker.id ? 0 : -1));
- //return ret;
- };
- if(!(typeof object == 'object')){
- var offset;
- if(typeof object == 'number'){
- offset = object;
- }else{ //to be sure...
- offset = parseFloat(object);
- }
- object = {
- 'offset':offset
- };
- //key will never be found, so return either 1 or -1:
- comparatorFunction = function(markerInMap,newMarker){
- var a = markerInMap.offset;
- var b = newMarker.offset;
- return a < b ? -1 : (a>b ? 1 : 0);
- };
- }
- var pInt = parseInt; //reference to parseInt outside the loop below
- //(to increase algorithm performances)
-
- var data = this.toArray();
- var low = 0;
- var high = data.length-1;
-
- while (low <= high) {
- //int mid = (low + high) >>> 1;
- var mid = pInt((low + high)/2);
- var midVal = data[mid];
- var cmp = comparatorFunction(midVal,object);
- if (cmp < 0){
- //the midvalue is lower than the searched index element
- low = mid + 1;
- }else if (cmp > 0){
- //the midvalue is greater than the searched index element
- high = mid - 1;
- }else{
- return mid; // key found
- }
- }
- return -(low + 1); // key not found
- }
-}
-);
\ No newline at end of file
+++ /dev/null
-var Player = TimesideClass.extend({
-
- //sound duration is in milliseconds because the soundmanager has that unit,
- //player (according to timeside syntax) has durations in seconds
- init: function(container, sound, soundDurationInMsec, itemId, visualizers, currentUserName) {
- this._super();
- var player = this;
-
- //container is the div #player
-
- if (!container){
- this.debug('ERROR: container is null in initializing the player')
- }
- this.getItemId = function(){
- return itemId;
- }
-
- this.getContainer = function(){
- return container;
- }
- this.getSound = function(){
- return sound;
- }
-
- this.getVisualizers = function(){
- return visualizers;
- }
-
-
- //rpivate functions for converting
- //soundmanager has milliseconds, we use here seconds
- var pInt = Math.round; //instantiate once for faster lookup
- var pFloat = parseFloat; //instantiate once for faster lookup
- function toMsec(seconds){
- return pInt(seconds*1000);
- }
- function toSec(msec){
- return pFloat(msec)/1000;
- }
-
-
- var sd = toSec(soundDurationInMsec);
- this.getSoundDuration = function(){
- return sd;
- }
-
- this.isPlaying = function(){
- /*Numeric value indicating the current playing state of the sound.
- * 0 = stopped/uninitialised
- * 1 = playing or buffering sound (play has been called, waiting for data etc.)
- *Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.*/
- return sound && sound.playState==1;
- };
-
- var currentMarkerIndex=0;
- this.getCurrentMarkerIndex = function(){
- return currentMarkerIndex;
- };
-
- //setting the position===============================================
- //if sound is not loaded, position is buggy. Moreover, we have to handle the conversions between units:
- //seconds (here) and milliseconds (swmanager sound). So we store a private variable
- //private variable and function
- var soundPos = sound.position ? toSec(sound.position) : 0.0;
- //private method: updates just the internal variable (called in whilePlaying below)
- function setPos(value){
- soundPos = value;
- var map = player.getMarkerMap();
- if(map){
- currentMarkerIndex = map.insertionIndex(value);
- if(currentMarkerIndex<0){ //see markermap.insertionindex
- currentMarkerIndex = -currentMarkerIndex-1;
- }
- }
- }
- //public methods: calls setPos above AND updates sounbd position
- this.setSoundPosition = function(newPositionInSeconds){
- //for some odd reason, if we set sound.setPosition here soundPos
- //is rounded till the 3rd decimal integer AND WILL BE ROUNDED THIS WAY IN THE FUTURE
- //don't know why, however we set the sound position before playing (see below)
- //however, now it works. Even odder....
- setPos(newPositionInSeconds);
- if(sound){
- var s = toMsec(this.getSoundPosition());
- sound.setPosition(s);
- }
- }
- //public methods: returns the sound position
- this.getSoundPosition = function(){
- return soundPos;
- };
-
-
- // if(sound.readyState != 3){
- // /*sound.readyState
- // * Numeric value indicating a sound's current load status
- // * 0 = uninitialised
- // * 1 = loading
- // * 2 = failed/error
- // * 3 = loaded/success
- // */
- // sound.options.whileloading=function(){
- //
- // }
- // };
-
- //implement play here: while playing we do not have to update the sound position, so
- //we call the private variable soundPos
- this.play = function(){
- if(!player || player.isPlaying()){ //TODO: remove?, multishot is set to false
- return false;
- }
- var sound = player.getSound();
- if(!sound){
- return false;
- }
-
- var ruler = player.getRuler();
-
- var playOptions = {
- whileplaying: function(){
- var sPos = toSec(this.position); //this will refer to the sound object (see below)
- setPos(sPos);
- if(ruler && !ruler.isPointerMovingFromMouse()){
- ruler.movePointer(sPos);
- }
-
- player.showMarkerPopup(currentMarkerIndex);
- },
- onfinish: function() {
- setPos(0); //reset position, not cursor, so that clicking play restarts from zero
- }
- };
- //internal play function. Set all properties and play:
- var play_ = function(sound, positionInSec){
- //consolelog('position is '+positionInSec+' sec');
- sound.setPosition(toMsec(positionInSec)); //TODO: remove???
- //consolelog('sound position is '+sound.position+' msec');
- sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play
- playOptions.position = toMsec(positionInSec); //apparently THIS IS WORKING
- sound.play(playOptions);
- };
-
- play_(sound, player.getSoundPosition());
-
- return false;
- };
- //now implement also pause here: note that pause has some odd behaviour.
- //Try this sequence: play stop moveforward moveback play pause
- //When we press the last pause the sound restarts (??!!!!)
- this.pause = function(){
- var sound = this.getSound();
- //we don't check if it's playing, as the stop must really stop anyway
- //if(sound && this.isPlaying()){
- sound.stop();
- //}
- return false;
- };
-
- //initializing markermap and markerui
- var map = new MarkerMap(this.getItemId(), currentUserName);
- this.getMarkerMap = function(){
- return map;
- }
- var mapUI = new MarkerMapDiv(currentUserName);
- this.getMarkersUI = function(){
- return mapUI;
- }
- this.getCurrentUserName = function(){
- return currentUserName;
- }
- //TODO: define setUpInterface here????
-
- },
-
-
-
- _setupInterface: function() {
-
- var sound = this.getSound();
- consolelog('player _setupInterface sound.readyState:'+sound.readyState); //handle also cases 0 and 2????
-
- var $J = this.$J; //defined in the super constructor
- var me=this;
- //image source (see below) is given a src with a temporary 1x1 pixels transparent image
- //see http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ and
- //http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx
- //for details
- var html = ["<div class='ts-viewer'>",
- "<div class='ts-ruler'></div>",
- "<div class='ts-wave'>",
- "<div class='ts-image-canvas'></div>",
- "<div class='ts-image-container'>",
- "<img class='ts-image' src='/images/transparent.png' alt='' />",
- "</div>",
- "</div>",
- "</div>",
- "<div class='ts-control'>",
- "<div class='ts-layout'>",
- "<div class='ts-playback'>",
- "<a class='ts-play'></a>",
- "<a class='ts-pause'></a>",
- "<a class='ts-rewind'></a>",
- "<a class='ts-forward'></a>",
- "<a class='ts-set-marker'></a>",
- "<a class='ts-volume'></a>",
- "<img class='ts-wait'/>",
- "<select class='ts-visualizer'></select>",
- "</div>",
- "</div>",
- "</div>"];
-
- this.getContainer().html(html.join(''));
- var container = this.getContainer();
-
-
- var rewind = container.find('.ts-rewind');
- var forward = container.find('.ts-forward');
- var play = container.find('.ts-play');
- var pause = container.find('.ts-pause');
- var volume = container.find('.ts-volume');
-
-
- //hide the wait image and set the src
- var waitImg = container.find('.ts-wait');
- waitImg.attr('src','/images/wait_small.gif').attr('title','refreshing image').attr('alt','refreshing image').hide();
-
- //setting the select option for visualizers:
- var visualizers = this.getVisualizers();
- var select = container.find('.ts-visualizer');
- for(var name in visualizers){
- //$J('<option/>').val(visualizers[name]).html(name).appendTo(select);
- $J('<option/>').html(name).appendTo(select);
- }
- //assigning event on select:
- select.change(
- function (){
- me.refreshImage.apply(me);
- });
-
- var rewind_ = this.rewind;
- var forward_ = this.forward;
- rewind.attr('href', '#').click(function(e){
- rewind_.apply(me);
- return false;
- });
- forward.attr('href', '#').click(function(e){
- forward_.apply(me);
- return false;
- });
-
- //volume:
- function setVolume(event){
- var ticks = [18,26,33,40,47];
- var vol = event.layerX;
- for(var i=0; i<ticks.length; i++){
- if(vol<=ticks[i]){
- var volume = i*20;
- me.setSoundVolume(volume);
- me.debug('setting volume'+volume);
- return false;
- }
- }
- me.setSoundVolume(100);
- return false;
- }
- volume.attr('href', '#').click(function(event){
- return setVolume(event);
- });
-
- //assigning title to all anchors
- container.find('a').attr('href', '#')
- .each(function(i, a){
- a = $J(a);
- a.attr('title', a.attr('class').substring(3));
- });
-
- //creating the ruler
- var viewer = container.find('.ts-viewer');
- var ruler = new Ruler(viewer, this.getSoundDuration(), (this.getCurrentUserName() || false));
- this.getRuler = function(){
- return ruler;
- }
-
- this.resize(); //which calls also ruler.resize() (see below)
-
- //TODO: here? maybe in the constructor
- this.setSoundVolume(this.getSoundVolume());
-
-
- //bind events to play and pause.
- //pause:
- var pause_ = me.pause;
- pause.attr('href', '#').bind('click', function(){
- pause_.apply(me);
- return false;
- });
- //play:
- var play_ = me.play;
- play.attr('href', '#').bind('click', function(){
- play_.apply(me);
- return false;
- });
-
- //binds click for the pointer: TODO: change this way of getting the tsviweer!!!!
- var v = $J('#player').find('.ts-viewer');
- v.unbind('click').click(function(evt){
- var w = v.width();
- var x = evt.pageX - v.offset().left; //using absolute coordinates allows us to
- //avoid checking whether or not we are clicking on a vertical marker line, on a subdiv etcetera
- var sd = me.getSoundDuration();
- me.setSoundPosition(sd*x/w);
- ruler.movePointer(ruler.toSoundPosition(x));
- });
-
-
- //finally, load markers and bind events for markers (see method below):
- //NOTE: loadMarkers ASYNCHRONOUSLY CALLS THE SERVER, SO METHODS WRITTEN AFTER IT MIGHT BE EXECUTED BEFORE
- //loadMarkers has finished its job
- this.loadMarkers();
-
- //set the marker popup
- //functions to set the marker popup
- // var popupMarker = $J('<div/>').addClass('component').css({
- // 'dislay':'none',
- // 'position':'absolute',
- // 'zIndex':1000,
- // 'overflow':'auto',
- // 'display':'none' //TODO: remove this
- // //'backgroundColor':'#666'
- // });
- // $J('body').append(popupMarker);
- // var w = v.width();
- // var h = v.height();
- // var offs = v.offset(); //relative to the document
- // var width = parseInt(w/2);
- // var height = parseInt(h/2);
- // var margin = 5;
- // popupMarker.css({
- // 'left':(margin+offs.left+width)+'px',
- // 'top': parseInt(margin+offs.top)+'px',
- // 'width':width+'px',
- // 'height':height+'px'
- // });
- // popupMarker.html("<table style='width:100%'><tr><td>"+gettrans('title')+"</td><td class='title'></td></tr><tr><td>"+
- // gettrans('description')+"</td><td class='description'></td></tr></table>");
- // this.getMarkerPopup = function(){
- // return popupMarker;
- // }
- },
-
- showMarkerPopup: function(markerIndex){
- // var popup = this.getMarkerPopup();
- //
- // if(popup.attr('id') != 'markerpopup'+markerIndex){
- //
- // var marker = this.getMarkerMap().toArray()[markerIndex];
- // var pos = this.getSoundPosition();
- // var mPos = marker.offset;
- // var span = 0.3;
- //
- // if(pos>=mPos-span && pos<=mPos+span){
- // consolelog('songpos: '+pos+' nextmarkerpos:'+mPos);
- // popup.attr('id','markerpopup'+markerIndex);
- // popup.find('.title').html(marker.title);
- // popup.find('.description').html(marker.desc);
- // if(!popup.is(':visible')){
- // popup.show('fast');
- // }
- // }
- // }
- },
-
- /**
- * sets whether or not window resize resizes also this player. When true, a variable _dynamicResize =setInterval(...) is attached to
- * this class. When false, if _dynamicResize is in this class, clearInterval(_dynamicResize) is called and then the key is deleted
- */
- setDynamicResize: function(value){
- var key = '_dynamicResize';
- if(!value && key in this){
- clearInterval(this[key]);
- delete this[key];
- return;
- }
- var wdw = this.$J(window);
- var w = wdw.width();
- //var h = wdw.height();
- var me = this;
- this.dynamicResize = setInterval(function(){
- var newW = wdw.width();
- if(w!=newW){
- w = newW;
- //still wait a second: are we still adjusting the window? (call resize just once):
- setTimeout(function(){
- if(wdw.width()==newW){
- me.resize.apply(me);
- }
- },200);
- }
- },100);
- },
-
- resize: function() {
- this.debug("resizing");
- var height;
- var container = this.getContainer();
-
- var wave = container.find('.ts-wave');
- var image = container.find('.ts-image');
- height = wave.height();
- this.debug("wave height:" + height);
- if (!height) {
- //this.debug('ERROR: image height is zero in player.,resize!!!!')
- height = image.height();
- }
- //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css
- var elements = image
- .add(container.find('.ts-image-container'))
- .add(container.find('.ts-image-canvas'));
-
- elements.css('width', 'auto'); // for IE6
-
- if (!height){
- height = 200;
- }
- var style = {
- width: wave.width(),
- height: height
- }
- elements.css(style);
-
-
- //refreshing images:
- this.refreshImage(image);
- this.getRuler().resize();
-
-
- //adjusting select size:
- var select = container.find('.ts-visualizer');
- var imgWait = container.find('.ts-wait');
-
- //NOTE: some buttons might be hidden AFTER THIS METHOD HAS BEEN INVOKED
- //Therefore, setting the width of select or imgWait is skipped for the moment.
- select.css('fontSize','90%'); //this is to increase probability that the select width will fit the available space
-
- var control = container.find('.ts-control');
- var maxHeight = control.height();
- select.add(imgWait).css('maxHeight',(maxHeight-2)+'px'); //at least a margin left and top of 1 px (see below)
-
- var span = (maxHeight-select.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
- select.css({'margin':'0px', 'marginTop':span+'px','marginLeft':span+'px'});
- var span2 = (maxHeight - imgWait.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
- imgWait.css({'margin':'0px', 'marginTop':span2+'px','marginLeft':span+'px'})
-
-
- return this;
- },
-
- // getImageUrl: function(){
- // return this.$J('#visualizer_id').get(0).value;
- // },
- refreshImage: function(optionalImgJQueryElm){
- var image;
- var container = this.getContainer();
- if(optionalImgJQueryElm){
- image = optionalImgJQueryElm;
- }else{
- image = container.find('.ts-image');
- }
- var select = container.find('.ts-visualizer');
- var funcImg = function(player_image_url, width, height){
- var _src_ = null;
- if (player_image_url && (width || height)) {
- _src_ = player_image_url.replace('WIDTH', width + '').replace('HEIGHT', height + '');
- }
- return _src_;
- };
- var imageUrl = this.getVisualizers()[""+select.val()];
- //consolelog(this.getVisualizers());
- //alert(imageUrl);
- var imgSrc = funcImg(imageUrl, image.width(),image.height());
- if(image.attr('src')==imgSrc){
- // consolelog('setting attrt');
- return;
- }
- var w =select.width();
- var h = select.height();
- select.hide();
- var progressBar = container.find('.ts-wait').css({
- 'width':w+'px',
- 'height':h+'px'
- }).show();
-
- image.load(function(){
- progressBar.hide();
- select.show();
- image.unbind('load');
- });
- //this timeout is set in order to leave the time to hide show components above:
- //setTimeout(function(){
- image.attr('src', imgSrc);
- //},100);
-
- },
-
- getSoundVolume :function(){
- var s = this.getSound();
- return s ? s.volume : 0;
- },
- //moves the pointer (and sound position) forward till the next marker or the end of sound
- forward: function() {
- var map = this.getMarkerMap();
- var markers = map.toArray();
- var len = markers.length;
- var offset = this.getSoundDuration();
- var position = this.getSoundPosition(); //parseFloat(this.getSoundPosition());
- var idx = map.insertionIndex(position);
- //consolelog('current pointer position: '+position+' '+(typeof position));
- if(idx<0){
- idx = -idx-1; //cursor is not on a a marker, get the insertion index
- }else{
- //cursor is on a marker. As there might be several markers with the same offset
- //(see MarkerMap.insertionIndex), move to the outmost right
- while(idx<len && markers[idx].offset == position){
- idx++;
- }
- }
-
- if(idx< len){
- offset = markers[idx].offset;
- }
- this.setSoundPosition(offset);
- this.getRuler().movePointer(offset);
- return false;
- },
- //moves the pointer (and sound position) backward till the previous marker or the start of sound
- rewind: function() {
- var map = this.getMarkerMap();
- var markers = map.toArray();
- var offset = 0;
- var position = this.getSoundPosition(); //parseFloat(this.getSoundPosition());
- var idx = map.insertionIndex(position);
- if(idx<0){
- idx = -idx-1; //cursor is not on a a marker, get the insertion index
- }else{
- //cursor is on a marker. As there might be several markers with the same offset
- //(see MarkerMap.insertionIndex), move to the outmost left
- while(idx>0 && markers[idx-1].offset == position){
- idx--;
- }
- }
- idx--; //move backward (rewind)
- if(idx>=0){
- offset = markers[idx].offset;
- }
- this.setSoundPosition(offset);
- this.getRuler().movePointer(offset)
- return false;
- },
-
- setSoundVolume: function(volume){
-
- if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest
- //see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number
- volume = 100;
- }
- if(volume<0){
- volume = 0;
- }else if(volume>100){
- volume = 100;
- }
- var sound = this.getSound();
- // if(sound.volume == volume){
- // return;
- // }
- sound.setVolume(volume);
- //update the anchor image:
- var indices = [20,40,60,80,100,100000];
-
- var volumeElm = this.getContainer().find('.ts-volume');
- for(var i=0; i <indices.length; i++){
- if(volume<indices[i]){
- var pos = -28*i;
- pos = '0px '+ pos+ 'px'; //DO NOT SET !important as in FF3 DOES NOT WORK!!!!!
- volumeElm.css('backgroundPosition',pos);
- return;
- }
- }
- // this.elements.volume.css('backgroundPosition','0px 0px !important')
-
- },
-
- loadMarkers: function(){
- //ruler.bind('markermoved',this.markerMoved,this);
- var $J = this.$J; //reference to jQuery
- var isInteractive_ = this.getCurrentUserName() || false;
- var itemId = this.getItemId();
-
- var player = this;
- //initialize the map.
- var map = this.getMarkerMap();
- var mapUI = this.getMarkersUI();
- var ruler = this.getRuler();
- map.clear();
- mapUI.clear();
- ruler.clear();
-
- //building the onSuccess function
- var onSuccess = function(data) {
- var tabIndex = 0;
- var mapuiAdd = mapUI.add;
- var rulerAdd = ruler.add;
-
- if(data && data.result && data.result.length>0){
- var result = data.result;
- //add markers to the map. No listeners associated to it (for the moment)
- var mapAdd = map.add;
- for(var i =0; i< result.length; i++){
- mapAdd.apply(map,[result[i]]);
- }
- //add markers to ruler and div
- map.each(function(i,marker){
- rulerAdd.apply(ruler,[marker, i]);
- mapuiAdd.apply(mapUI,[marker, i]);
- });
-
- tabIndex = result.length>0 ? 1 : 0;
- }
- //BINDINGS:
- //
- //1) ADD
- //
- //add binding to the setMarker button (html anchor):
- var setMarkerButton = player.getContainer().find('.ts-set-marker');
- var tab = $J('#tab_markers');
- if(setMarkerButton){
- if(isInteractive_){
- setMarkerButton.show().attr('href','#').unbind('click').bind('click', function(){
- if(tab && tab.length){
- tab.trigger('click');
- }
- map.add(player.getSoundPosition());
- return false;
- });
- }else{
- setMarkerButton.hide().unbind('click');
- }
- }
-
-
- //the function above calls map.add:
- //add bindings when adding a marker:
- map.bind('add',function(data){
- mapuiAdd.apply(mapUI,[data.marker, data.index,data.isNew]);
- rulerAdd.apply(ruler,[data.marker, data.index]);
- });
-
- //2) MOVE
-
- //add the binding when we move a marker on the ruler:
- ruler.bind('markermoved',function(data){
- var soundPos = data.soundPosition;
- var markerClass = data.markerClass;
- if(markerClass=='pointer'){
- player.setSoundPosition(soundPos);
- }else{
- map.move(data.markerElement.getIndex(), soundPos);
- }
- });
-
- //and now add a binding to the map when we move a marker:
- var rulerMove = ruler.move;
- var mapuiMove = mapUI.move;
-
- map.bind('move', function(data){
- var from = data.fromIndex;
- var to = data.toIndex;
- rulerMove.apply(ruler,[from,to]);
- mapuiMove.apply(mapUI,[from,to,data.newOffset]);
- });
-
- //3) EVENTS ON MARKERDIV: SAVE AND REMOVE
- //save - UI delegates the map:
- var mapSave = map.save;
- mapUI.bind('save',function(data){
- mapSave.apply(map,[data.marker]);
- });
- //and map delegates back to the UI:
- var mapuiSetEditMode = mapUI.setEditMode;
- map.bind('save',function(data){
- mapuiSetEditMode.apply(mapUI,[data.index,false]);
- });
-
- //remove - UI delegates the map:
- var mapRemove = map.remove;
- mapUI.bind('remove',function(data){
- mapRemove.apply(map,[data.marker]);
- });
- //and, again, map delegates back to the UIs:
- var mapuiRemove = mapUI.remove;
- var rulerRemove = ruler.remove;
- map.bind('remove',function(data){
- mapuiRemove.apply(mapUI, [data.index]);
- rulerRemove.apply(ruler, [data.index]);
- });
-
- //finally, focus events (WHEN the user CLICKS on a textinput or a textarea on a markerdiv)
- mapUI.bind('focus', function(data){
- if(data && 'index' in data){
- if(data.index>=0 && data.index<map.length){
- var offset = map.toArray()[data.index].offset;
- player.setSoundPosition(offset);
- player.getRuler().movePointer(offset);
- }
- }
- });
-
- $J('#loading_span').empty().remove();
- //TODO: move this in load_player?
- // setUpPlayerTabs([jQuery('#tab_analysis'), jQuery('#tab_markers')],
- // [jQuery('#analyzer_div_id'), jQuery('#markers_div_id')], tabIndex,
- // 'tab_selected','tab_unselected');
- setUpPlayerTabs($J('#tab_analysis').add($J('#tab_markers')),
- [$J('#analyzer_div_id'), $J('#markers_div_id')], tabIndex,
- 'tab_selected','tab_unselected');
- };
- json([itemId],"telemeta.get_markers", onSuccess);
- }
-});
\ No newline at end of file
+++ /dev/null
-/**
- * TimeSide - Web Audio Components
- * Copyright (c) 2011 Parisson
- * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
- * License: GNU General Public License version 2.0
- */
-
-/**
- * Class for loading a player. Requires a div#player, jQuery and all timeside javascript (player.js, markermap.js etcetera)
- */
-
-var player; //global player variable
-
-function togglePlayerMaximization() {
- consolelog('entered togglePlayerMaximization');
- var view = $('#player');
- $('#player_maximized, #player_minimized').css('display', 'none');
- var ctr;
- var dynamicResize = false;
- if (view.parents('#player_maximized').length) {
- ctr = $('#player_minimized').append(view);
- } else {
- ctr = $('#player_maximized').append(view);
- dynamicResize = true;
- }
- ctr.css({
- opacity: 0,
- display: 'block'
- });
- var p = player;
- if (p){
- p.resize();
- }
- ctr.animate({
- opacity: 1
- }, 100);
- if (p){
- p.setDynamicResize(dynamicResize);
- }
-}
-
-
-
-function loadPlayer(analizerUrl, soundUrl, itemId, visualizers, currentUserName){
- var $J = jQuery;
- var playerDiv = $J('#player');
- if (!playerDiv.length){
- //playerError('div #player does not exists');
- //DO NOT RAISE ANY ERROR, JUST RETURN
- return;
- }
-
- if(!(analizerUrl)){
- playerError('invalid analyzer url');
- return;
- }
-
- if(!(soundUrl)){
- playerError('invalid sound url');
- return;
- }
-
-
- //consolelog('till here all ok1');
- var msgElm = $J('#loading_span_text'); //element to show messages
- //consolelog('till here all ok2');
- if(msgElm){
- msgElm.html('Loading analyzer...');
- }
-
- var tableBody = $J('#analyzer_div_id').find('table').find('tbody:last');
-
- //function to be executed when the analyzer has fully loaded (ie, a duration is provided)
- function load_player(soundUrl, durationInMsec, itemId, visualizers, currentUserName) {
- var sound = soundManager.createSound({
- id: 'sound',
- autoLoad: false,
- url: soundUrl
- });
-
- loadScripts('/timeside/src/',['rulermarker.js','markermap.js', 'player.js', 'ruler.js','divmarker.js'], function() {
-
-
- var p = new Player(jQuery('#player'), sound, durationInMsec, itemId, visualizers, currentUserName);
- consolelog('initialized player');
- p._setupInterface();
-
- player = p;
-
- $J('#player_maximized .toggle, #player_minimized .toggle').click(function() {
- togglePlayerMaximization();
- this.blur();
- return false;
- });
- });
- };
-
- $J.ajax({
- url: analizerUrl, //'analyze/xml',
- dataType: 'xml',
- success: function(data){
- //populatetable
- $J.each($J(data).find('data'),function(index,element){
- var elm = $J(element);
- tableBody.append('<tr><td>'+elm.attr('name')+'</td><td>'+elm.attr('value')+'</td><td>'
- +elm.attr('unit')+'</td></tr>');
- });
- //loaded analizer, loading player
- if(msgElm){
- msgElm.html('Loading player...');
- }
- var duration = $J(data).find('#duration').attr('value');
- duration = duration.split(":");
- consolelog('analyzer loaded, duration: '+duration);
- //format duration
- var pin = parseInt;
- var pfl = parseFloat;
- var timeInMSecs=pin(duration[0])*3600+pin(duration[1])*60+pfl(duration[2]);
- timeInMSecs = Math.round(timeInMSecs*1000);
- load_player(soundUrl, timeInMSecs, itemId, visualizers, currentUserName);
- },
- error:function(){
- playerError('Error loading analyzer');
- //"<img src='/images/dialog-error.png' style='vertical-align:middle'/><span class='login-error'>Error loading analyzer</span>");
- }
- });
-}
-
-
-
-//function loadPlayer(analizerUrl, soundUrl, itemId, visualizers, currentUserName){
-//
-// if(!(analizerUrl) || !(soundUrl)){
-// return;
-// }
-//
-// var $J = jQuery;
-// //consolelog('till here all ok1');
-// var msgElm = $J('#loading_span_text'); //element to show messages
-// //consolelog('till here all ok2');
-// if(msgElm){
-// msgElm.html('Loading analyzer...');
-// }
-// var url = urlNormalized();
-// var tableBody = $J('#analyzer_div_id').find('table').find('tbody:last');
-// var load_player = this.load_player;
-// $J.ajax({
-// url: analizerUrl, //'analyze/xml',
-// dataType: 'xml',
-// success: function(data){
-// //populatetable
-// $J.each($J(data).find('data'),function(index,element){
-// var elm = $J(element);
-// tableBody.append('<tr><td>'+elm.attr('name')+'</td><td>'+elm.attr('value')+'</td><td>'
-// +elm.attr('unit')+'</td></tr>');
-// });
-// //loaded analizer, loading player
-// if(msgElm){
-// msgElm.html('Loading player...');
-// }
-// var duration = $J(data).find('#duration').attr('value');
-// duration = duration.split(":");
-// consolelog('analyzer loaded, duration: '+duration);
-// //format duration
-// var pin = parseInt;
-// var pfl = parseFloat;
-// var timeInMSecs=pin(duration[0])*3600+pin(duration[1])*60+pfl(duration[2]);
-// timeInMSecs = Math.round(timeInMSecs*1000);
-// load_player(soundUrl, timeInMSecs, itemId, visualizers, currentUserName);
-// },
-// error:function(){
-// playerError('Error loading analyzer');
-// //"<img src='/images/dialog-error.png' style='vertical-align:middle'/><span class='login-error'>Error loading analyzer</span>");
-// }
-// });
-//}
-//
-//
-////loads a player WAITING for the sound identified by soundUrl to be FULLY LOADED!!!!
-//function load_player(soundUrl, durationInMsecs, itemId, visualizers, currentUserName) {
-// consolelog('PlayerLoader.load_player: '+soundUrl+' '+durationInMsecs);
-// var load_player2 = this.load_player2;
-//
-// //this variable can be changed to load a sound immediately or not
-// var loadImmediately = true;
-// if(durationInMsecs){
-// loadImmediately = false;
-// }
-// var sound = soundManager.createSound({
-// id: 'sound',
-// autoLoad: loadImmediately,
-// url: soundUrl,
-// onload: function() { //formerly was: whileloading
-// //PROBLEM/BUG: on chrome and firefox whileloading is the same as onload,
-// //ie it is not called at regular interval but when the whole file has loaded
-// if(loadImmediately){
-// consolelog('entering while loading setting up---------------'+this.bytesLoaded+' of '+this.bytesTotal);
-// loadImmediately=false;
-// load_player2(this, this.duration, itemId, visualizers, currentUserName);
-// }
-// }
-// });
-// if(!loadImmediately){
-// //TODO: remove this code is only temporary here!!!!!!!!!!!!!!!!!!!!1
-// loadScripts('/timeside/src/',['rulermarker.js', //'markerlist.js',
-// 'markermap.js', 'player.js', 'ruler.js','divmarker.js'], function(){
-// load_player2(sound,durationInMsecs,itemId, visualizers, currentUserName);
-// });
-// }
-//
-//}
-////NOTE: the duration must be present. Loaded from xmlanalyzer (see above)
-//function load_player2(sound, durationInMsec, itemId, visualizers, currentUserName) {
-//
-// if (!$('#player').length){
-// return;
-// }
-// consolelog("entered load_player2");
-//
-// //TODO: what are we doing here????
-//// $('.ts-wave a img').insertAfter('.ts-wave a');
-//// $('.ts-wave a').remove();
-//
-// var p = new Player(jQuery('#player'), sound, durationInMsec, itemId, visualizers, currentUserName);
-// consolelog('initialized player');
-// p._setupInterface();
-// //p.loadMarkers();
-//
-// player = p;
-//
-//// var change_visualizer_click = change_visualizer_clicked;
-//// $('#visualizer_id').change(change_visualizer_click);
-// //$('#visualizer_id_form').submit(change_visualizer_clicked);
-//
-// $('#player_maximized .toggle, #player_minimized .toggle').click(function() {
-// togglePlayerMaximization();
-// this.blur();
-// return false;
-// });
-//
-//
-//}
+++ /dev/null
-
-var Ruler = TimesideArray.extend({
- //init constructor: soundDuration is IN SECONDS!!! (float)
- init: function(viewer, soundDuration, isInteractive){
- this._super();
- var cssPref = this.cssPrefix;
-
- this.isInteractive = function(){
- return isInteractive;
- };
-
- this.getSoundDuration= function(){
- return soundDuration;
- };
-
- var waveContainer = viewer.find('.' + cssPref + 'image-canvas');
- this.debug( 'WAVECONTAINER?? LENGTH='+ waveContainer.length);
- this.getWaveContainer =function(){
- return waveContainer;
- };
- //ts-image-canvas has width=0. Why was not the case in old code?
- //BECAUSE IN OLD CODE ts-image-canvas has style="width..height" defined, and not HERE!!!!
- this.getContainerWidth =function(){
- return waveContainer.width();
- };
-
-
- this.debug( 'init ruler: container width '+this.getContainerWidth());
-
-
- //private function used in resize() defined below
-
-
- var container = viewer.find('.' + cssPref + 'ruler');
-
- this.getRulerContainer = function(){
- return container;
- }
-
-
- if(!isInteractive){ //is not interactive, skip all methods assignmenets below
- return;
- }
- },
-
- resize : function(){
- //code copied from old implementation, still to get completely what is going on here...
- var sectionSteps = [[5, 1], [10, 1], [20, 2], [30, 5], [60, 10], [120, 20], [300, 30],
- [600, 60], [1800, 300], [3600, 600]];
- //old computeLayout code
- var fullSectionDuration,sectionSubDivision, sectionsNum;
- var width = this.getContainerWidth();
- var duration = this.getSoundDuration();
- var cssPref = this.cssPrefix;//defined in superclass
- var fontSize = 10;
- var mfloor = Math.floor; //instanciating once increases performances
- var $J = this.$J; //reference to jQuery
- //this.debug('container width: ' +" "+width);
-
-
- var i, ii = sectionSteps.length;
- var timeLabelWidth = this._textWidth('00:00', fontSize);
- for (i = 0; i < ii; i++) {
- var tempDuration = sectionSteps[i][0];
- var subDivision = sectionSteps[i][1];
- var labelsNum = mfloor(duration / tempDuration);
- if ((i == ii - 1) || (width / labelsNum > timeLabelWidth * 2)) {
- fullSectionDuration = tempDuration;
- sectionSubDivision = subDivision;
- sectionsNum = mfloor(duration / fullSectionDuration);
- //this.debug('(in _computeLayout) this.fullSectionDuration: ' + fullSectionDuration);
- //this.debug('(in _computeLayout) sectionsNum: ' +sectionsNum);
- //this.debug('(in _computeLayout) sectionSubDivision: ' +sectionSubDivision);
- break;
- }
- }
- //old draw() code:
- if (!duration) {
- this.debug("Can't draw ruler with a duration of 0");
- return;
- }
- //this.debug("draw ruler, duration: " + duration);
-
- var container = this.getRulerContainer();
- var layout = container.find("."+cssPref + 'layout');
- //REDONE: if does not exists, create it
- if(!layout || !(layout.length)){
- layout = $J('<div/>')
- .addClass(cssPref + 'layout')
- .css({
- position: 'relative'
- }) // bugs on IE when resizing
- //TODO: bind doubleclick events!!!!!!
- //.bind('dblclick', this.attachWithEvent(this._onDoubleClick))
- //.bind('resize', this.attachWithEvent(this.resize)) // Can loop ?
- .appendTo(container);
- }else{
- //remove all elements neither pointer nor marker
- layout.find(':not(a.ts-pointer,a.ts-marker,a.ts-pointer>*,a.ts-marker>*)').remove();
- }
-
- // if (layout && layout.length){
- // layout.remove();
- // }
- // layout = $J('<div/>')
- // .addClass(cssPref + 'layout')
- // .css({
- // position: 'relative'
- // }) // bugs on IE when resizing
- // //TODO: bind doubleclick events!!!!!!
- // //.bind('dblclick', this.attachWithEvent(this._onDoubleClick))
- // //.bind('resize', this.attachWithEvent(this.resize)) // Can loop ?
- // .appendTo(container);
-
-
-
- //creating sections
- //defining function maketimelabel
- var makeTimeLabel = this.makeTimeLabel;
-
- //defining the function createSection
- var _createSection = function(timeOffset, pixelWidth,timeLabelWidth) {
- var section = $J('<div/>')
- .addClass(cssPref + 'section')
- .css({
- fontSize: fontSize + 'px',
- fontFamily: 'monospace',
- width: pixelWidth,
- overflow: 'hidden'
- })
- .append($J('<div />').addClass(cssPref + 'canvas'));
-
- var topDiv = $J('<div/>')
- .addClass(cssPref + 'label')
- .appendTo(section);
- var bottomDiv = $J('<div/>')
- .addClass(cssPref + 'lines')
-
- .appendTo(section);
- var empty = $J('<span/>').css({
- visibility: 'hidden'
- }).text(' ');
- var text;
-
- if (pixelWidth > timeLabelWidth) {
- text = $J('<span/>')
- .text(makeTimeLabel(timeOffset))
- .bind('mousedown selectstart', function() { //WHY THIS?
- return false;
- });
- } else {
- text = empty.clone();
- }
- topDiv.append(text);
- bottomDiv.append(empty);
- return section;
- };
- //function defined, creating sections:
- var sections = new Array();
- var currentWidth = 0;
- var sectionDuration, sectionWidth;
- for (i = 0; i <= sectionsNum; i++) {
- if (i < sectionsNum) {
- sectionDuration = fullSectionDuration;
- sectionWidth = mfloor(sectionDuration / duration * width);
- } else {
- sectionDuration = duration - i * fullSectionDuration;
- sectionWidth = width - currentWidth;
-
- }
- var section = _createSection(i * fullSectionDuration, sectionWidth, timeLabelWidth);
- if (i > 0) {
- section.css({
- left: currentWidth,
- top: 0,
- position: 'absolute'
- });
- }
- section.duration = sectionDuration;
- layout.append(section);
- currentWidth += section.width();
- sections[i] = section;
- }
-
- //function to draw section rulers:
- var _drawSectionRuler= function(section, drawFirstMark) {
- var j;
-
- var jg = new jsGraphics(section.find('.' + cssPref + 'canvas').get(0));
- jg.setColor(layout.find('.' + cssPref + 'lines').css('color'));
- var height = section.height();
- var ypos;
- for (j = 0; j < section.duration; j += sectionSubDivision) {
- if (j == 0) {
- if (drawFirstMark) {
- ypos = 0;
- } else {
- continue;
- }
- } else {
- ypos = (j == section.duration / 2) ? 1/2 + 1/8 : 3/4;
- }
- //var x = j / this.duration * this.width;
- var x = j / duration * width;
- jg.drawLine(x, height * ypos, x, height - 1);
- }
- jg.paint();
- };
- //draw section rulers
- for (i = 0; i <= sectionsNum; i++) {
- _drawSectionRuler(sections[i], (i > 0));
- }
-
-
- var pointer = undefined;
- if('getPointer' in this){
- pointer = this.getPointer();
- }
- if(!pointer){
- //consolelog('QUALE CHAZZO E IL CONTAINER?????? ' + $J(layout.get(0)).attr('class'));
- // pointer = new RulerMarker($J(layout.get(0)),this.getWaveContainer(),'pointer', true);
- // pointer.setText(this.makeTimeLabel(0));
- //
- // this.debug('WELL, ');
- // consolelog(pointer);
- // var me = this;
- // pointer.getLabel().mousedown(function(evt) {
- // var lbl = $J(evt.target);
- // me.markerBeingClicked = {
- // 'marker':pointer,
- // 'offset':evt.pageX-(lbl.offset().left+lbl.outerWidth(true)/2)
- // };
- // consolelog(evt.pageX-(lbl.offset().left+lbl.outerWidth(true)/2));
- // evt.stopPropagation(); //dont notify the ruler;
- // return false;
- // });
- pointer = this.add(0);
- this.getPointer = function(){
- return pointer;
- };
- }else{
- pointer.refreshPosition();
-
- }
- this.each(function(i,rulermarker){
- rulermarker.refreshPosition();
- });
-
- // if(!pointer){
- // this.debug("Creating pointer:"+layout);
- // //this.createMarkerForRuler = function(rulerLayout,viewer,className, fontSize, optionalToolTip)
- // pointer = this.createMarkerForRuler($J(layout.get(0)),waveContainer,'pointer',fontSize,'move pointer');
- // this.debug('pointerdisplay'+pointer.css('display'));
- // }
-
- //TODO: move pointer??????
- //this._movePointer(sound.position/1000);
-
-
- //TODO: draw markers?
- // if (this.cfg.map) {
- // $J(this.markers).each(function(i, m) {
- // m.clear();
- // });
- // this.markers = new Array();
- // this.cfg.map.each(this.attach(function(i, m) {
- // this.markers.push(this._drawMarker(m, i));
- // }));
- // }
- },
-
- //overridden: Note that the pointer is NOT cleared!!!!!
- clear: function(){
- var markers = this._super();
- // if('getPointer' in this){
- // markers.push(this.getPointer());
- // }
- for( var i=0; i<markers.length; i++){
- markers[i].remove();
- }
- return markers;
- },
- //overridden TimesideArray methods (add, move, remove):
- remove: function(index){
- var rulermarker = this._super(index);
- rulermarker.remove();
- this.each(index, function(i,rulermarker){
- consolelog(i);
- rulermarker.setIndex(i, true);
- });
- },
- //overridden
- move: function(from, to){
- var newIndex = this._super(from,to);
- //this.debug('ruler.move: [from:'+from+', to:'+to+', real:'+newIndex+']');
- if(newIndex!=from){
- var i1 = Math.min(from,newIndex);
- var i2 = Math.max(from,newIndex)+1;
- //this.debug('updating ['+i1+','+i2+']');
- this.each(i1,i2, function(index,rulermarker){
- rulermarker.setIndex(index, true);
- });
- }
- },
- //overridden
- //markerObjOrOffset can be a marker object (see in markermap) or any object with the fields isEditable and offset
- add: function(markerObjOrOffset, indexIfMarker){
- var soundPosition;
- var isMovable;
- var markerClass;
-
- if(typeof markerObjOrOffset == 'number'){
- soundPosition = markerObjOrOffset;
- isMovable = true; //this.isInteractive();
- markerClass='pointer';
- }else{
- soundPosition = markerObjOrOffset.offset;
- isMovable = markerObjOrOffset.isEditable && this.isInteractive();
- markerClass='marker';
- }
-
- var container = this.getRulerContainer();
- var layout = container.find("."+this.cssPrefix + 'layout');
- var $J = this.$J;
- var pointer = new RulerMarker($J(layout.get(0)),this.getWaveContainer(),markerClass);
- //call super constructor
- //if it is a pointer, dont add it
- if(markerClass != 'pointer'){
- this._super(pointer,indexIfMarker); //add at the end
- //note that setText is called BEFORE move as move must have the proper label width
- this.each(indexIfMarker, function(i,rulermarker){
- rulermarker.setIndex(i,i!=indexIfMarker);
- //rulermarker.setIndex.apply(rulermarker, [i,i!=indexIfMarker]); //update label width only if it is not this marker added
- //as for this marker we update the position below (move)
- });
- this.debug('added marker at index '+indexIfMarker+' offset: '+markerObjOrOffset.offset);
- }else{
- //note that setText is called BEFORE move as move must have the proper label width
- pointer.setText(this.makeTimeLabel(0));
- }
- //proceed with events and other stuff: move (called AFTER setText or setText)
- pointer.move(this.toPixelOffset(soundPosition));
-
- //pointer.setText(markerClass== 'pointer' ? this.makeTimeLabel(0) : this.length);
-
- //click on labels stop propagating. Always:
- var lbl = pointer.getLabel();
- lbl.bind('click', function(evt){
- evt.stopPropagation();
- return false;
- });
-
- //if there are no events to associate, return it.
- if(!isMovable){
- return pointer;
- }
-
- //namespace for jquery event:
- var eventId = 'markerclicked';
- var doc = $J(document);
-
- var me = this;
-
- var ismovingpointer = false;
- var setmovingpointer = function(value){
- ismovingpointer = value;
- }
- //TODO: this method below private, but how to let him see in the bind below???
- this.setPointerMovingFromMouse = function(value){
- setmovingpointer(value);
- }
- this.isPointerMovingFromMouse = function(){
- return ismovingpointer;
- };
- //functions to set if we are moving the pointer (for player when playing)
-
- lbl.bind('mousedown.'+eventId,function(evt) {
-
- if(markerClass=='pointer'){
- me.setPointerMovingFromMouse(true);
- }
-
- var startX = evt.pageX; //lbl.position().left-container.position().left;
- var startPos = lbl.position().left+lbl.width()/2;
-
- evt.stopPropagation(); //dont notify the ruler or other elements;
- var newPos = startPos;
- doc.bind('mousemove.'+eventId, function(evt){
- var x = evt.pageX;
- newPos = startPos+(x-startX);
- pointer.move(newPos);
- //update the text if pointer
- if(markerClass=='pointer'){
- pointer.setText(me.makeTimeLabel(me.toSoundPosition(newPos)));
- }
- return false;
-
- });
- //to avoid scrolling
- //TODO: what happens if the user releases the mouse OUTSIDE the browser????
- var mouseup = function(evt_){
- doc.unbind('mousemove.'+eventId);
- doc.unbind('mouseup.'+eventId);
- evt_.stopPropagation();
- if(markerClass=='pointer'){
- me.setPointerMovingFromMouse(false);
- }
- if(newPos == startPos){
- consolelog('NOT MOVED!!!!');
- return false;
- }
- var data = {
- 'markerElement':pointer,
- 'soundPosition': me.toSoundPosition.apply(me,[newPos]),
- 'markerClass':markerClass
- };
- me.fire('markermoved',data);
- return false;
- };
- doc.bind('mouseup.'+eventId, mouseup);
- //lbl.bind('mouseup.'+eventId, mouseup);
- // doc.bind('mouseup.'+eventId, function(evt){
- // consolelog(newPos);
- // doc.unbind('mousemove.'+eventId);
- // doc.unbind('mouseup.'+eventId);
- //
- // //TODO: fire event marker moved (with the class name)
- // var data = {
- // 'markerElement':pointer,
- // 'soundPosition': me.toSoundPosition.apply(me,[newPos]),
- // 'markerClass':markerClass
- // };
- // me.fire('markermoved',data);
- // return false;
- // });
- return false;
- });
-
- return pointer;
-
-
- },
-
- //moves the pointer, does not notify any listener.
- //soundPosition is in seconds (float)
- movePointer : function(soundPosition) {
- var pointer = this.getPointer();
- if (pointer) {
- var pixelOffset = this.toPixelOffset(soundPosition);
- //first set text, so the label width is set, then call move:
- pointer.setText(this.makeTimeLabel(soundPosition));
- pointer.move(pixelOffset); //does NOT fire any move method
- }
- //this.debug('moving pointer: position set to '+offset);
- return soundPosition;
- },
-
- //soundPosition is in seconds (float)
- toPixelOffset: function(soundPosition) {
- //this.debug('sPos:' + soundPosition+ 'sDur: '+this.getSoundDuration());
- var duration = this.getSoundDuration();
- if (soundPosition < 0){
- soundPosition = 0;
- }else if (soundPosition > duration){
- soundPosition = duration;
- }
- var width = this.getContainerWidth();
- var pixelOffset = (soundPosition / duration) * width;
- return pixelOffset;
- },
-
- //returns the soundPosition is in seconds (float)
- toSoundPosition: function(pixelOffset) {
- var width = this.getContainerWidth();
-
- if (pixelOffset < 0){
- pixelOffset = 0;
- }else if (pixelOffset > width){
- pixelOffset = width;
- }
- var duration = this.getSoundDuration();
- var soundPosition = (pixelOffset / width) *duration;
- return soundPosition;
- }
-});
-
-
- // TODO: check here
- // http://stackoverflow.com/questions/3299926/ie-mousemove-bug
- // div in IE to receive mouse events must have a background
- // so for the moment
-
-
-
- // var mouseDown = false;
- // var _onMouseDown = function(evt) {
- // mouseDown = true;
- // this._onMouseMove(evt);
- // evt.preventDefault(); //If this method is called, the default action of the event will not be triggered.
- // };
- // var _onMouseMove = function(evt) {
- // if (mouseDown) {
- // var pixelOffset = evt.pageX - container.offset().left;
- // this._movePointerAndUpdateSoundPosition(pixelOffset / this.width * this.duration);
- // //moves the pointer and fires onPointerMove
- // }
- // return false;
- // };
- //
- // var _onMouseUp= function(evt) {
- // if (mouseDown) {
- // mouseDown = false;
- // this.debug('_onMouseUp:'+this.pointerPos+' '+this.cfg.sound.position);
- // }
- // return false;
- // };
- // var imgContainer = viewer.find('.' + cssPref + 'image-container'); // for IE
- // var element = waveContainer.add(imgContainer); //constructs a new jQuery object which is the union of the jquery objects
- //
- // element
- // .bind('click dragstart', function() {
- // return false;
- // })
- // .bind('mousedown', function(evt){
- // return _onMouseDown(evt);
- // })
- // .bind('mousemove', function(evt){
- // return _onMouseMove(evt);
- // })
- // .bind('mouseup', function(evt){
- // return _onMouseUp(evt);
- // });
- // this.$J(document)
- // .bind('mousemove', function(evt){
- // return _onMouseMove(evt);
- // });
\ No newline at end of file
+++ /dev/null
-/**
- * TimeSide - Web Audio Components
- * Copyright (c) 2011 Parisson
- * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
- * License: GNU General Public License version 2.0
- */
-
-/**
- * Class representing a RulerMarker in TimesideUI
- * Requires jQuery and all associated player classes
- */
-
-var RulerMarker = TimesideClass.extend({
-
- init: function(rulerLayout, viewer, className) {
- this._super();
- var $J = this.$J;
- var fontSize = 10;
- this.getFontSize = function(){
- return fontSize;
- }
- var zIndex = 1000;
- var tooltip = '';
- //TODO: why viewer get(0) ? more than one? check and maybe simplify
- var painter = new jsGraphics(viewer.get(0));
- //from create (oldCode)
- var cssPref = this.cssPrefix;
- var y = rulerLayout.find('.' + cssPref + 'label').outerHeight();
- //added by me:================
- if(className == "pointer"){
- y = 0;
- }
- //==========================
- var label = $J('<a/>')
- .css({
- display: 'block',
- width: '10px',
- textAlign: 'center',
- position: 'absolute',
- fontSize: fontSize + 'px',
- fontFamily: 'monospace',
- top: y + 'px'
- })
- .attr('href', '#')
- .addClass(cssPref + className)
- .append('<span />')
- //.hide();
-
- if (tooltip){
- label.attr('title', tooltip);
- }
-
- rulerLayout.append(label);
-
- var height = viewer.height();
- var x = 0;
- painter.drawLine(x, 0, x, height);
-
- x = [-4, 4, 0];
- y = [0, 0, 4];
-
- painter.fillPolygon(x, y);
- painter.paint();
- var nodes = $J(painter.cnv).children();
-
- var style = {};
- if (zIndex) {
- style.zIndex = zIndex;
- label.css(style);
- }
- style.backgroundColor = '';
- //nodes.hide();
- nodes.css(style).addClass(cssPref + className)
- .each(function(i, node) {
- node.originalPosition = parseInt($J(node).css('left'));
- });
-
- //set the index,
- var index = -1;
- this.setIndex = function(idx, optionalUpdateLabelWidth){
- index = idx;
- this.setText(idx+1, optionalUpdateLabelWidth ? true : false);
- };
- this.getIndex = function(){
- return index;
- }
-
- //end=======================================================
- //creating public methods:
- this.getLabel = function(){
- return label;
- }
-
-
- //CODE HERE BELOW IS EXECUTED ONLY IF THE MARKER HAS CAN MOVE IMPLEMENTED (see Ruler???).
- //Otherwise, no mouse event can call these methods
- //re-implement function move
- // var position = 0;
- // var relativePosition = 0; //position in percentage of container width, set it in move and use it in refreshPosition
- //
- // var mRound = Math.round; //instantiate the functio once
-
- // this.move = function(pixelOffset) {
- // var width = viewer.width();
- // if (position != pixelOffset) {
- // if (pixelOffset < 0) {
- // pixelOffset = 0;
- // } else if (pixelOffset >= width) {
- // pixelOffset = width - 1;
- // }
- // nodes.each(function(i, node) {
- // $J(node).css('left', mRound(node.originalPosition + pixelOffset) + 'px');
- // });
- // position = pixelOffset;
- // this.refreshLabelPosition(width);
- // //store relative position (see refreshPosition below)
- // relativePosition = pixelOffset == width-1 ? 1 : pixelOffset/width;
- // }
- // return this;
- // };
- //
- // this.refreshLabelPosition = function(optionalContainerWidth){
- // if(!(optionalContainerWidth)){
- // optionalContainerWidth = viewer.width();
- // }
- // var width = optionalContainerWidth;
- // var pixelOffset = position;
- // var labelWidth = label.outerWidth(); //consider margins and padding //label.width();
- // var labelPixelOffset = pixelOffset - labelWidth / 2;
- // if (labelPixelOffset < 0){
- // labelPixelOffset = 0;
- // }else if (labelPixelOffset + labelWidth > width){
- // labelPixelOffset = width - labelWidth;
- // }
- // label.css({
- // left: mRound(labelPixelOffset) + 'px'
- // });
- //
- // };
- //
- // //function called on ruler.resize. Instead of recreating all markers, simply redraw them
- // this.refreshPosition = function(){
- // var width = viewer.width();
- // //store relativePosition:
- // var rp = relativePosition;
- // this.move(mRound(relativePosition*width));
- // //reset relative position, which does not have to change
- // //but in move might have been rounded:
- // relativePosition = rp;
- // //last thing: resize the vertical line.
- // //Assumptions (having a look at the web page element with a debugger and the code above
- // //which uses jsgraphics):
- // //The line is the first item (see drawLine above)
- // //not only the height, but also the height of the clip property must be set
- // var h = viewer.height();
- // $J(nodes[0]).css({
- // 'height':h+'px',
- // 'clip': 'rect(0px 1px '+h+'px 0px)'
- // });
- // }
- //
- // this.remove = function() {
- // painter.clear();
- // $J(painter.cnv).remove();
- // label.remove();
- // return this;
- // };
-
- this.getViewer = function(){
- return viewer;
- }
- this.getPainter = function(){
- return painter;
- }
-
- this.positionInPixels = 0;
- this.positionAsViewerRatio = 0;
-
- },
-
- //sets the text of the marker, if the text changes the marker width and optionalUpdateLabelPosition=true,
- //re-arranges the marker position to be center-aligned with its vertical line (the one lying on the wav image)
- setText: function(text, optionalUpdateLabelPosition) {
- var label = this.getLabel();
- if (label) {
- text += '';
- var labelWidth = this._textWidth(text, this.getFontSize()) + 10;
- var oldWidth = label.width();
- if (oldWidth != labelWidth) {
- label.css({
- width: labelWidth+'px'
- });
- }
- label.find('span').html(text);
- if(oldWidth != labelWidth && optionalUpdateLabelPosition){
- consolelog('refreshing label position');
- this.refreshLabelPosition();
- }
- }
- return this;
- },
-
-
- getNodes: function(){
- return this.$J(this.getPainter().cnv).children();
- },
- //these methods are executed only if marker is movable (see Ruler.js)
-
- move : function(pixelOffset) {
- var width = this.getViewer().width();
- if (this.positionInPixels != pixelOffset) {
- if (pixelOffset < 0) {
- pixelOffset = 0;
- } else if (pixelOffset >= width) {
- pixelOffset = width - 1;
- }
- var nodes = this.getNodes();
- var $J = this.$J;
- var mRound = this.mRound;
- nodes.each(function(i, node) {
- $J(node).css('left', mRound(node.originalPosition + pixelOffset) + 'px');
- });
- this.positionInPixels = pixelOffset;
- this.refreshLabelPosition(width);
- //store relative position (see refreshPosition below)
- this.positionAsViewerRatio = pixelOffset == width-1 ? 1 : pixelOffset/width;
- }
- return this;
- },
-
- refreshLabelPosition : function(optionalContainerWidth){
- if(!(optionalContainerWidth)){
- optionalContainerWidth = this.getViewer().width();
- }
- var label = this.getLabel();
- var width = optionalContainerWidth;
- var pixelOffset = this.positionInPixels;
- var labelWidth = label.outerWidth(); //consider margins and padding //label.width();
- var labelPixelOffset = pixelOffset - labelWidth / 2;
- if (labelPixelOffset < 0){
- labelPixelOffset = 0;
- }else if (labelPixelOffset + labelWidth > width){
- labelPixelOffset = width - labelWidth;
- }
- label.css({
- left: this.mRound(labelPixelOffset) + 'px'
- });
-
- },
-
- //function called on ruler.resize. Instead of recreating all markers, simply redraw them
- refreshPosition : function(){
- var width = this.getViewer().width();
- //store relativePosition:
- var rp = this.positionAsViewerRatio;
- this.move(this.mRound(this.positionAsViewerRatio*width));
- //reset relative position, which does not have to change
- //but in move might have been rounded:
- this.positionAsViewerRatio = rp;
- //last thing: resize the vertical line.
- //Assumptions (having a look at the web page element with a debugger and the code above
- //which uses jsgraphics):
- //The line is the first item (see drawLine above)
- //not only the height, but also the height of the clip property must be set
- var h = this.getViewer().height();
- var nodes = this.getNodes();
- var $J = this.$J;
- $J(nodes[0]).css({
- 'height':h+'px',
- 'clip': 'rect(0px 1px '+h+'px 0px)'
- });
- },
-
- remove : function() {
- var $J = this.$J;
- var painter = this.getPainter();
- var label = this.getLabel();
- painter.clear();
- $J(painter.cnv).remove();
- label.remove();
- return this;
- },
-
- mRound: Math.round
-
-});
+++ /dev/null
-/**
- * TimeSide - Web Audio Components
- * Copyright (c) 2011 Parisson
- * Author: Riccardo Zaccarelli <riccardo.zaccarelli gmail.com> and Olivier Guilyardi <olivier samalyse com>
- * License: GNU General Public License version 2.0
- */
-
-/**
- * Base class defining classes for TimesideUI
- */
-
-/* Simple JavaScript Inheritance
- * By John Resig http://ejohn.org/
- * MIT Licensed.
- * (Inspired by base2 and Prototype)
- *
- * In my (Riccardo) opinion the lightest and most-comprehensive way to implement inhertance and OOP in
- * javascript. Usages can be found below.
- * Basically,
- * 1) a new Class is instantiated with Class.extend(). This function takes a dictionary
- * of properties/methods which will be put IN THE PROTOTYPE of the class, so that each instance will share the same properties/methods
- * and the latter don't have to be created for each instance separately.
- * 2) If var A = Class.extend({...}) and var B = A.extend({..}), then methods which are found in B will override the same methods in A.
- * In this case, the variable this._super inside the overridden methods will refers to the super-method and can thus be called safely.
- * Consequently, if a _super property/method is implemented in the extend dictionary, it WILL NOT be accessible
- * to the overriding methods of B. Basically, don't use _super as a key of the argument of extend.
- * 3) AFTER the prototype has been populated, the init function, if exists, is called. The latter can be seen as a class constructor in java,
- * with a substantial difference: when executing the init() method the class prototype has already been populated with all inherited methods.
- * Private variable can be declared in the init function, as well as
- * relative getters and setters, if needed. Downside is that the privileged getters and setters can’t be put in the prototype,
- * i.e. they are created for each instance separately, and the _super keyword does not apply to them. Another issue is the overhead of closures in general (basically, write as less as possible
- * in the init function, in particular if the class has to be declared several times)
- * Of course, the this._super keyword of methods implemented in the init constructor does not work
- *
- * EXAMPLE:
- * var MyClass = Class.extend({
- * init: function(optionalArray){ //constructor
- * this._super(); //!!!ERROR: Class is the base class and does not have a super construcor
- * var me = []; //private variable
- * this.count = 6; //set the value of the public property defined below
- * this.getMe = function(){ //public method
- * this._super(); //!!!ERROR: methods defined in the init function don't have acces to _super
- * }
- * this.alert = function(){ //another public method, !!!WARNING: this will be put in the MyClass scope (NOT in the prototype)
- * alert('ok');
- * }
- * },
- * count:0, //public property
- * alert: function(){ //public method. !!!WARNING: this method will be put in the prototype BEFORE the init is called,
- * alert('no'); // so the alert defined above will be actually called
- * }
- * });
- * var MyClass2 = MyClass.extend({
- * init: function(){
- * this._super(); //call the super constructor
- * }
- * alert: function(){ //override a method
- * this._super(); //call the super method, ie alerts 'no'. WARNING: However, as long as there is an alert written
- * //in the init method of the superclass (see above), THAT method will be called
- * }
- * });
- *
- */
-//
-(function(){
-
- var initializing = false, fnTest = /xyz/.test(function(){
- xyz;
- }) ? /\b_super\b/ : /.*/;
-
- /*The xyz test above determines whether the browser can inspect the textual body of a function.
- *If it can, you can perform an optimization by only wrapping an overridden method if it
- *actually calls this._super() somewhere in its body.
- *Since it requires an additional closure and function call overhead to support _super,
- *it’s nice to skip that step if it isn’t needed.
- */
-
- // The base Class implementation (does nothing)
- this.Class = function(){};
-
- // Create a new Class that inherits from this class
- Class.extend = function(prop) {
- var _super = this.prototype;
-
- // Instantiate a base class (but only create the instance,
- // don't run the init constructor)
- initializing = true;
- var prototype = new this();
- initializing = false;
-
- // Copy the properties over onto the new prototype
- for (var name in prop) {
- // Check if we're overwriting an existing function
- prototype[name] = typeof prop[name] == "function" &&
- typeof _super[name] == "function" && fnTest.test(prop[name]) ?
- (function(name, fn){
- return function() {
- var tmp = this._super;
-
- // Add a new ._super() method that is the same method
- // but on the super-class
- this._super = _super[name];
-
- // The method only need to be bound temporarily, so we
- // remove it when we're done executing
- var ret = fn.apply(this, arguments);
- this._super = tmp;
-
- return ret;
- };
- })(name, prop[name]) :
- prop[name];
- }
-
- // The dummy class constructor
- function Class() {
- // All construction is actually done in the init method
- if ( !initializing && this.init ){
- this.init.apply(this, arguments);
- }
- }
-
- // Populate our constructed prototype object
- Class.prototype = prototype;
-
- // Enforce the constructor to be what we expect
- Class.constructor = Class;
-
- // And make this class extendable
- Class.extend = arguments.callee;
-
- return Class;
- };
-})();
-
-//Defining the base TimeClass class. Player, Ruler, MarkerMap are typical implementations (see js files)
-//Basically we store here static methods which must be accessible
-//in several timside sub-classes
-var TimesideClass = Class.extend({
-
- _textWidth : function(text, fontSize) {
- var ratio = 3/5;
- return text.length * ratio * fontSize;
- },
-
- /*
- *formats (ie returns a string representation of) a time which is in the form seconds,milliseconds (eg 07.6750067)
- * formatArray is an array of strings which can be:
- * 'h' hours. Use 'hh' for a zero-padding to 10 (so that 6 hours is rendered as '06')
- * 'm' hours. Use 'mm' for a zero-padding to 10 (so that 6 minutes is rendered as '06')
- * 's' hours. Use 'ss' foar a zero-padding to 10 (so that 6 seconds is rendered as '06')
- * 'D' deciseconds
- * 'C' centiseconds (it will be padded to 10, so that 5 centiseconds will be rendered as '05')
- * 'S' milliseconds (it will be padded to 100, so that 5 milliseconds will be rendered as '005')
- * If formatArray is null or undefined or zero-length, it defaults to ['mm','ss']
- * 'h','m' and 's' will be prepended the separator ':'. For the others, the prepended separator is '.'
- * Examples:
- * makeTimeLabel(607,087) returns '10:07' (formatArray defaults to ['mm','ss'])
- * makeTimeLabel(607,087,['m':'s']) returns '10:7'
- * makeTimeLabel(607,087,['m':'s','C']) returns '10:7.09'
- */
- makeTimeLabel: function(time, formatArray){
- if(!(formatArray)){
- formatArray = ['mm','ss'];
- }
- //marker offset is in float format second.decimalPart
- var pInt = parseInt;
- var round = Math.round;
- var factor = 60*24;
- var hours = pInt(time/factor);
- time-=hours*factor;
- factor = 60;
- var minutes = pInt(time/factor);
- time-=minutes*factor;
- var seconds = pInt(time);
- time-=seconds;
-
- //here below the function to format a number
- //ceilAsPowerOfTen is the ceil specifiedas integer indicating the relative power of ten
- //(0: return the number as it is, 1: format as "0#" and so on)
- //Examples: format(6) = "6", format(6,1)= "06", format(23,1)= "23"
-
- //first of all, instantiate the power function once (and not inside the function or function's loop):
- //note that minimumNumberOfDigits lower to 2 returns integer as it is
- var mpow = Math.pow; //instantiate mpow once
- var format = function(integer,minimumNumberOfDigits){
- var n = ""+integer;
- var zero = "0"; //instantiating once increases performances???
- for(var i=1; i< minimumNumberOfDigits; i++){
- if(integer<mpow(10,i)){
- n = zero+n;
- }
- }
- return n;
- }
- var ret = [];
- for(var i =0; i<formatArray.length; i++){
- var f = formatArray[i];
- var separator = ":";
- if(f=='h'){
- ret[i]=hours;
- }else if(f=='hh'){
- ret[i]=format(hours,2);
- }else if(f=='m'){
- ret[i]=minutes;
- }else if(f=='mm'){
- ret[i]=format(minutes,2);
- }else if(f=='s'){
- ret[i]=seconds;
- }else if(f=='ss'){
- ret[i]=format(seconds,2);
- }else if(f=='S'){
- separator = ".";
- ret[i]=format(round(time*1000),3);
- }else if(f=='C'){
- separator = ".";
- ret[i]=format(round(time*100),2);
- }else if(f=='D'){
- separator = ".";
- ret[i]= round(time*10);
- }
- if(i>0){
- ret[i] = separator+ret[i];
- }
- }
- return ret.join("");
- },
-
- cssPrefix : 'ts-',
- $J : jQuery,
- debugging : true,
- debug : function(message) {
- if (this.debugging && typeof console != 'undefined' && console.log) {
- console.log(message);
- }
- },
- //init constructor. Define the 'bind' and 'fire' (TODO: rename as 'trigger'?) methods
- //we do it in the init function so that we can set a private variable storing all
- //listeners. This means we have to re-write all methods
- init: function(){
-
- //the map for listeners. Must be declared in the init as it's private and NOT shared by all instances
- //(ie, every instance has its own copy)
- this.listenersMap={};
- //follows jquery bind. Same as adding a listener for a key
-
- },
-
- /**
- *methods defining listeners, events fire and bind:
- */
- bind : function(key, callback, optionalThisArgInCallback){
- if(!(callback && callback instanceof Function)){
- this.debug('cannot bind '+key+' to callback: the latter is null or not a function');
- return;
- }
- var listenersMap = this.listenersMap;
- var keyAlreadyRegistered = (key in listenersMap);
- if(!keyAlreadyRegistered){
- listenersMap[key] = [];
- }
- listenersMap[key].push({
- callback:callback,
- optionalThisArgInCallback:optionalThisArgInCallback
- });
- },
- unbind : function(){
- var listenersMap = this.listenersMap;
- if(arguments.length>0){
- var key = arguments[0];
- if(key in listenersMap){
- delete listenersMap[key];
- }
- }else{
- for(key in listenersMap){
- delete listenersMap[key];
- }
- }
- },
- fire : function(key, dataArgument){
- var listenersMap = this.listenersMap;
- if(!(key in listenersMap)){
- this.debug(key+' fired but no binding associated to it');
- return;
- }
- var callbacks = listenersMap[key];
- var len = callbacks && callbacks.length ? callbacks.length : 0;
- for(var i=0; i<len; i++){
- var obj = callbacks[i];
- if('optionalThisArgInCallback' in obj){
- obj.callback.apply(obj.optionalThisArgInCallback, [dataArgument]);
- }else{
- obj.callback(dataArgument);
- }
- }
- }
-
-});
-
-//re-implemented array for easier access/modification of markers:
-//Ruler, MArkerMap and MarkerMapDiv implement this class
-var TimesideArray = TimesideClass.extend({
- init: function(optionalArray){
- this._super();
- //here methods that CANNOT be overridden
- var me= optionalArray ? optionalArray : [];
- //note that this method written here OVERRIDES the same method written outside init in the children!!!!
- this.toArray = function(returnACopy){
- if(returnACopy){
- consolelog('copying array');
- var ret = [];
- for(var i=0; i<me.length; i++){
- ret.push(me[i]);
- }
- return ret;
- }
- return me;
- }
- this.length = me.length; //in order to match the javascript array property
- },
- length:0, //implement it as public property to be consistent with Array length property. Be careful however to NOT TO modify directly this property!!!
- //adds at the end of the array. If index is missing the object is appended at the end
- add : function(object, index){
- var array = this.toArray();
- if(arguments.length<2){
- index = array.length;
- }
- array.splice(index,0,object);
- this.length = array.length; //note that length is a property and must be updated!!!
- return object;
- },
- //removes item at index, returns the removed element
- remove : function(index){
- var array = this.toArray();
- var ret = array.splice(index,1)[0];
- this.length = array.length; //note that length is a property and must be updated!!!
- return ret;
- },
- //Iterate over the array, with the same syntax of jQuery.each, ie, executes a function(index,element)
- //for each element from startIndexInclusive to
- //endIndexExclusive.
- //The only required argument is callback:
- //1) each(callback) iterates over all elements executing callback
- //2) each(m, callback) iterates over the elements from m executing callback
- //3) each(m,n,callback) iterates over the elements from m (inclusive) to n-1 (inclusive) executing callback
-
- //NOTE: writing each : function(startInclusive, endExclusive, callback) throws an error in chrome, as the last
- //argument (even if it is a function) is a number. Why?????
- //Anyway, we must write the function arguments as empty
- each : function(){
- // consolelog(arguments.length+' arguments passed. Details: ');
- // for(var j=0; j<arguments.length; j++){
- // consolelog('arguments['+ j+']: ');consolelog(arguments[j]);
- // }
- var startInclusive, endExclusive, callback;
-
- var arg = arguments;
- var len = arg.length;
- var l = this.length;
- switch(len){
- case 0:
- this.debug('each called without arguments!!!');
- return;
- case 1:
- //callback = arg[0];
- startInclusive = 0;
- endExclusive = l;
- break;
- case 2:
- if(arg[0] >= l){
- return;
- }
- startInclusive = arg[0]=== undefined ? 0 : arg[0];
- endExclusive = l;
- //callback = arg[len-1];
- break;
- default:
- startInclusive = arg[0]=== undefined ? 0 : arg[0];
- endExclusive = arg[1]=== undefined ? l : arg[1];
- //callback = arg[len-1];
- }
- callback = arg[len-1];
- if(!(callback instanceof Function)){
- this.debug('callback NOT a function!!!');
- return;
- }
- var me =this.toArray();
- for(var i = startInclusive; i<endExclusive; i++){
- callback(i,me[i]);
- }
-
- },
-
- //clears the array and the events associated to it, ie removes all its elements and calls unbind(). Returns the array of the removed elements
- clear: function(){
- this.unbind();
- var me = this.toArray();
- var l = me.length;
- this.length = 0;
- if(l==0){
- return [];
- }
- return me.splice(0,l);
- },
- //moves the element from position [from] to position [to]. Shifts all elements
- //from position [to] (inclusive) of one position. Note that the elemnt at position from is first removed
- //and then inserted at position to. Therefore,
- //if to==from+1 the element is not moved. Returns from if the element
- //is not moved, i.e. either in the case above, or when:
- //1) from or to are not integers or from or to are lower than zero or greater than the array length.
- //in any other case, returns the index of the element moved, which is not necessarily to:
- //It is, if to<from, otherwise (to>from+1) is to-1
- move : function(from, to){
- var pInt = parseInt;
- if(pInt(from)!==from || pInt(to)!==to){
- return from;
- }
- var me =this.toArray();
- var len = me.length;
- if((from<0 || from>len)||(to<0 || to>len)){
- return from;
- }
- //if we moved left to right, the insertion index is actually
- //newIndex-1, as we must also consider the removal of the object at index from
- if(to>from){
- to--;
- }
- if(from != to){
- var elm = me.splice(from,1)[0];
- me.splice(to,0,elm);
- }
- return to;
- }
-});
-
-
-/*
- * Sets a "tab look" on some elements of the page. Takes at least 3 arguments, at most 5:
- * 1st argument: an array (or a jquery object) of html elements, ususally anchors, representing the tabs
- * 2nd argument: an array (or a jquery object) of html elements, ususally divs, representing the containers to be shown/hidden when
- * clicking the tabs. The n-th tab will set the n-th container to visible, hiding the others. So order is important. Note that if tabs
- * or container are jQuery objects, the html elements inside them are sorted according to the document order. That's why tabs and
- * container can be passed also as javascript arrays, so that the binding n-th tab -> n-th container can be decided by the user
- * regardeless on how elements are written on the page, if already present
- * 3rd argument: the selected index. If missing it defaults to zero.
- * 4th argument: selectedtab class. Applies to the selected tab after click of one tab. If missing, nothing is done
- * 5th argument the unselectedtab class. Applies to all tabs not selected after click of one tab. If missing, nothing is done
- *
- * NOTE: The last 2 arguments are mostly for customizing the tab "visual look", as some css elements (eg, (position, top, zIndex)
- * are set inside the code and cannot be changed, as they are mandatory to let tab anchor behave like desktop application tabs. Note also
- * that every tab container is set to 'visible' by means of jQuery.show()
- *
- * Examples:
- * setUpPlayerTabs([jQuery('#tab1),jQuery('#tab1)], [jQuery('#div1),jQuery('#div2)], 1);
- * sets the elements with id '#tab1' and '#tab2' as tab and assign the click events to them so that clicking tab_1 will show '#div_1'
- * (and hide '#div2') and viceversa for '#tab2'. The selected index will be 1 (second tab '#tab2')
-*/
-function setUpPlayerTabs() {//called from within controller.js once all markers have been loaded.
- //this is because we need all divs to be visible to calculate size. selIndex is optional, it defaults to 0
- //
-
- var $J = jQuery;
- var tabs_ = arguments[0];
- var divs_ = arguments[1]; //they might be ctually any content, div is a shoertand
-
- //converting arguments to array: tabs
- var tabs=[];
- if(tabs_ instanceof $J){
- tabs_.each(function(i,elm){
- tabs.push(elm);
- });
- }else{
- tabs = tabs_;
- }
- //set the overflow property of the parent tab to visible, otherwise scrollbars are displayed
- //and the trick of setting position:relative+top:1px+zIndices (see css) doesnt work)
- $J(tabs).each(function(i,tab){
- var t = $J(tab).attr('href','#');
- t.show(); //might be hidden
- //set necessary style for the tab appearence:
- var overflow = t.parent().css('overflow');
- if(overflow && overflow != 'visible'){
- t.parent().css('overflow','visible');
- }
- });
- //converting arguments to array: divs
- var divs=[];
- if(divs_ instanceof $J){
- divs_.each(function(i,elm){
- divs.push(elm);
- });
- }else{
- divs = divs_;
- }
-
- //reading remaing arguments (if any)
- var selIndex = arguments.length>2 ? arguments[2] : 0;
- var selectedTabClass = arguments.length>3 ? arguments[3] : undefined;
- var unselectedTabClass = arguments.length>4 ? arguments[4] : undefined;
-
- //function to be associate to every click on the tab (see below)
- var tabClicked = function(index) {
- for(var i=0; i<tabs.length; i++){
- var t = $J(tabs[i]);
-
- var div = $J(divs[i]);
- // consolelog(t.attr('id')+' is '+(i==index ? 'showing ' : 'hiding ')+div.attr('id'));
- var addClass = i==index ? selectedTabClass : unselectedTabClass;
- var removeClass = i==index ? unselectedTabClass : selectedTabClass;
- if(removeClass){
- t.removeClass(removeClass);
- }
- if(addClass){
- t.addClass(addClass);
- }
-
- //relevant css. Will override any css set in stylesheets
- t.css({
- 'position':'relative',
- 'top':'1px',
- 'zIndex': (i==index ? '10' : '0')
- });
-
- if(i===index){
- div.fadeIn('slow');
- }else{
- div.hide();
- }
- }
- };
-
- //bind clicks on tabs to the function just created
- for (var i=0;i<tabs.length;i++){
- // introduce a new scope (round brackets)
- //otherwise i is retrieved from the current scope and will be always equal to tabs.length
- //due to this loop
- (function(tabIndex){
- $J(tabs[i]).click(function(){
- tabClicked(tabIndex);
- return false;//returning false avoids scroll of the anchor to the top of the page
- });
- })(i);
- }
-
- //select the tab
- $(tabs[selIndex]).trigger("click");
-}
\ No newline at end of file
{% block extra_javascript %}
<script src="{% url telemeta-js "swfobject.js" %}" type="text/javascript"></script>
-<script src="{% url telemeta-timeside "src/playlist.js" %}" type="text/javascript"></script>
+<script src="{% url telemeta-js "popupdiv.js" %}" type="text/javascript"></script>
+<script src="{% url telemeta-js "playlist.js" %}" type="text/javascript"></script>
<script>
var setupPlaylist = function(){
{% if user.is_authenticated %}
{% if item.file %}
<!--<script src="{% url telemeta-js "wz_jsgraphics.js" %}" type="text/javascript"></script>-->
-<script src="{% url telemeta-js "soundmanager2-nodebug-jsmin.js" %}" type="text/javascript"></script>
+<script src="{% url telemeta-timeside "js/soundmanager2-nodebug-jsmin.js" %}" type="text/javascript"></script>
<script src="{% url telemeta-js "popupdiv.js" %}" type="text/javascript"></script>
<script src="{% url telemeta-js "playlist.js" %}" type="text/javascript"></script>
<script type="text/javascript">
- soundManager.url = '{% url telemeta-swf "./" %}';
+ //soundManager.url = '{% url telemeta-swf "./" %}';
+ soundManager.url = "{% url telemeta-timeside "swf/" %}";
soundManager.flashVersion = 9;
soundManager.useMovieStar = true; // enable MP4/M4A/AAC
soundManager.debugMode = true;
}
//warn on soundmanager error:
soundManager.onerror = function() {
- playerError('SoundManager error. If your browser does not support HTML5, flash (version 9+) must be installed.\nIf it is the case, try to:\n - Reload the page\n - Empty the cache (see browser preferences) and reload the page\n - Restart the browser');
+ playerError('SoundManager error. If your browser does not support HTML5, Flash player (version 9+) must be installed.\nIf flash is installed, try to:\n - Reload the page\n - Empty the cache (see browser preferences) and reload the page\n - Restart the browser');
};
setTimeout(function(){
visualizers["{{v.name}}"] = "{% url telemeta-item-visualize item.public_id,v.id,"WIDTH","HEIGHT" %}";
{% endfor %}
- var scripts = ["{% url telemeta-js "wz_jsgraphics.js" %}", "{% url telemeta-timeside "src/timeside.js" %}","{% url telemeta-timeside "src/playerLoader.js" %}"];
+ var scripts = ["{% url telemeta-timeside "js/wz_jsgraphics.js" %}", "{% url telemeta-timeside "js/timeside.js" %}","{% url telemeta-timeside "js/playerLoader.js" %}"];
jQuery(window).ready(function(){
//if soundmanager is ready, the callback is executed immetiately