/* Do not put anything above this line */
var $Y = YAHOO;
var $W = YAHOO.widget;
var $D = YAHOO.util.Dom;
var $E = YAHOO.util.Event;
var $A = YAHOO.util.Anim;
var $C = YAHOO.util.Connect;
var $CA = YAHOO.util.ColorAnim;
var $M = YAHOO.util.Motion;
var $Ease = YAHOO.util.Easing;
var $DD = YAHOO.util.DragDrop;
var $DDM = YAHOO.util.DragDropMgr;
var $ = $D.get;
/* */

var EMBEDDED = false;

//
// Return milliseconds since epoch UTC
// does this just reimpliment date.getTime()? heh
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Date:getTime
//
Date.prototype.utimeUTC = function () {
    return Date.UTC(this.getUTCFullYear(), this.getUTCMonth(), this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds(), this.getUTCMilliseconds());
}


//
// Sleep for specificed number of milliseconds from the given moment before
// executing function... moment must be utimeUTC
// Use when you want something to not happen before a certain sleep period, 
// but you have an unknown variable length task that must happen before.
// Basically use to guarantee a minimum length of time for a task that may
// take a longer time depending on factors you cannot predict... in which case
// you don't want to add an extra arbitrary wait to the task.
//
function setTimeoutFromMoment(f, sleep, moment) {
    var d = new Date();
    var now = d.utimeUTC();

    if (now > moment) {
        if ((now - moment) > sleep) {
            sleep = 0;

        } else {
            sleep -= (now - moment);
        }
    }
    
    setTimeout(f, sleep);
}


$E.onDOMReady(onDOMReady);
$E.on(window, 'load', baseOnLoad);


function onDOMReady() {
    if ($('searchform')) {
        $E.addListener('searchform', 'submit', function () {$('hsubmit').disabled = true; return true;}, $('searchform'), true);
        $E.addListener('hsearch', 'blur', function () {if (this.value == '') {this.value = 'search here...';}}, $('hsearch'), true);
        $E.addListener('hsearch', 'focus', function () {if (this.value == 'search here...') {this.value = '';}}, $('hsearch'), true);
    }
    
    if ($('comment')) {
	    $E.addListener('comment', 'focus', function () {if ($('comment').value == 'Your comment here...') {$('comment').value = '';}});
	}
}


function baseOnLoad() {    
    var body = document.getElementsByTagName('body')[0];

    var ajaxScreen = document.createElement('div');
    ajaxScreen.id = 'ajaxScreen';
    var ajaxContainer = document.createElement('div');
    ajaxContainer.id = 'ajaxContainer';
    var ajaxBox = document.createElement('div');
    ajaxBox.id = 'ajaxBox';
    
    body.appendChild(ajaxScreen);
    body.appendChild(ajaxContainer);
    ajaxContainer.appendChild(ajaxBox);
    
    $D.setStyle('ajaxScreen', 'opacity', '0.8');
    $E.addListener('ajaxScreen', 'mousedown', hideAjaxContainer);
}


var gLoginSuccessCallback = null;
var gLoginCancelCallback = null;
var gLoginPageWillReload = false;
var gLoginForWhat = '';
function startAjaxLogin(fSuccess, fCancel, reload, forWhat) {
    showAjaxContainer();
    
    if (fSuccess) {
        gLoginSuccessCallback = fSuccess;
    } else {
        gLoginSuccessCallback = null;
    }
    
    if (fCancel) {
        gLoginCancelCallback = fCancel;
    } else {
        gLoginCancelCallback = null;
    }
    
    if (reload) {
        gLoginPageWillReload = reload;
    } else {
        gLoginPageWillReload = false;
    }
    
    if (forWhat) {
        gLoginForWhat = forWhat;
    } else {
        gLoginForWhat = 'unset';
    }
    
    ajaxShowLoginForm();
}


