rob@100: // ---------------------------------------------------------------------------- rob@100: // Buzz, a Javascript HTML5 Audio library rob@100: // v 1.0.4 beta rob@100: // Licensed under the MIT license. rob@100: // http://buzz.jaysalvat.com/ rob@100: // ---------------------------------------------------------------------------- rob@100: // Copyright (C) 2011 Jay Salvat rob@100: // http://jaysalvat.com/ rob@100: // ---------------------------------------------------------------------------- rob@100: // Permission is hereby granted, free of charge, to any person obtaining a copy rob@100: // of this software and associated documentation files ( the "Software" ), to deal rob@100: // in the Software without restriction, including without limitation the rights rob@100: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell rob@100: // copies of the Software, and to permit persons to whom the Software is rob@100: // furnished to do so, subject to the following conditions: rob@100: // rob@100: // The above copyright notice and this permission notice shall be included in rob@100: // all copies or substantial portions of the Software. rob@100: // rob@100: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR rob@100: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, rob@100: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE rob@100: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER rob@100: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, rob@100: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN rob@100: // THE SOFTWARE. rob@100: // ---------------------------------------------------------------------------- rob@100: rob@100: var buzz = { rob@100: defaults: { rob@100: autoplay: false, rob@100: duration: 5000, rob@100: formats: [], rob@100: loop: false, rob@100: placeholder: '--', rob@100: preload: 'metadata', rob@100: volume: 80 rob@100: }, rob@100: types: { rob@100: 'mp3': 'audio/mpeg', rob@100: 'ogg': 'audio/ogg', rob@100: 'wav': 'audio/wav', rob@100: 'aac': 'audio/aac', rob@100: 'm4a': 'audio/x-m4a' rob@100: }, rob@100: sounds: [], rob@100: el: document.createElement( 'audio' ), rob@100: rob@100: sound: function( src, options ) { rob@100: options = options || {}; rob@100: rob@100: var pid = 0, rob@100: events = [], rob@100: eventsOnce = {}, rob@100: supported = buzz.isSupported(); rob@100: rob@100: // publics rob@100: this.load = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.load(); rob@100: return this; rob@100: }; rob@100: rob@100: this.play = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.play(); rob@100: return this; rob@100: }; rob@100: rob@100: this.togglePlay = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: if ( this.sound.paused ) { rob@100: this.sound.play(); rob@100: } else { rob@100: this.sound.pause(); rob@100: } rob@100: return this; rob@100: }; rob@100: rob@100: this.pause = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.pause(); rob@100: return this; rob@100: }; rob@100: rob@100: this.isPaused = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.paused; rob@100: }; rob@100: rob@100: this.stop = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.setTime( this.getDuration() ); rob@100: this.sound.pause(); rob@100: return this; rob@100: }; rob@100: rob@100: this.isEnded = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.ended; rob@100: }; rob@100: rob@100: this.loop = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.loop = 'loop'; rob@100: this.bind( 'ended.buzzloop', function() { rob@100: this.currentTime = 0; rob@100: this.play(); rob@100: }); rob@100: return this; rob@100: }; rob@100: rob@100: this.unloop = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.removeAttribute( 'loop' ); rob@100: this.unbind( 'ended.buzzloop' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.mute = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.muted = true; rob@100: return this; rob@100: }; rob@100: rob@100: this.unmute = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.muted = false; rob@100: return this; rob@100: }; rob@100: rob@100: this.toggleMute = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.muted = !this.sound.muted; rob@100: return this; rob@100: }; rob@100: rob@100: this.isMuted = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.muted; rob@100: }; rob@100: rob@100: this.setVolume = function( volume ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: if ( volume < 0 ) { rob@100: volume = 0; rob@100: } rob@100: if ( volume > 100 ) { rob@100: volume = 100; rob@100: } rob@100: rob@100: this.volume = volume; rob@100: this.sound.volume = volume / 100; rob@100: return this; rob@100: }; rob@100: rob@100: this.getVolume = function() { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: return this.volume; rob@100: }; rob@100: rob@100: this.increaseVolume = function( value ) { rob@100: return this.setVolume( this.volume + ( value || 1 ) ); rob@100: }; rob@100: rob@100: this.decreaseVolume = function( value ) { rob@100: return this.setVolume( this.volume - ( value || 1 ) ); rob@100: }; rob@100: rob@100: this.setTime = function( time ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.whenReady( function() { rob@100: this.sound.currentTime = time; rob@100: }); rob@100: return this; rob@100: }; rob@100: rob@100: this.getTime = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: var time = Math.round( this.sound.currentTime * 100 ) / 100; rob@100: return isNaN( time ) ? buzz.defaults.placeholder : time; rob@100: }; rob@100: rob@100: this.setPercent = function( percent ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: return this.setTime( buzz.fromPercent( percent, this.sound.duration ) ); rob@100: }; rob@100: rob@100: this.getPercent = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: var percent = Math.round( buzz.toPercent( this.sound.currentTime, this.sound.duration ) ); rob@100: return isNaN( percent ) ? buzz.defaults.placeholder : percent; rob@100: }; rob@100: rob@100: this.setSpeed = function( duration ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound.playbackRate = duration; rob@100: }; rob@100: rob@100: this.getSpeed = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.playbackRate; rob@100: }; rob@100: rob@100: this.getDuration = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: var duration = Math.round( this.sound.duration * 100 ) / 100; rob@100: return isNaN( duration ) ? buzz.defaults.placeholder : duration; rob@100: }; rob@100: rob@100: this.getPlayed = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return timerangeToArray( this.sound.played ); rob@100: }; rob@100: rob@100: this.getBuffered = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return timerangeToArray( this.sound.buffered ); rob@100: }; rob@100: rob@100: this.getSeekable = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return timerangeToArray( this.sound.seekable ); rob@100: }; rob@100: rob@100: this.getErrorCode = function() { rob@100: if ( supported && this.sound.error ) { rob@100: return this.sound.error.code; rob@100: } rob@100: return 0; rob@100: }; rob@100: rob@100: this.getErrorMessage = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: switch( this.getErrorCode() ) { rob@100: case 1: rob@100: return 'MEDIA_ERR_ABORTED'; rob@100: case 2: rob@100: return 'MEDIA_ERR_NETWORK'; rob@100: case 3: rob@100: return 'MEDIA_ERR_DECODE'; rob@100: case 4: rob@100: return 'MEDIA_ERR_SRC_NOT_SUPPORTED'; rob@100: default: rob@100: return null; rob@100: } rob@100: }; rob@100: rob@100: this.getStateCode = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.readyState; rob@100: }; rob@100: rob@100: this.getStateMessage = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: switch( this.getStateCode() ) { rob@100: case 0: rob@100: return 'HAVE_NOTHING'; rob@100: case 1: rob@100: return 'HAVE_METADATA'; rob@100: case 2: rob@100: return 'HAVE_CURRENT_DATA'; rob@100: case 3: rob@100: return 'HAVE_FUTURE_DATA'; rob@100: case 4: rob@100: return 'HAVE_ENOUGH_DATA'; rob@100: default: rob@100: return null; rob@100: } rob@100: }; rob@100: rob@100: this.getNetworkStateCode = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return this.sound.networkState; rob@100: }; rob@100: rob@100: this.getNetworkStateMessage = function() { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: switch( this.getNetworkStateCode() ) { rob@100: case 0: rob@100: return 'NETWORK_EMPTY'; rob@100: case 1: rob@100: return 'NETWORK_IDLE'; rob@100: case 2: rob@100: return 'NETWORK_LOADING'; rob@100: case 3: rob@100: return 'NETWORK_NO_SOURCE'; rob@100: default: rob@100: return null; rob@100: } rob@100: }; rob@100: rob@100: this.set = function( key, value ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.sound[ key ] = value; rob@100: return this; rob@100: }; rob@100: rob@100: this.get = function( key ) { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: return key ? this.sound[ key ] : this.sound; rob@100: }; rob@100: rob@100: this.bind = function( types, func ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: types = types.split( ' ' ); rob@100: rob@100: var that = this, rob@100: efunc = function( e ) { func.call( that, e ); }; rob@100: rob@100: for( var t = 0; t < types.length; t++ ) { rob@100: var type = types[ t ], rob@100: idx = type; rob@100: type = idx.split( '.' )[ 0 ]; rob@100: rob@100: events.push( { idx: idx, func: efunc } ); rob@100: this.sound.addEventListener( type, efunc, true ); rob@100: } rob@100: return this; rob@100: }; rob@100: rob@100: this.unbind = function( types ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: types = types.split( ' ' ); rob@100: rob@100: for( var t = 0; t < types.length; t++ ) { rob@100: var idx = types[ t ], rob@100: type = idx.split( '.' )[ 0 ]; rob@100: rob@100: for( var i = 0; i < events.length; i++ ) { rob@100: var namespace = events[ i ].idx.split( '.' ); rob@100: if ( events[ i ].idx == idx || ( namespace[ 1 ] && namespace[ 1 ] == idx.replace( '.', '' ) ) ) { rob@100: this.sound.removeEventListener( type, events[ i ].func, true ); rob@100: delete events[ i ]; rob@100: } rob@100: } rob@100: } rob@100: return this; rob@100: }; rob@100: rob@100: this.bindOnce = function( type, func ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: var that = this; rob@100: rob@100: eventsOnce[ pid++ ] = false; rob@100: this.bind( pid + type, function() { rob@100: if ( !eventsOnce[ pid ] ) { rob@100: eventsOnce[ pid ] = true; rob@100: func.call( that ); rob@100: } rob@100: that.unbind( pid + type ); rob@100: }); rob@100: }; rob@100: rob@100: this.trigger = function( types ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: types = types.split( ' ' ); rob@100: rob@100: for( var t = 0; t < types.length; t++ ) { rob@100: var idx = types[ t ]; rob@100: rob@100: for( var i = 0; i < events.length; i++ ) { rob@100: var eventType = events[ i ].idx.split( '.' ); rob@100: if ( events[ i ].idx == idx || ( eventType[ 0 ] && eventType[ 0 ] == idx.replace( '.', '' ) ) ) { rob@100: var evt = document.createEvent('HTMLEvents'); rob@100: evt.initEvent( eventType[ 0 ], false, true ); rob@100: this.sound.dispatchEvent( evt ); rob@100: } rob@100: } rob@100: } rob@100: return this; rob@100: }; rob@100: rob@100: this.fadeTo = function( to, duration, callback ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: if ( duration instanceof Function ) { rob@100: callback = duration; rob@100: duration = buzz.defaults.duration; rob@100: } else { rob@100: duration = duration || buzz.defaults.duration; rob@100: } rob@100: rob@100: var from = this.volume, rob@100: delay = duration / Math.abs( from - to ), rob@100: that = this; rob@100: this.play(); rob@100: rob@100: function doFade() { rob@100: setTimeout( function() { rob@100: if ( from < to && that.volume < to ) { rob@100: that.setVolume( that.volume += 1 ); rob@100: doFade(); rob@100: } else if ( from > to && that.volume > to ) { rob@100: that.setVolume( that.volume -= 1 ); rob@100: doFade(); rob@100: } else if ( callback instanceof Function ) { rob@100: callback.apply( that ); rob@100: } rob@100: }, delay ); rob@100: } rob@100: this.whenReady( function() { rob@100: doFade(); rob@100: }); rob@100: rob@100: return this; rob@100: }; rob@100: rob@100: this.fadeIn = function( duration, callback ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: return this.setVolume(0).fadeTo( 100, duration, callback ); rob@100: }; rob@100: rob@100: this.fadeOut = function( duration, callback ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: return this.fadeTo( 0, duration, callback ); rob@100: }; rob@100: rob@100: this.fadeWith = function( sound, duration ) { rob@100: if ( !supported ) { rob@100: return this; rob@100: } rob@100: rob@100: this.fadeOut( duration, function() { rob@100: this.stop(); rob@100: }); rob@100: rob@100: sound.play().fadeIn( duration ); rob@100: rob@100: return this; rob@100: }; rob@100: rob@100: this.whenReady = function( func ) { rob@100: if ( !supported ) { rob@100: return null; rob@100: } rob@100: rob@100: var that = this; rob@100: if ( this.sound.readyState === 0 ) { rob@100: this.bind( 'canplay.buzzwhenready', function() { rob@100: func.call( that ); rob@100: }); rob@100: } else { rob@100: func.call( that ); rob@100: } rob@100: }; rob@100: rob@100: // privates rob@100: function timerangeToArray( timeRange ) { rob@100: var array = [], rob@100: length = timeRange.length - 1; rob@100: rob@100: for( var i = 0; i <= length; i++ ) { rob@100: array.push({ rob@100: start: timeRange.start( length ), rob@100: end: timeRange.end( length ) rob@100: }); rob@100: } rob@100: return array; rob@100: } rob@100: rob@100: function getExt( filename ) { rob@100: return filename.split('.').pop(); rob@100: } rob@100: rob@100: function addSource( sound, src ) { rob@100: var source = document.createElement( 'source' ); rob@100: source.src = src; rob@100: if ( buzz.types[ getExt( src ) ] ) { rob@100: source.type = buzz.types[ getExt( src ) ]; rob@100: } rob@100: sound.appendChild( source ); rob@100: } rob@100: rob@100: // init rob@100: if ( supported ) { rob@100: rob@100: for(var i in buzz.defaults ) { rob@100: if(buzz.defaults.hasOwnProperty(i)) { rob@100: options[ i ] = options[ i ] || buzz.defaults[ i ]; rob@100: } rob@100: } rob@100: rob@100: this.sound = document.createElement( 'audio' ); rob@100: rob@100: if ( src instanceof Array ) { rob@100: for( var j in src ) { rob@100: if(src.hasOwnProperty(j)) { rob@100: addSource( this.sound, src[ j ] ); rob@100: } rob@100: } rob@100: } else if ( options.formats.length ) { rob@100: for( var k in options.formats ) { rob@100: if(options.formats.hasOwnProperty(k)) { rob@100: addSource( this.sound, src + '.' + options.formats[ k ] ); rob@100: } rob@100: } rob@100: } else { rob@100: addSource( this.sound, src ); rob@100: } rob@100: rob@100: if ( options.loop ) { rob@100: this.loop(); rob@100: } rob@100: rob@100: if ( options.autoplay ) { rob@100: this.sound.autoplay = 'autoplay'; rob@100: } rob@100: rob@100: if ( options.preload === true ) { rob@100: this.sound.preload = 'auto'; rob@100: } else if ( options.preload === false ) { rob@100: this.sound.preload = 'none'; rob@100: } else { rob@100: this.sound.preload = options.preload; rob@100: } rob@100: rob@100: this.setVolume( options.volume ); rob@100: rob@100: buzz.sounds.push( this ); rob@100: } rob@100: }, rob@100: rob@100: group: function( sounds ) { rob@100: sounds = argsToArray( sounds, arguments ); rob@100: rob@100: // publics rob@100: this.getSounds = function() { rob@100: return sounds; rob@100: }; rob@100: rob@100: this.add = function( soundArray ) { rob@100: soundArray = argsToArray( soundArray, arguments ); rob@100: for( var a = 0; a < soundArray.length; a++ ) { rob@100: sounds.push( soundArray[ a ] ); rob@100: } rob@100: }; rob@100: rob@100: this.remove = function( soundArray ) { rob@100: soundArray = argsToArray( soundArray, arguments ); rob@100: for( var a = 0; a < soundArray.length; a++ ) { rob@100: for( var i = 0; i < sounds.length; i++ ) { rob@100: if ( sounds[ i ] == soundArray[ a ] ) { rob@100: delete sounds[ i ]; rob@100: break; rob@100: } rob@100: } rob@100: } rob@100: }; rob@100: rob@100: this.load = function() { rob@100: fn( 'load' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.play = function() { rob@100: fn( 'play' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.togglePlay = function( ) { rob@100: fn( 'togglePlay' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.pause = function( time ) { rob@100: fn( 'pause', time ); rob@100: return this; rob@100: }; rob@100: rob@100: this.stop = function() { rob@100: fn( 'stop' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.mute = function() { rob@100: fn( 'mute' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.unmute = function() { rob@100: fn( 'unmute' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.toggleMute = function() { rob@100: fn( 'toggleMute' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.setVolume = function( volume ) { rob@100: fn( 'setVolume', volume ); rob@100: return this; rob@100: }; rob@100: rob@100: this.increaseVolume = function( value ) { rob@100: fn( 'increaseVolume', value ); rob@100: return this; rob@100: }; rob@100: rob@100: this.decreaseVolume = function( value ) { rob@100: fn( 'decreaseVolume', value ); rob@100: return this; rob@100: }; rob@100: rob@100: this.loop = function() { rob@100: fn( 'loop' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.unloop = function() { rob@100: fn( 'unloop' ); rob@100: return this; rob@100: }; rob@100: rob@100: this.setTime = function( time ) { rob@100: fn( 'setTime', time ); rob@100: return this; rob@100: }; rob@100: rob@100: this.setduration = function( duration ) { rob@100: fn( 'setduration', duration ); rob@100: return this; rob@100: }; rob@100: rob@100: this.set = function( key, value ) { rob@100: fn( 'set', key, value ); rob@100: return this; rob@100: }; rob@100: rob@100: this.bind = function( type, func ) { rob@100: fn( 'bind', type, func ); rob@100: return this; rob@100: }; rob@100: rob@100: this.unbind = function( type ) { rob@100: fn( 'unbind', type ); rob@100: return this; rob@100: }; rob@100: rob@100: this.bindOnce = function( type, func ) { rob@100: fn( 'bindOnce', type, func ); rob@100: return this; rob@100: }; rob@100: rob@100: this.trigger = function( type ) { rob@100: fn( 'trigger', type ); rob@100: return this; rob@100: }; rob@100: rob@100: this.fade = function( from, to, duration, callback ) { rob@100: fn( 'fade', from, to, duration, callback ); rob@100: return this; rob@100: }; rob@100: rob@100: this.fadeIn = function( duration, callback ) { rob@100: fn( 'fadeIn', duration, callback ); rob@100: return this; rob@100: }; rob@100: rob@100: this.fadeOut = function( duration, callback ) { rob@100: fn( 'fadeOut', duration, callback ); rob@100: return this; rob@100: }; rob@100: rob@100: // privates rob@100: function fn() { rob@100: var args = argsToArray( null, arguments ), rob@100: func = args.shift(); rob@100: rob@100: for( var i = 0; i < sounds.length; i++ ) { rob@100: sounds[ i ][ func ].apply( sounds[ i ], args ); rob@100: } rob@100: } rob@100: rob@100: function argsToArray( array, args ) { rob@100: return ( array instanceof Array ) ? array : Array.prototype.slice.call( args ); rob@100: } rob@100: }, rob@100: rob@100: all: function() { rob@100: return new buzz.group( buzz.sounds ); rob@100: }, rob@100: rob@100: isSupported: function() { rob@100: return !!buzz.el.canPlayType; rob@100: }, rob@100: rob@100: isOGGSupported: function() { rob@100: return !!buzz.el.canPlayType && buzz.el.canPlayType( 'audio/ogg; codecs="vorbis"' ); rob@100: }, rob@100: rob@100: isWAVSupported: function() { rob@100: return !!buzz.el.canPlayType && buzz.el.canPlayType( 'audio/wav; codecs="1"' ); rob@100: }, rob@100: rob@100: isMP3Supported: function() { rob@100: return !!buzz.el.canPlayType && buzz.el.canPlayType( 'audio/mpeg;' ); rob@100: }, rob@100: rob@100: isAACSupported: function() { rob@100: return !!buzz.el.canPlayType && ( buzz.el.canPlayType( 'audio/x-m4a;' ) || buzz.el.canPlayType( 'audio/aac;' ) ); rob@100: }, rob@100: rob@100: toTimer: function( time, withHours ) { rob@100: var h, m, s; rob@100: h = Math.floor( time / 3600 ); rob@100: h = isNaN( h ) ? '--' : ( h >= 10 ) ? h : '0' + h; rob@100: m = withHours ? Math.floor( time / 60 % 60 ) : Math.floor( time / 60 ); rob@100: m = isNaN( m ) ? '--' : ( m >= 10 ) ? m : '0' + m; rob@100: s = Math.floor( time % 60 ); rob@100: s = isNaN( s ) ? '--' : ( s >= 10 ) ? s : '0' + s; rob@100: return withHours ? h + ':' + m + ':' + s : m + ':' + s; rob@100: }, rob@100: rob@100: fromTimer: function( time ) { rob@100: var splits = time.toString().split( ':' ); rob@100: if ( splits && splits.length == 3 ) { rob@100: time = ( parseInt( splits[ 0 ], 10 ) * 3600 ) + ( parseInt(splits[ 1 ], 10 ) * 60 ) + parseInt( splits[ 2 ], 10 ); rob@100: } rob@100: if ( splits && splits.length == 2 ) { rob@100: time = ( parseInt( splits[ 0 ], 10 ) * 60 ) + parseInt( splits[ 1 ], 10 ); rob@100: } rob@100: return time; rob@100: }, rob@100: rob@100: toPercent: function( value, total, decimal ) { rob@100: var r = Math.pow( 10, decimal || 0 ); rob@100: rob@100: return Math.round( ( ( value * 100 ) / total ) * r ) / r; rob@100: }, rob@100: rob@100: fromPercent: function( percent, total, decimal ) { rob@100: var r = Math.pow( 10, decimal || 0 ); rob@100: rob@100: return Math.round( ( ( total / 100 ) * percent ) * r ) / r; rob@100: } rob@100: };