YAHOO.ympyui.util.Dom.setStyles = function(el, styles) {
	for (var i in styles) {
		YAHOO.ympyui.util.Dom.setStyle(el, i, styles[i]);
	}
};

/**
*/
var CookieCutter = function(options) {};
CookieCutter.prototype = {
	
	/**
	*/
	get: function(key) {
		var start = 0, end = 0;
		if (key && (document.cookie.length > 0)) {
			start = document.cookie.indexOf(key + '=');
			if (start != -1) {
				start = start + key.length+1; 
				end = document.cookie.indexOf(';', start);
				if (end == -1) {
					end = document.cookie.length;
				}
				return unescape(document.cookie.substring(start, end));
			} 
		}
		return '';
	},
	
	/**
	*/
	set: function(key, value, expiredays) {
		var exdate = new Date();
		exdate.setDate(exdate.getDate() + expiredays);
		document.cookie = key + '=' + escape(value) + ((expiredays == null) ? '' : ';expires=' + exdate.toGMTString() + ';path=/;');
	},
	
	/**
	*/
	check: function(key) {
		var cookie = this.get(key);
		return (cookie && ((cookie != null) && (cookie != ''))) ? true : false;
	}
	
};


function utf8_encode ( argString ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // +   bugfixed by: Ulrich
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'

    var string = (argString+''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");

    var utftext = "";
    var start, end;
    var stringl = 0;

    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;

        if (c1 < 128) {
            end++;
        } else if (c1 > 127 && c1 < 2048) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }

    if (end > start) {
        utftext += string.substring(start, string.length);
    }

    return utftext;
}
//
function md5 (str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: md5('Kevin van Zonneveld');
    // *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'

    var xl;

    var rotateLeft = function (lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    };

    var addUnsigned = function (lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    };

    var _F = function (x,y,z) { return (x & y) | ((~x) & z); };
    var _G = function (x,y,z) { return (x & z) | (y & (~z)); };
    var _H = function (x,y,z) { return (x ^ y ^ z); };
    var _I = function (x,y,z) { return (y ^ (x | (~z))); };

    var _FF = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _GG = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _HH = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _II = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var convertToWordArray = function (str) {
        var lWordCount;
        var lMessageLength = str.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=new Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    };

    var wordToHex = function (lValue) {
        var wordToHexValue="",wordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            wordToHexValue_temp = "0" + lByte.toString(16);
            wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length-2,2);
        }
        return wordToHexValue;
    };

    var x=[],
        k,AA,BB,CC,DD,a,b,c,d,
        S11=7, S12=12, S13=17, S14=22,
        S21=5, S22=9 , S23=14, S24=20,
        S31=4, S32=11, S33=16, S34=23,
        S41=6, S42=10, S43=15, S44=21;

    str = this.utf8_encode(str);
    x = convertToWordArray(str);
    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
    
    xl = x.length;
    for (k=0;k<xl;k+=16) {
        AA=a; BB=b; CC=c; DD=d;
        a=_FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=_FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=_FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=_FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=_FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=_FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=_FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=_FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=_FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=_FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=_FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=_FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=_FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=_FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=_FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=_FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=_GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=_GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=_GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=_GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=_GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=_GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=_GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=_GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=_GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=_GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=_GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=_GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=_GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=_GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=_GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=_GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=_HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=_HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=_HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=_HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=_HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=_HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=_HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=_HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=_HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=_HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=_HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=_HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=_HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=_HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=_HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=_HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=_II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=_II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=_II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=_II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=_II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=_II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=_II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=_II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=_II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=_II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=_II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=_II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=_II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=_II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=_II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=_II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=addUnsigned(a,AA);
        b=addUnsigned(b,BB);
        c=addUnsigned(c,CC);
        d=addUnsigned(d,DD);
    }

    var temp = wordToHex(a)+wordToHex(b)+wordToHex(c)+wordToHex(d);

    return temp.toLowerCase();
}

var MD5 = md5;

// JavaScript Document