function showAjaxContainer() {
    $D.setStyle('ajaxScreen', 'height', $D.getDocumentHeight()+'px');
    $D.setStyle('ajaxScreen', 'display', 'block');
    $D.setStyle('ajaxContainer', 'top', $D.getDocumentScrollTop()+100+'px');
    $D.setStyle('ajaxContainer', 'display', 'block');

    var sketchpads = $D.getElementsByClassName('flashBox');
    $D.batch(sketchpads, function(sketchpad) {
        // firefox and IE give these different units... silly firefox
        if($D.getStyle(sketchpad, 'left') == '0pt' || $D.getStyle(sketchpad, 'left') == '0px') {
            $D.setStyle(sketchpad, 'left', '-999em'); 
         }
    });
}


function hideAjaxContainer() {
    if (gFetchAndInjectRequest) {
        $C.abort(gFetchAndInjectRequest);
    }
    
    $D.setStyle('ajaxContainer', 'display', 'none');
    $D.setStyle('ajaxScreen', 'display', 'none');
    
    var sketchpads = $D.getElementsByClassName('flashBox');
    $D.batch(sketchpads, function(sketchpad) {
        if($D.getStyle(sketchpad, 'left') == '-999em') {
            $D.setStyle(sketchpad, 'left', '0'); 
        }
    });
    
    $('ajaxContainer').innerHTML = '';
    
    if (gLoginCancelCallback) {
        (gLoginCancelCallback)();
    }
}


gFetchAndInjectRequest = null;
function ajaxFetchAndInject(url, injectionFunction) {
    $('ajaxContainer').innerHTML = '<div class="content"><form><div class="msg message single"><h2>One moment please...</h2></div></form></div>';
    
    var callback = {
        success: function(o) {
            // If the user requests the login form, but they are already logged in,
            // we need to process the response rather than show the login form
            var responseParts = o.responseText.split('|');
            if (responseParts[0] == 'OK' && responseParts[1] && responseParts[2] && responseParts[3]) {
                ajaxLoginSuccess(responseParts[1], null, responseParts[3], responseParts[4], responseParts[5], responseParts[2]);
            
            } else {
                injectionFunction(o.responseText);
            }

            /*
            var responseParts = o.responseText.split('|');
            
            // If the user requests the login form, but they are already logged in,
            // we need to process the response rather than show the login form
            if (responseParts[0] == 'OK') {
                
            
            } else {
                injectionFunction(o.responseText);
            }
            */
        },

        failure: function(o) {
            // For debugging:
            alert('Failed to load login form: ' + o.status);
            hideAjaxContainer();
        },
        
        argument: null,

        timeout: 10000,
        
        cache: false
    };
    
    gFetchAndInjectRequest = $C.asyncRequest(
        'GET',
        url,
        callback,
        null
    );
}


function ajaxShowColorInfo(color)
{
    showAjaxContainer();
    ajaxFetchAndInject('/about/colors/' + color + '?ajaxed=1', injectColorInfo);
    
    // Google Analytics tracking
    if (pageTracker) {
        pageTracker._trackPageview('/ajax/draw/color/' + color);
    }
}


function injectColorInfo(html)
{
    $('ajaxContainer').innerHTML = '<div class="content"><form>' + html + '<p><a id="cancelDialog" href="#">Close This Message</a></p></form></div>';
    $E.addListener('cancelDialog', 'click', function(e) {$E.stopEvent(e); hideAjaxContainer(); return false;});
}


function ajaxLoginSuccess(tabHTML, joinHTML, availableColors, lockedColors, forsaleColors, privileges) {
    if (privileges == 'NODRAW' && !gLoginSuccessCallback) {
        window.location.reload();
        return;
    }
    
    $D.addClass('loginTab', 'hideTab');
    $D.addClass('joinTab', 'hideTab');
    
    $('profileTab').innerHTML = tabHTML;
    $D.removeClass('profileTab', 'hideTab');

    if (joinHTML && $('joinMsg')) {
        $('joinMsg').innerHTML = joinHTML;
    }
    
    if (availableColors && $('Lflash1') && $('Rflash1') && $('Oflash1')) {
        $('Lflash1').sendAvailableColors(availableColors, lockedColors, forsaleColors);
        $('Rflash1').sendAvailableColors(availableColors, lockedColors, forsaleColors);
        $('Oflash1').sendAvailableColors(availableColors, lockedColors, forsaleColors);
    }

    hideAjaxContainer();
    
    gLoggedIn = true;
    
    if (gLoginSuccessCallback) {
        (gLoginSuccessCallback)();
    }
}


function ajaxShowLoginForm() {
    ajaxFetchAndInject('/users/login?ajaxed=1', injectLoginForm);
    
    // Google Analytics tracking
    if (pageTracker) {
        pageTracker._trackPageview('/ajax/' + gLoginForWhat + '/login/show');
    }
}


function injectLoginForm(html) {
    $('ajaxContainer').innerHTML = html;
    $('login_email').focus();
    $E.addListener('login', 'submit', ajaxLoginSubmitHandler);
    $E.addListener('forgotLink', 'click', function (e) {$E.stopEvent(e); ajaxShowForgotForm(); return false;});
    $E.addListener('joinLink', 'click', function (e) {$E.stopEvent(e); ajaxShowJoinForm(); return false;});
    $E.addListener('cancelDialog', 'click', function(e) { $E.stopEvent(e); hideAjaxContainer(); return false;});
}


function ajaxLoginSubmitHandler(e) {
    $E.stopEvent(e);
    
    $('loginsubmit').value = 'Logging in...';
    $('loginsubmit').setAttribute('disabled', 'disabled');
    
    var callback = {
        success: function(o) {
            var responseParts = o.responseText.split('|');
            if (responseParts[0] == 'OK' && responseParts[1] && responseParts[2] && responseParts[3]) {
                // Google Analytics tracking
                if (pageTracker) {
                    pageTracker._trackPageview('/ajax/' + gLoginForWhat + '/login/success');
                }
                
                ajaxLoginSuccess(responseParts[1], null, responseParts[3], responseParts[4], responseParts[5], responseParts[2]);
            
            } else {
                injectLoginForm(o.responseText);
            }
        },

        failure: function(o) {
            // For debugging:
            alert('Failed to load login form: ' + o.status);
            
            hideAjaxContainer();
        },
        
        //argument: [],

        timeout: 10000
    };
    
    // Get the data from the form
    var postVars = $C.setForm('login');
    
    $C.asyncRequest(
        'POST',
        '/users/login',
        callback,
        postVars + '&ajaxed=1'
    );
}


function ajaxShowForgotForm() {
    ajaxFetchAndInject('/users/forgotpassword.php?ajaxed=1', injectForgotForm);
    
    // Google Analytics tracking
    if (pageTracker) {
        pageTracker._trackPageview('/ajax/' + gLoginForWhat + '/forgot/show');
    }
}


function injectForgotForm(html) {
    $('ajaxContainer').innerHTML = html;
    $E.addListener('forgotpasswordform', 'submit', ajaxForgotSubmitHandler);
    $E.addListener('loginLink', 'click', function (e) {$E.stopEvent(e); ajaxShowLoginForm(); return false;});
    $E.addListener('joinLink', 'click', function (e) {$E.stopEvent(e); ajaxShowJoinForm(); return false;});
}


function ajaxForgotSubmitHandler(e) {
    $E.stopEvent(e);
    
    $('forgotsubmit').value = 'Resetting...';
    $('forgotsubmit').setAttribute('disabled', 'disabled');
    
    var callback = {
        success: function(o) {
            injectForgotForm(o.responseText);
        },

        failure: function(o) {
            // For debugging:
            alert('Failed to load forgot password form: ' + o.status);
            
            hideAjaxContainer();
        },
        
        //argument: [],

        timeout: 10000
    };
    
    // Get the data from the form
    var postVars = $C.setForm('forgotpasswordform');
    
    $C.asyncRequest(
        'POST',
        '/users/forgotpassword.php',
        callback,
        postVars + '&ajaxed=1'
    );
}


function ajaxShowJoinForm() {
    ajaxFetchAndInject('/users/create?ajaxed=1', injectJoinForm);
    
    // Google Analytics tracking
    if (pageTracker) {
        pageTracker._trackPageview('/ajax/' + gLoginForWhat + '/join/show');
    }
}


function injectJoinForm(html) {
    $('ajaxContainer').innerHTML = html;
    $E.addListener('registration', 'submit', ajaxJoinSubmitHandler);
    $E.addListener('loginLink', 'click', function (e) {$E.stopEvent(e); ajaxShowLoginForm(); return false;});
    $E.addListener('cancelDialog', 'click', function(e) { $E.stopEvent(e); hideAjaxContainer(); return false;});
}