/**
Yahoo Media Player - trackFocus extension

Focuses the currently playing track

@author: Eric Fehrenbacher
@company: Yahoo!
*/
var TrackFocus = function() {
    
    // reference to YMP
    this.player = YAHOO.MediaPlayer;
    
    // create playlist reference
    this.playlist = YAHOO.mediaplayer.Controller.playlistmanager.playlistArray;
    
    //
    this.init();
    
};
TrackFocus.create = function(args) {
    YAHOO.mediaplayer.TrackFocus = new TrackFocus(args[0]);
    return YAHOO.mediaplayer.TrackFocus;
};
TrackFocus.attachElement = 'ymp-tray-list';
TrackFocus.prototype = {
    
    /**
    Attach some handlers for track play
    */
    init: function() {
        this.player.onTrackStart.subscribe(this.onPlay, this, true);
    },
    
    /**
    */
    onPlay: function(track) {
        
        var trackRegion = YAHOO.ympyui.util.Dom.getRegion(YAHOO.ympyui.util.Dom.get(track.mediaObject.id));
        var trackList = YAHOO.ympyui.util.Dom.get(TrackFocus.attachElement);
        var trackListRegion = YAHOO.ympyui.util.Dom.getRegion(trackList);
        var scrollTop = Math.abs((trackRegion.top - trackListRegion.top) + trackList.scrollTop);
        
        new YAHOO.ympyui.util.Scroll(trackList, { scroll: { to: [0, scrollTop] } }, 1, YAHOO.ympyui.util.Easing.easeOut).animate();
        
    }
    
};

/**
*/
(typeof YAHOO != 'undefined') && YAHOO.ympyui.util.Event.onAvailable(TrackFocus.attachElement, TrackFocus.create, TrackFocus);