function ajaxJoinSubmitHandler(e) {
    $E.stopEvent(e);
    
    $('joinsubmit').value = 'Creating User...';
    $('joinsubmit').setAttribute('disabled', 'disabled');
    
    var callback = {
        success: function(o) {
            var responseParts = o.responseText.split('|');
            if (responseParts[0] == 'OK' && responseParts[1] && responseParts[2] && responseParts[3]) {
                // Google Analytics tracking
                if (pageTracker) {
                    pageTracker._trackPageview('/ajax/' + gLoginForWhat + '/join/success');
                }
                
                ajaxLoginSuccess(responseParts[1], responseParts[2], responseParts[3], responseParts[4], responseParts[5], '');
            
            } else {
                injectJoinForm(o.responseText);
            }
        },

        failure: function(o) {
            // For debugging:
            alert('Failed to load forgot password form: ' + o.status);
            
            hideAjaxContainer();
        },
        
        //argument: [],

        timeout: 10000
    };
    
    // Get the data from the form
    var postVars = $C.setForm('registration');
    
    $C.asyncRequest(
        'POST',
        '/users/create',
        callback,
        postVars + '&ajaxed=1' + (gLoginPageWillReload ? '&willReload=1' : '')
    );
}



function ajaxFavOutcome(n, outcome_did) {
    var d = new Date();
    var start = d.utimeUTC();
    
    function favComplete(newcount, n) {
        var fav = $('favCount' + n);
        var favCount = fav.getElementsByTagName('strong')[0];
        var favText = fav.getElementsByTagName('em')[0];
        var favLink = fav.getElementsByTagName('a')[0];

        $D.removeClass(fav, 'loading');

        favCount.innerHTML = newcount;
        favText.innerHTML = 'hearted';
        
        $D.addClass(fav, 'faved');
        
        favLink.removeAttribute('href');
        favLink.onclick = function () {return false;};
        $D.setStyle(favLink, 'cursor', 'default');
        
        /*
        var fadeInCount = new $A(favCount, {opacity: {to: 1}}, 0.25);
        fadeInCount.animate();
        var fadeInText = new $A(favText, {opacity: {to: 1}}, 0.25);
        fadeInText.animate();
        */
        
        var fadeInLink = new $A(favLink, {opacity: {to: 1}}, 0.2);
        fadeInLink.animate();
    }
    
    var callback = {
        success: function(o) {
            var responseParts = o.responseText.split('|');
            if (responseParts[1]) {
                if (responseParts[0] == 'LOGIN') {
                    /*
                    if we do ajax logins for everything... well... we have to update everything on the screen that goes with being logged in... namely heart all the things that should be hearted, flag all the things that should be flagged.  THAT SUCKS.  So... don't do ajax logins except for draw, heart, flag... and for heart and flag, reload the page!
                    /*
                    var f = (function (n, outcome_did) {return function () {ajaxFavOutcome(n, outcome_did);}})(n, outcome_did);
                    */
                    
                    // If this is embedded and this person isn't logged in, force them to our site
                    if (EMBEDDED) {
                        window.parent.location.href = favLink.getAttribute('href');
                        return;
                    }
                    
                    // IE6 is retarded (big surprise) and doesn't set the referer for us here, so we have to pass it explicitly
                    var fSuccess = function () {window.location.href = favLink.getAttribute('href') + '&redirect=' + escape(window.location.href);};
                    var fCancel = function () {favCancel(o, n);};
                    startAjaxLogin(fSuccess, fCancel, true, 'fav');
                    
                } else if (responseParts[0] != '<!--MAINT') {
                    setTimeoutFromMoment(function () {favComplete(responseParts[1], n);}, 300, start);
                }
            
            } else {
                // For debugging:
                //alert('ERROR: ' + responseParts[0]);
                
                favCancel(o, n, 'error');
            }
        },

        failure: function(o) {
            favCancel(o, n, 'timed out');
        },
        
        argument: [n, start],

        timeout: 10000
    };
    
    var fav = $('favCount' + n);
    var favLink = fav.getElementsByTagName('a')[0];
    $D.addClass(fav, 'loading');
    $D.setStyle(favLink, 'cursor', 'default');
    
    var fadeLink = new $A(favLink, {opacity: {to: 0}}, 0.2);
    
    fadeLink.onComplete.subscribe(
        function () {
            $C.asyncRequest(
                'POST',
                '/ajax/fav_yui.php',
                callback,
                'ajax=1&outcome_did='+outcome_did
            );
        }
    );
    
    fadeLink.animate();
    
    // Cancel anchor default
    return false;
}


function favCancel(o, n, error) {
    // For debugging:
    //alert('Failed to save heart: ' + o.status);
    
    // For production:
    var fav = $('favCount' + n);
    var favText = fav.getElementsByTagName('em')[0];
    var favLink = fav.getElementsByTagName('a')[0];

    $D.removeClass(fav, 'loading');
    $D.removeClass(fav, 'error');
    
    if (error) {
        favText.innerHTML = error;

        $D.addClass(fav, 'error');
    }
    
    $D.setStyle(favLink, 'cursor', 'pointer');
    
    var fadeInLink = new $A(favLink, {opacity: {to: 1}}, 0.2);
    fadeInLink.animate();
}

/*
function showFlagMenu(n, outcome_id) {
    var flag = $('flagPole' + n);
    var flagSpan = flag.getElementsByTagName('span')[0];
    var flagStrong = flag.getElementsByTagName('strong')[0];
    
    var fadeSpan = new $A(flagSpan, {opacity: {to:0}}, 0.2);
    
    fadeSpan.onComplete.subscribe(
        function() {
            $D.addClass(flag, 'loading');
            
            var tt = new Tooltip(flagStrong, null, null, false, false);
            
            tt.customHideCallback = function ()
            {
                $D.removeClass(flag, 'loading');
                var fadeIn = new $A(flagSpan, {opacity: {to: 1}}, 0.25);
                fadeIn.animate();
            };
            
            tt.create(
                '<ul>'
                + '<li><a href="#" onclick="ajaxFlagOutcome(' + n + ', ' + outcome_id + ', 2); return false;">Graphic Nudity</a></li>'
                + '<li><a href="#" onclick="ajaxFlagOutcome(' + n + ', ' + outcome_id + ', 3); return false;">Violates Terms of Use</a></li>'
                + '<li><a href="#" onclick="return false;">Cancel</a></li>'
                + '</ul>',
                'warning'
            );
            
            tt.show(null, 100);
        }
    );
    
    fadeSpan.animate();
    
    // Cancel anchor default
    return false;
}
*/

function ajaxFlagOutcome(n, outcome_id, flagNum) {
    if (typeof flagNum == 'undefined')
    {
        flagNum = 1;
    }
    
    var callback = {
        success: function(o) {
            var responseParts = o.responseText.split('|');
            if (responseParts[1]) {
                if (responseParts[0] == 'LOGIN') {
                    var flag = $('flagPole' + n);
                    var flagLink = flag.getElementsByTagName('a')[0];
                    
                    // If this is embedded and this person isn't logged in, force them to our site
                    if (EMBEDDED) {
                        window.parent.location.href = flagLink.getAttribute('href');
                        return;
                    }
                    
                    // IE6 is retarded (big surprise) and doesn't set the referer for us here, so we have to pass it explicitly
                    var fSuccess = function () {window.location.href = flagLink.getAttribute('href') + '&flag=' + parseInt(flagNum) + '&redirect=' + escape(window.location.href);};
                    var fCancel = function () {flagCancel(o, n);};
                    startAjaxLogin(fSuccess, fCancel, true, 'flag');
                    
                } else if (responseParts[0] != '<!--MAINT') {
                    var flag = $('flagPole' + n);
                    var flagSpan = flag.getElementsByTagName('span')[0];

                    $D.removeClass(flag, 'loading');
                    $D.removeClass(flag, 'error');

                    flagSpan.innerHTML = '<em>You flagged this outcome.</em>';

                    var fadeIn = new $A(flagSpan, {opacity: {to: 1}}, 0.25);
                    fadeIn.animate();
                }
                            
            } else {
                // For debugging:
                //alert('ERROR: ' + response);
                
                flagCancel(o, n, 'Flagging error. Try again?');
            }
        },

        failure: function(o) {
            flagCancel(o, n, 'Flagging timed out. Try again?');
        },
        
        argument: [n],

        timeout: 10000
    };
    
    var flag = $('flagPole' + n);
    var flagSpan = flag.getElementsByTagName('span')[0];
    
    var fadeSpan = new $A(flagSpan, {opacity: {to:0}}, 0.2);
    
    fadeSpan.onComplete.subscribe(
        function() {
            $D.addClass(flag, 'loading');
            $C.asyncRequest(
                'POST',
                '/ajax/flag_yui.php',
                callback,
                'ajax=1&flag=' + parseInt(flagNum) + '&outcome_id='+outcome_id
            );
        }
    );
    
    fadeSpan.animate();
    
    // Cancel anchor default
    return false;
}