/*    JavaScript Document

Yahoo Media Player - resumeTrack extension

Enables resuming of tracks from the last seek position.

@author: Eric Fehrenbacher
@company: Yahoo!
@version 0.1.2
*/
var TrackResume = function() {
    
    // reference to YMP
    this.player = YAHOO.MediaPlayer;
    
    // coookie handler
    this.cookie = new CookieCutter();
    
    // just some setup options
    this.config = {
        volume: this.player.getVolume(),
        elapsed: 0,
        duration: 0,
        token: '',
        paused: false,
        cookieCrumb: {
            volume   : 'ympVOL',
            paused   : 'ympPAU',
            elapsed  : 'ympTET',
            duration : 'ympTDR',
            token    : 'ympTTK'
        }
    };
    
    // reference to the currently playing track
    this.track = null;
    
    // keep the volume if we are resuming from another page
    this.volume = this.cookie.get(this.config.cookieCrumb.volume) || this.config.volume;
    this.volumeStack = [];
        
    // elapsed time of the currently playing track
    this.elapsed = this.cookie.get(this.config.cookieCrumb.elapsed) || this.config.elapsed;
    
    // total time of the currently playing track
    this.duration = this.cookie.get(this.config.cookieCrumb.duration) || this.config.duration;
    
    // md5 hash of token
    // we use md5 to keep this cookie size down to 120 bits and to guarantee the track is unique
    this.token = this.cookie.get(this.config.cookieCrumb.token) || this.config.token;
    
    // was the track paused when we left the player last time
    this.paused = (this.cookie.get(this.config.cookieCrumb.paused) == 1) ? true : this.config.paused;
    
    // 
    this.init();
    
};
TrackResume.create = function(args) {
    YAHOO.mediaplayer.TrackResume = new TrackResume(args);
    return YAHOO.mediaplayer.TrackResume;
};
TrackResume.prototype = {
    
    /**
    Gets fired during the construction of the object
    @method init
    @param {Object} options
    */
    init: function(options) {
        
        // adjust the volume to it's previous level
        this.adjustVolume();
        
        // track hash of active track when play is clicked
        this.player.onTrackStart.subscribe(this.onPlay, this, true);
        
        // track hash of active track when pausing
        this.player.onTrackPause.subscribe(this.onPause, this, true);
        
        // track elapsed time of active track
        this.player.onProgress.subscribe(this.onProgress, this, true);
        
        // handle resume play
        this.player.onMediaUpdate.subscribe(this.onUpdate, this, true);
        
    },
    
    /**
    @method play
    */
    play: function(track, elapsed) {
        this.updateSeekPosition();
        track = track || this.track;
        elapsed = elapsed || this.elapsed;
        this.player.play(track, elapsed);
    },
    
    /**
    @method pause
    */
    pause: function(track, elapsed) {
        track = track || this.track;
        elapsed = elapsed || this.elapsed;
        // reduce the volume before we play so that no one here's the brief noise
        var volume = volume = this.player.getVolume();
        this.player.setVolume(0);
        this.play(track, elapsed);
        /*
        this is a total hack :)
        
        because we don't have any exposed methods for setting the seek time of the track
        except for the 'play' method, we have to actually 'play' the track and then 'pause' it.
        the problem with this is that the 'play' method fires asyncronously which means that
        calling the 'pause' method following the 'play' method will most likely fail due to the
        fact that the 'play' method is not finished and cancels the 'pause'
        the solution here is to use an interval to execute the pause method only after the
        state of the player is in 'play' mode.
        a more legitimate solution would be to have a method exposed that allows us to set the
        seek position in any state. so even if the track is paused the player seeks to the
        requested position
        */
        this.playCheck = YAHOO.ympyui.lang.later(100, this, function(volume) {
            if (this.player.getPlayerState() == 2) {
                this.playCheck.cancel();
                this.updateSeekPosition();
                this.player.pause();
                this.player.setVolume(volume);
            }
        }, [volume], true);
    },
    
    /**
    */
    setVolume: function() {
        
        this.volume = this.player.getVolume();
        
        var saveVolume = true;
        
        if (this.volumeStack.length < 3) {
            saveVolume = false;
        } else {
            for (var i = 0; i < this.volumeStack.length; i++) {
                if (this.volumeStack[i] != this.volume) {
                    saveVolume = false;
                }
            }
        }
        this.volumeStack.splice(0, 0, this.volume);
        this.volumeStack.length = 3;
        
        if (saveVolume) {
            this.cookie.set(this.config.cookieCrumb.volume, this.volume, 90);
        }
        
    },
    
    /**
    */
    adjustVolume: function(volume) {
        this.volume = volume || this.volume;
        this.player.setVolume(this.volume);
    },
    
    /**
    @method setCurrentTrack
    @param {Object} track
    */
    setCurrentTrack: function(track) {
        this.track = track.mediaObject;
        var token = MD5(this.track.token);
        this.elapsed = (token != this.token) ? 0 : this.elapsed;
        this.token = token;
        this.cookie.set(this.config.cookieCrumb.token, token, 90);
    },
    
    /**
    @method setTrackTime
    @param {Object} options
    */
    setTrackTime: function(options) {
        if (options.duration > 0) {
            this.elapsed = options.elapsed;
            this.cookie.set(this.config.cookieCrumb.elapsed, options.elapsed, 90);
            this.cookie.set(this.config.cookieCrumb.duration, options.duration, 90);
            return true;
        }
        return false;
    },
    
    /**
    @method setPausedState
    @param {Boolean} state Wheather YMP is currently paused. true || false
    */
    setPausedState: function(state) {
        this.paused = state;
        this.cookie.set(this.config.cookieCrumb.paused, (this.paused ? 1 : 0), 90);
    },
    
    /**
    @method updateSeekPosition
    */
    updateSeekPosition: function() {
        YAHOO.mediaplayer.TrackSeek && YAHOO.mediaplayer.TrackSeek.onProgress({elapsed: this.elapsed, duration: this.duration});
    },
    
    /**
    Event handler for 'play'
    @method onPlay
    @param {Object} track
    */
    onPlay: function(track) {
        //console.log("onPlay::this.elapsed",this.elapsed);
        this.setCurrentTrack(track);
        this.setPausedState(false);
        this.play(this.track, this.elapsed);
    },
    
    /**
    Event handler
    This function tracks the elapsed time of the currently playing track
    @method onProgress
    @param {Object} options
    */
    onProgress: function(options) {
        //console.log("onProgress::this.elapsed",this.elapsed);
        this.setTrackTime(options);
        this.setVolume();
    },
    
    /**
    Event handler for 'pause'
    @method onPause
    @param {Object} track
    */
    onPause: function(track) {
        this.setPausedState(true);
    },
    
    /**
    Event handler for when a mediaObject exists and is updated
    */
    onUpdate: function(mediaObject) {
        if (MD5(mediaObject.token) == this.token) {
            this.track = mediaObject;
            if (this.paused) {
                this.pause(this.track, this.elapsed);
            } else {
                this.play(this.track, this.elapsed);
            }
        }
    }
    
};