function flagCancel(o, n, error) {
    // For debugging:
    //alert('Failed to save flag: ' + o.status);
    
    // For production:
    var flag = $('flagPole' + n);
    var flagSpan = flag.getElementsByTagName('span')[0];
    var flagLink = flag.getElementsByTagName('a')[0];
    
    $D.removeClass(flag, 'loading');
    
    if (error) {
        $D.addClass(flag, 'error');

        flagLink.innerHTML = error;
    }
    
    var fadeIn = new $A(flagSpan, {opacity: {to: 1}}, 0.25);
    fadeIn.animate();
}


gConfirmTooltips = {}
function confirmDeleteComment(comment_id) {
    var deleteSpan = $('deleteSpan' + comment_id);
    var deleteLink = deleteSpan.getElementsByTagName('a')[0];
    
    var fadeOut = new $A(deleteLink, {opacity: {to:0}}, 0.2);
    
    fadeOut.onComplete.subscribe(
        function() {
            $D.setStyle(deleteLink, 'display', 'none');
            $D.addClass(deleteSpan, 'loading');
            
            if (!gConfirmTooltips[comment_id]) {
                gConfirmTooltips[comment_id] = new Tooltip(deleteSpan, null, null, false, false);
                gConfirmTooltips[comment_id].customHideCallback = function () {deleteCommentCancel(null, comment_id);};
                gConfirmTooltips[comment_id].create('Delete this comment?<br /><a href="#" onclick="return false;">Cancel</a> <a style="margin-left: 1.5em;" href="#" onclick="ajaxDeleteComment(' + comment_id + '); return false;">Yes</a>', 'warning');
            }

            gConfirmTooltips[comment_id].show(null, 100);
        }
    );
    
    fadeOut.animate();
}


function ajaxDeleteComment(comment_id) {
    var callback = {
        success: function(o) {
            var responseParts = o.responseText.split('|');
            if (responseParts[1]) {
                if (responseParts[0] == 'LOGIN') {
                    var deleteSpan = $('deleteSpan' + comment_id);
                    
                    var deleteLink = deleteSpan.getElementsByTagName('a')[0];
                    
                    // IE6 is retarded (big surprise) and doesn't set the referer for us here, so we have to pass it explicitly
                    var fSuccess = function () {window.location.href = '/ajax/deletecomment_yui.php?comment_id=' + comment_id + '&referer=' + escape(window.location.href);};
                    var fCancel = function () {deleteCommentCancel(o, comment_id);};
                    startAjaxLogin(fSuccess, fCancel, true, 'delete');
                    
                } else {
                    var commentLi = $('c' + comment_id);
                    
                    var fadeLi = new $A(commentLi, {opacity: {to: 0}, height: {to: 0}}, 0.2);
                    fadeLi.onComplete.subscribe(
                        function () {
                            $D.setStyle(commentLi, 'display', 'none');
                        }
                    );
                    fadeLi.animate();
                }
                            
            } else {
                // For debugging:
                //alert('ERROR: ' + response);
                
                deleteCommentCancel(o, comment_id, 'Delete error. Try again?');
            }
        },

        failure: function(o) {
            deleteCommentCancel(o, comment_id, 'Delete timed out. Try again?');
        },
        
        argument: [comment_id],

        timeout: 10000
    };
    
    $C.asyncRequest(
        'POST',
        '/ajax/deletecomment_yui.php',
        callback,
        'ajax=1&comment_id=' + comment_id
    );
}


function deleteCommentCancel(o, comment_id, error) {
    // For debugging:
    //alert('Failed to save flag: ' + o.status);
    
    // For production:
    var deleteSpan = $('deleteSpan' + comment_id);
    var deleteLink = deleteSpan.getElementsByTagName('a')[0];
    
    $D.removeClass(deleteSpan, 'loading');
    $D.setStyle(deleteLink, 'display', 'inline');
    
    if (error) {
        $D.addClass(deleteSpan, 'error');

        deleteLink.innerHTML = error;
    }
    
    var fadeIn = new $A(deleteLink, {opacity: {to: 1}}, 0.25);
    fadeIn.animate();
}

// Google Analytics tracking for share
function trackShare(service, what) {
    if (pageTracker) {
        pageTracker._trackPageview('/share/' + service + '/' + what);
    }
}


function DEBUG(s) {
    var div = $('debug');
    if (div) {
        div.innerHTML += '<p>' + s + '</p>';
    }
}



/////////////

//
// Super awesome happy funtime tooltips.
// @param target    {Object}    The element that invokes showing and hiding the tooltip (optional)
// @param tooltip   {Object}    The element that holds the tooltip content (optional)
// @param relative  {Object}    Object to point the tooltip at. Overrides position on target (optional)
// @param autoShow  {boolean}   Whether or not the target invokes the tooltip on mouseover (optional)
// @param autoHide  {boolean}   Whether or not the tooltip will auto-hide without click (optional)
// @param visible   {boolean}   Show by default (optional)
//

function Tooltip(target, tooltip, relative, autoShow, autoHide, visible) {
    this.tooltip = $(tooltip);
    
    this.tipContent = $D.getFirstChild(this.tooltip);
    
    this.targetEl = $(target) || null;
    this.relative = $(relative) || null;
    
    this.autoShow = autoShow || false;
    this.autoHide = autoHide || false;
    this.locked = visible || false;

    this.timer = null;
    if(this.tooltip) { this.attachEvents(); }
};

Tooltip.prototype.attachEvents = function() {
    this.autoShow = (this.autoShow || $D.hasClass(this.targetEl, 'autoShow'));
    this.autoHide = (this.autoHide || $D.hasClass(this.targetEl, 'autoHide'));
    this.locked = (this.visible || $D.hasClass(this.tooltip, 'openTooltip'));
    
    if(this.targetEl) {
        if(this.autoShow) {
            $E.addListener(this.targetEl, 'mouseover', function(event) {
                if(!this.visible) { this.unlock(); }
                this.show(event, 1000);
            }, this, true);
            $E.addListener(this.targetEl, 'mouseout', this.lock, this, true);
        } else {
            $E.addListener(this.targetEl, 'click', this.toggle, this, true);
        }
         
        if(this.autoHide) {
            $E.addListener(this.targetEl, 'mouseout', function(event) {
                this.hide(event, 1000, true);
            }, this, true);
            $E.removeListener(this.targetEl, 'mouseout', this.lock);
            $E.addListener(this.tooltip, 'mouseover', this.lock, this, true);
            $E.addListener(this.tooltip, 'mouseout', function(event) {
                this.hide(event, 1000, true);
            }, this, true);
        }
    }

    if(this.relative) { this.setPosition(); }
    $E.addListener(this.tooltip, 'click', this.toggle, this, true);
};

//
// @param text      {string}    content to render inside the tooltip
// @param tipClass  {string}    class to add to the tooltip (optional)
//
Tooltip.prototype.create = function(text, tipClass) {
    var tooltip = document.createElement('div');
    tooltip.className = 'tooltip';
    (tipClass) ? tooltip.className += ' '+tipClass : tooltip.className += '';
    
    var content = document.createElement('div');
    content.className = 'content';
    tooltip.appendChild(content);
    
    var copy = document.createElement('p');
    copy.innerHTML = text;
    content.appendChild(copy)
    
    document.getElementsByTagName('body')[0].appendChild(tooltip);
    this.tooltip = tooltip;
    this.tipContent = content;

    this.attachEvents();
};