/*
This creates a new TrackResume object and attaches to the MediaPlayer
*/
(typeof YAHOO != 'undefined') && YAHOO.MediaPlayer.onAPIReady.subscribe(TrackResume.create);

// JavaScript Document

/**
Yahoo Media Player - TrackSeek extension

Displays a visual position indicator and allows the user to control the seek position

@author: Eric Fehrenbacher
@company: Yahoo!
@version 0.1.2
*/
var TrackSeek = function() {
    
    // reference to YMP
    this.player = YAHOO.MediaPlayer;
    
    // position of the left edge of the slider relative to the page
    this.seekControlX = 0;
    
    // reference to the currently playing track
    this.track = null;
    
    // the elapsed time of the currently playing track
    this.elapsed = 0;
    
    // the duration of the currently playing track
    this.duration = 0;
    
    // tells us if the track is playing or not
    this.paused = true;
    
    // tells us if we are dragging the slider or not
    this.dragging = false;
    
    // tracks the percentage of movement from the left edge of the control
    this.position = 0;
    
    // setup of delegates, subscribers, and UI
    this.init();
    
};
TrackSeek.create = function(args) {
    YAHOO.mediaplayer.TrackSeek = new TrackSeek(args[0]);
    return YAHOO.mediaplayer.TrackSeek;
};
TrackSeek.attachElement = 'ymp-meta-album-title';
TrackSeek.prototype = {
    
    /**
    Fires during the contruction of this object
    @method init
    */
    init: function() {
        
        // 
        this.setupUI();
        
        // some ui specs
        this.ui = {
            // define the total width
            width: function() {
                return parseInt(YAHOO.ympyui.util.Dom.getStyle('ymp-seek', 'width'));
            },
            // define the left edge
            left: function() {
                return Math.round(parseInt(YAHOO.ympyui.util.Dom.getStyle('ymp-seek-thumb', 'width')) / 2);
            },
            // define the right edge
            right: function() {
                return this.width() - this.left();
            }
        };
        
        // initialize default seek position...
        this.onPositionChange(1);
        
        // handle mousedown on the position control
        YAHOO.ympyui.util.Event.on('ymp-seek', 'mousedown', this.seekStartDrag, this, true);
        
        // handle clicks on the position control
        YAHOO.ympyui.util.Event.on('ymp-seek', 'click', this.stopEvent);
        
        // track hash of active track when play is clicked
        this.player.onTrackStart.subscribe(this.onPlay, this, true);
        
        // update position based on elapsed time of active track
        this.player.onProgress.subscribe(this.onProgress, this, true);
        
        //
        this.player.onTrackPause.subscribe(this.onPause, this, true);
        
        // 
        YAHOO.ympyui.util.Event.addListener(['ymp-next','ymp-prev'], 'click', function() {
            this.onPositionChange(1);
        }, this, true);
        
    },
    
    /**
    We just setup the GUI here.
    @method setupUI
    */
    setupUI: function() {
        
        // grab the volume control
        var displaced = document.getElementById(TrackSeek.attachElement);
        YAHOO.ympyui.util.Dom.setStyles(displaced, {display: 'none'});
        
        // create slider
        var seekContainer = document.createElement('div');
        seekContainer.id = 'ymp-seek';
        YAHOO.ympyui.util.Dom.setStyles(seekContainer, {
            position: 'absolute',
            width: '190px',
            height: '15px',
            zIndex: '2'
        });
        displaced.parentNode.insertBefore(seekContainer, displaced);
        /*
        // we need to be notified when the timer changes size so we can readjust
        // or better yet, why do we need to readjust the timer should be doing that
        var seekRegion = YAHOO.ympyui.util.Dom.getRegion(seekContainer);
        var seekWidth = seekRegion.right - seekRegion.left;
        YAHOO.ympyui.util.Dom.setStyle(seekContainer, 'width', (seekWidth - 10) + 'px');
        */
        
        var seekCover = document.createElement('div');
        seekCover.id = 'ymp-seek-cover';
        YAHOO.ympyui.util.Dom.setStyles(seekCover, {
            display: 'block',
            position: 'absolute',
            overflow: 'hidden',
            top: '5px',
            left: '0px',
            width: '100%',
            height: '4px',
            backgroundColor: '#D6D6D6'
        });
        seekContainer.appendChild(seekCover);
        
        var seekCoverElapsed = document.createElement('div');
        seekCoverElapsed.id = 'ymp-seek-cover-elapsed';
        YAHOO.ympyui.util.Dom.setStyles(seekCoverElapsed, {
            display: 'block',
            position: 'absolute',
            visibility: 'hidden',
            overflow: 'hidden',
            top: '0px',
            left: '0px',
            width: '100%',
            height: '4px',
            backgroundColor: '#929392'
        });
        seekCover.appendChild(seekCoverElapsed);
        YAHOO.ympyui.util.Event.addListener(seekContainer, 'mouseover', function() {
            this.style.backgroundColor = '#CEFD0D';
        }, seekCoverElapsed, true);
        YAHOO.ympyui.util.Event.addListener(seekContainer, 'mouseout', function() {
            this.style.backgroundColor = '#929392';
        }, seekCoverElapsed, true);
        
        var seekThumb = document.createElement('div');
        seekThumb.id = 'ymp-seek-thumb';
        YAHOO.ympyui.util.Event.addListener(seekThumb, 'mouseover', function() {
            this.style.borderColor = '#CEFD0D';
        }, seekThumb, true);
        YAHOO.ympyui.util.Event.addListener(seekThumb, 'mouseout', function() {
            this.style.borderColor = '#DDDDDD #B2B2B2 #B2B2B2 #DDDDDD';
        }, seekThumb, true);
        YAHOO.ympyui.util.Dom.setStyles(seekThumb, {
            display: 'block',
            position: 'absolute',
            overflow: 'hidden',
            top: '3px',
            left: '0px',
            width: '4px',
            height: '7px',
            cursor: 'pointer',
            backgroundColor: '#E9E8E8',
            borderWidth: '1px',
            borderStyle: 'solid',
            borderColor: '#DDDDDD #B2B2B2 #B2B2B2 #DDDDDD'
        });
        seekContainer.appendChild(seekThumb);
        
    },
    
    /**
    Provides a shortcut for stopping an event
    @method stopEvent
    @param {DOMEvent} evt
    */
    stopEvent: function(evt) {
        YAHOO.ympyui.util.Event.stopEvent(evt);
    },
    
    /**
    Event handler for when the user starts to drag the position slider
    @method seekStartDrag
    @param {Object} eventObj The HTML event object.
    */
    seekStartDrag: function(evt) {
        if (this.paused) {
            return;
        }
        
        this.stopEvent(evt);
        this.dragging = true;
        
        // get the current position of the left edge of the slider relative to the page
        this.seekControlX = YAHOO.ympyui.util.Dom.getX('ymp-seek');
        
        // notify everyone about position change
        this.notifySeekChange(evt);
        
        YAHOO.ympyui.util.Event.on(document, 'mousemove', this.notifySeekChange, this, true);
        YAHOO.ympyui.util.Event.on(document, 'mouseup', this.seekMouseUp, this, true);  
    },
    
    /**
    Event handler when the user releases the mouse after dragging the position slider. Remove the appropriate event listeners.
    @method seekMouseUp
    @param {Object} eventObj The HTML event object
    */                                                    
    seekMouseUp: function(evt) {
        this.dragging = false;
        this.stopEvent(evt);
        this.elapsed = this.duration - (this.position * this.duration);
        
        YAHOO.ympyui.util.Event.removeListener(document, 'mousemove', this.notifySeekChange);
        YAHOO.ympyui.util.Event.removeListener(document, 'mouseup', this.seekMouseUp);
        
        if (this.paused) {
            
            this.player.pause();
            return;
            
            // reduce the volume before we play so that no one here's the brief noise
            var volume = this.player.getVolume();
            this.player.setVolume(0);
            this.player.play(this.track, this.elapsed);
            /*
            it would be nice to be able to move the position while paused, but...
            for some reason this hack won't work here, haven't figured out why yet
            */
            /*
            this.playCheck = YAHOO.ympyui.lang.later(100, this, function(volume) {
                if (this.player.getPlayerState() == 2) {
                    this.playCheck.cancel();
                    //this.updateSeekPosition();
                    this.onProgress({elapsed: this.elapsed, duration: this.duration})
                    console.log("asddddddddd");
                    this.player.pause();
                    //this.player.setVolume(volume);
                }
            }, [volume], true);
            */
        } else {
            this.player.play(this.track, this.elapsed);
        }
        
    },
    
    /**
    Get the right requested position based on where the user has dragged the position slider and then fire the position change request event for that position
    @method notifySeekChange
    @param {DOMEvent} evt
    */
    notifySeekChange: function(evt) {
        this.stopEvent(evt);
        var newMouseX = YAHOO.ympyui.util.Event.getPageX(evt);
        var xDiff = (newMouseX - this.seekControlX);
        xDiff -= 0;
        var thumbLeft;
        
        // calculate position percentage (0 - 1) and fire the event to notify whoever is listening
        if ((xDiff >= this.ui.left()) && (xDiff < this.ui.right())) {
            // mouse is within the constraint
            thumbLeft = xDiff - this.ui.left();
        } else if (xDiff >= this.ui.right()) {
            // mouse is way below the position, so cap the thumb at the maximum x it is allowed to go
            thumbLeft = this.ui.right() - this.ui.left();
        } else if (xDiff < this.ui.left()) {
            // mouse is way above the position, so cap the x at 0
            thumbLeft = 0;
        }
        
        // percentage of movement from the left edge of the control
        this.position = 1 - (thumbLeft / (this.ui.right() - this.ui.left()));
        
        this.onPositionChange(this.position);
    },
    
    /**
    Event handler for onPlay. Record the track as a mediaObject for reference.
    @method onPlay
    @param {Object} track The currently playing track
    */
    onPlay: function(track) {
        this.paused = false;
        this.track = track.mediaObject;
    },
    
    /**
    This function updates the seek position based on the elapsed time of the currently playing track
    @method onProgress
    @param {Object} options
    */
    onProgress: function(options) {
        this.elapsed = options.elapsed;
        this.duration = options.duration || (YAHOO.mediaplayer.TrackResume && YAHOO.mediaplayer.TrackResume.duration) || 0;
        if (!this.dragging && (this.duration != 0)) {
            var thumbLeft;
            
            // convert thumb position into seek position
            var xDiff = Math.ceil((Math.ceil(this.elapsed) * this.ui.right() - this.ui.left()) / Math.ceil(this.duration));
            xDiff -= 0;
            
            // calculate position percentage (0 - 1) and fire the event to notify whoever is listening
            if ((xDiff >= this.ui.left()) && (xDiff < this.ui.right())) {
                // seek is within the constraint
                thumbLeft = xDiff - this.ui.left();
            } else if (xDiff >= this.ui.right()) {
                // seek is way below the position, so cap the thumb at the maximum x it is allowed to go
                thumbLeft = this.ui.right() - this.ui.left();
            } else if (xDiff < this.ui.left()) {
                // seek is way above the position, so cap the x at 0
                thumbLeft = 0;
            }
            
            // percentage of seek position from the left edge of the controle
            var position = 1 - (thumbLeft / (this.ui.right() - this.ui.left()));
            
            this.onPositionChange(position);
        }
    },
    
    /**
    Event handler for onPlay. Record the track as a mediaObject for reference.
    @method onPause
    @param {Object} track The currently playing track
    */
    onPause: function(track) {
        this.paused = true;
    },
    
    /**
    Event handler for onPositionChange. If the seek position is changed through API update the view appropriately
    @method onPositionChange
    @param {Object} seek The new position [0-1]
    */
    onPositionChange: function(position) {
        
        // convert seek position into thumb position
        var thumbLeft = (1 - position) * (this.ui.right() - this.ui.left());
        
        // adjust seek thumb position
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-thumb', 'left', thumbLeft + 'px');
        
        // adjust elapsed position
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-cover-elapsed', 'visibility', 'visible');
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-cover-elapsed', 'left', -((this.ui.right() - this.ui.left()) - thumbLeft) + 'px');
        
    }
    
};

/**
This creates a new TrackSeek object and attaches to the MediaPlayer
*/
(typeof YAHOO != 'undefined') && YAHOO.ympyui.util.Event.onAvailable(TrackSeek.attachElement, TrackSeek.create, TrackSeek);