Tooltip.prototype.show = function(event, delay) {
    if(event) { $E.stopEvent(event); }
    if(this.locked) { return false; } 
    this.clearTimer();
    
    if(typeof(delay) == 'number') {
        var self = this;
        this.timer = window.setTimeout(function() {
            self.animateIn();
        }, delay);
    } else {
        this.animateIn();
    }
};

Tooltip.prototype.animateIn = function() {
    if(this.locked) { return false; } 
    this.lock();

    if(this.targetEl) { this.setPosition(); }
    
    var timing = Math.round((this.contentHeight/300)*100)/100;

 	var show = new $A(this.tipContent, {height: {from: 0, to: this.contentHeight}}, timing, $Ease.easeOut);
 	show.onStart.subscribe(function() {
        if(this.customShowCallback) { this.customShowCallback(); }
        $D.setStyle(this.tooltip, 'visibility', 'visible');
 	}, this, true);

    show.animate();
    this.visible = true;
};

Tooltip.prototype.hide = function(event, delay, forceUnlock) {
    if(event) { $E.stopEvent(event); }
    if(this.locked && !forceUnlock) { return false; } 
    this.clearTimer();
    
 	var hide = new $A(this.tipContent, {height: {to: 0}}, 0.2);
 	hide.onComplete.subscribe(function() {
      	this.unlock();
        this.setPosition();
        if(this.customHideCallback) { this.customHideCallback(); }
 	}, this, true);

    if(typeof(delay) == 'number') {
        this.timer = window.setTimeout(function() {
        	hide.animate();
        }, delay);
    } else {
        hide.animate();
    }
    this.visible = false;
};

Tooltip.prototype.clearTimer = function() {
    if (this.timer != null) {
        window.clearTimeout(this.timer);
        this.timer = null;
    }
};

Tooltip.prototype.toggle = function(event) {
    $E.stopEvent(event);
    if(this.locked) {
        this.unlock();
        this.hide(event);
    } else {
        this.show(event);
    }
};

Tooltip.prototype.setPosition = function() {
    var xPos, yPos;
    if(this.targetEl || this.relative) {
        var anchor = this.relative || this.targetEl;
        var xPos = $D.getX(anchor) + Math.floor(anchor.offsetWidth/2);
        var yPos = $D.getY(anchor) + anchor.offsetHeight;
    }
    if(!this.locked) {
        xPos = -9999;
        yPos = -9999;
    }

 	$D.setX(this.tooltip, -9999);
  	$D.setY(this.tooltip, -9999); 
    $D.setStyle(this.tooltip, 'display', 'block');
    
    $D.setStyle(this.tipContent, 'height', 'auto');
    if(!this.contentHeight) {
        this.contentHeight = this.tipContent.offsetHeight - $D.getStyle(this.tipContent, 'paddingTop').split('px')[0] - $D.getStyle(this.tipContent, 'paddingBottom').split('px')[0];
    }
    
    if(this.targetEl) { 
        $D.setStyle(this.tooltip, 'visibility', 'hidden'); 
        $D.setStyle(this.tipContent, 'height', '0');
    }
    
    $D.setX(this.tooltip, (xPos - Math.floor(this.tooltip.offsetWidth/2)));
    $D.setY(this.tooltip, yPos);
};

Tooltip.prototype.lock = function() {
    if(this.timer != null) {
        window.clearTimeout(this.timer);
        this.timer = null;
    }
    this.locked = true;
};

Tooltip.prototype.unlock = function() {
    this.locked = false;
};

function createTooltips() {
    var targets = $D.getElementsByClassName('hasTooltip');
    for(var i = 0; i < targets.length; i++) {
        new Tooltip(targets[i], targets[i].href.split('#')[1]);
    }
    new Tooltip(null, $D.getElementsByClassName('openTooltip')[0], $('awesome'));
}
$E.onDOMReady(createTooltips);
//
// No more super awesome happy funtime tooltips. That makes me super shitty crappy sucktime sad.
//
