
function console_log(msg) {
    if (window.console)
        window.console.log(msg);
    return undefined;
}

/** FORM OBJECT **/

window.allFormObjects = new Array();

function findFormObject(id, noisy) {
    var rv = window.allFormObjects[id];
    if (rv) 
        return rv;
    
    var f = document.getElementById(id);
    if (f && f.formObject)
         return f.formObject;
   
    if (noisy)
        alert("Cannot find form object: " + id);    

    return rv;
}

FormObject.prototype.getMasterDocument = function(noisy) {
    var mm = this.getMaster(noisy);
    return mm ? mm.document : null;
};

// return master window.
FormObject.prototype.getMaster = function(noisy) {
    if (! this.master)
    {
        if (window.opener && window.opener.document)
            this.master = window.opener;
        else if (window.parent && window.parent.document)
            this.master = window.parent;
        else if (noisy)
            alert("cannot determine master document");
    }
    return this.master;
};

// return a jquery object.
FormObject.prototype.getMasterField = function(id, noisy) {
    var m = this.getMaster();
  
    // m.$ means to call the jquery instance in the parent doc - if one exists. 
    var outfield = m.$ ? m.$('#'+id) : $(m.document).find('#' + id);
    if (outfield && outfield[0])
        return outfield;

    outfield = m.find('input[name='+id+']');
    if (outfield && outfield[0])
        return outfield;

    if (noisy)
    {
        alert("cannot find " + id + " in master document " + m[0].location); 
    } 
    return null;
};

// putIntoMaster (target-field-id, value, [ noisy:false ])
FormObject.prototype.putIntoMaster = function(id, val, noisy) {
    var outfield = this.getMasterField(id, noisy);

    if (outfield && outfield[0])
    {
        var tn = outfield[0].tagName.toLowerCase();

        if (tn=='input' || tn=='select')
        {
            outfield.val(val);
        } else {
            outfield.html(val);
        }
        outfield.change();  // call event handler in parent doc

        return true;
    } 
    return false;
};

FormObject.prototype.getField = function(fieldname, noisy) {
    var rv = null;
    if (typeof fieldname == "string")
    {
        rv = this.form[0].elements[fieldname];
    } else if (typeof fieldname == "object") {
        rv = fieldname;
    } else {
        alert("getField:unknown type " + (typeof fieldname) + " for form field " + fieldname);
    } 

    if (rv)
	return rv;
    if (noisy)
	alert("cannot find form field " + fieldname);
    return null;
};

FormObject.prototype.getFieldValue = function(fieldname, noisy) {
	var f = this.getField(fieldname,noisy);
	if (f)
		return f.value;
	return undefined;
};

FormObject.prototype.putFieldValue = function(fieldname, newval) {
	var f = this.getField(fieldname, true);
	if (f)
	{
		f.value = newval;
		// don't call onchange as we may get into loops.
		// if (f.onchange) f.onchange();
	}
	return f;
};

FormObject.prototype.handlePopulate = function(evt) {
    return this;
};

FormObject.prototype.handleActivate = function(evt) {
    // handler for custom method 'activate'
    return this;
};

FormObject.prototype.handleDeactivate = function(evt) {
    // handler for custom method 'activate'
    return this;
};

FormObject.prototype.handleFocus = function(evt) {
	return this;
};

// this is a no-op - expect child classes to override.
FormObject.prototype.handleClick  = function(evt) { return this._handleChange(evt); } 
FormObject.prototype.handleChange = function(evt) { return null; } 

// a simple wrapper that calls on the real _handleChange function
FormObject.prototype._handleChange = function(evt) {
    this.handleChange(evt);

    var widget = evt.target ? evt.target : evt;
    if (widget.value != widget.defaultValue)
        this.markChanged(widget);

    var $w = $(widget);
    if ($w.hasClass('suggestor'))
    {
        var targetid = widget.id.replace('-suggestor', '');
        if (targetid && targetid!=widget.id)
        {
            var f = this.getField(targetid);
            if (f)
            {
                f.value = $w.val();
                $(f).trigger('change');
            }
        } 
    } 

    return void(0);

};

FormObject.prototype.handleBlur = function(evt) {
	return this;
};

FormObject.prototype.handleKeyPress = function(evt) {
	return true;
};

FormObject.prototype.handleOptionClick = function(evt) { 
    return this; 
}

FormObject.prototype.handleSubmit = function(evt) {
	return true;
};

FormObject.prototype.dumpForm = function() {
// for debugging.
    for (var i=0; i < f.elements.length; i++)
    {
        var e = f.elements[i];
        if (console)
            console.log(e.name + " is '" + e.value + "'");
    }
	return true;
};

// called when you have a specific group of widgets that need to handleChange() etc.
// ordinarily, though, just call bindEverything, and let the form decide what to bind.
FormObject.prototype.bindWidgets = function(widgets) {

    // Note it's calling the private _handleChange here.
	var me = this;
    widgets.not('input[type=radio]').not('input[type=checkbox]').bind(
        'change', function(evt) { me._handleChange(evt) } ).bind(
        'keypress', function(evt) { return me.handleKeyPress(evt) } ).bind(

        /* activate, deactivate, populate are custom events I made up! */
        'activate', function(evt) { me.handleActivate(evt) } ).bind(
        'populate', function(evt) { me.handlePopulate(evt) } ).bind(
        'deactivate', function(evt) { me.handleDeactivate(evt) } ).bind(

        'blur', function(evt) { me.handleBlur(evt) } ).bind(
        'focus', function(evt) { me.handleFocus(evt) } 
    );

    // We track clicks on 'option' separately because the 'change' event of a
    // SELECT MULTIPLE is useless.
    widgets.find('option').click(function(evt) { me.handleOptionClick(evt) });
    
    widgets.filter('input[type=radio]').bind(
        'click', function(evt) { me.handleClick(evt) }
    );
    widgets.filter('input[type=checkbox]').bind(
        'click', function(evt) { me.handleClick(evt) }
    );
    widgets.filter('button').bind(
        'click', function(evt) { me.handleClick(evt) }
    );
    return widgets;
};

FormObject.prototype.bindEverything = function() {
    if (!this.$allwidgets)
    {
        this.$allwidgets = this.form.find('input,select,textarea,button');
        //this.radios = this.form.find('input[type=radio]');
    }

	var me = this;
    this.bindWidgets(this.$allwidgets);
    this.form.bind('submit', function(evt) { return me.handleSubmit(evt); } );

	return this;
};

FormObject.prototype.getValuesBySuffix = function (suffix) {
    var rv = new Array();

    for (var w in this.$allwidgets)
    {
        var widget = this.$allwidgets[w];
        var name = widget.name ? widget.name : widget.id;
        
        if (name && (name.indexOf(suffix)>0))
        {
            var pos = name.indexOf(suffix);
            var frag = name.substr(0, pos);
            if (frag+suffix == name)
            {
                rv[frag] = widget.value;
            }
        }
    }
    return rv;
};
FormObject.prototype.markChanged = function(f) {
    var field = this.getField(f, false);
    if (field)
    {
        if (field.value==field.defaultValue)
        {
            $(field).removeClass('changed');
            return false;
        } else if (field.type=='button' || field.tagName=='BUTTON') {
        } else if (field.type=='submit') {
        } else if (field.type=='reset') {
        } else {
            $(field).addClass('changed');
            return true;
        }
    }
    return void(0);
};

FormObject.prototype.assembleQueryString = function () {
    var elems = this.form[0].elements; 

    var qs = '';
    for (var i=0; i< elems.length; i++)
    {
        var e = elems[i];
        if (e.name)
        {
            qs = qs + e.name + '=' + escape( $(e).val() ) + '&';
        } 
    } 
    return qs;
};

FormObject.prototype.ajaxSubmitCallback = function(tree) {
    if (console)
        console.dir(tree);
    return void(0);
};


FormObject.prototype.ajaxSubmit = function() {
    this.throbber.show('fast');

    var qs = this.assembleQueryString();
    var url = this.form[0].action + '?' + qs;

    var me = this;
    jQuery.get(url, {}, function (xmltree) {
         return me.ajaxSubmitCallback(xmltree);
    });
    return this;
};

FormObject.prototype.setupAjaxSubmit = function(expr) {
    var button = this.form.find(expr);
    var me =this;
    button.bind('click', function() { me.ajaxSubmit(); });
    if (button[0] && button[0].form)
    {
        $(button[0].form).bind('submit', function() { me.ajaxSubmit(); return false;});
    } 

    this.throbber = $('#' + this.formid + '-throbber');
    this.throbber.hide('fast');

    return this;
};

function FormObject()
{
	return this;
};

FormObject.prototype.findAllWidgets= function () {
    this.$inputs = this.form.find('input');
    this.$selects = this.form.find('select');
    this.$textareas = this.form.find('textarea');
    this.$buttons = this.form.find('button');

    this.$allwidgets = $([]).add(
        this.$inputs).add(
        this.$selects).add(
        this.$textareas).add(
        this.$buttons
    );

    this.$radios = this.$inputs.filter('type=radio'); 
    this.$checkboxen = this.$inputs.filter('type=checkbox'); 
    this.$textfields = this.$inputs.filter('type=text'); 
    // other types : password, submit, image, button - are a bit less useful,
    // so they don't get their own yet...
    //this.$hiddenwidgets = this.$inputs.filter('type=hidden'); 
    return this;
};

FormObject.prototype.init = function(formid1) {
    this.formid = formid1;
    this.form = this.$form = $('#' + formid1);

    window.allFormObjects[formid1] = this;

    this.findAllWidgets();  // sets this.$allwidgets

	if (!this.form[0])
	{
		alert("Cannot find form " + formid1);
		return this;
	} else {
		this.form.addClass("formObject");
        this.form.formObject = this;
	}
	
	return this;
};

function SelectProductForm(formid) {
    this.init(formid);
    this.bindEverything();
    this.$addfields = $("#" + formid + "-add-fields");
    this.showAdd(false);
}

SelectProductForm.prototype = new FormObject();

SelectProductForm.prototype.handleChange = function (evt) {
    var w = evt.target ? evt.target : evt;
    var $w = $(w);
  
    if ($w.hasClass('item-number-select'))
    {
        return this.handleChangeItem(w);
    } else {

    }

    return undefined;
};

SelectProductForm.prototype.showAdd = function (visible) {
    if (visible)
        this.$addfields.show('slow');
    else
        this.$addfields.hide('slow');
};

SelectProductForm.prototype.handleChangeItem = function (w) {
    var $w = $(w);
    var $opt = $w.find('option:selected');
    var text = $opt.text();
    if ($opt.size<1 || !text)
    {
        return void(alert("cannot determine selected option"));
    }

    if ($w.val())
    {
        var splitPoint = text.lastIndexOf('$');
        if (splitPoint>0)
        {
            var price = text.substring(splitPoint+1);
            var name = text.substring(0, splitPoint-2);

            var $pf = this.$form.find('.item-amount-field');
            var $nf = this.$form.find('.item-name-field');
            if ($pf.size() && $nf.size())
            {
                this.showAdd(true);
                $pf.val(price);
                $nf.val(name);
                
                // HAPPY RETURN.
                return undefined;
            } else {
                alert("cannot find output fields for name/price");
            }

        }
        
    }

    this.showAdd(false);
};
function FooterFeedbackForm(formid) {
    var me = this;
    
    this.$form = $('#' + formid);
    this.$text = this.$form.find('textarea');

    this.defaultText = this.$text.val();

    this.$text.bind('focus', function(evt) { me.handleFocus(evt) });
    this.$form.bind('submit', function (evt) { me.handleSubmit(evt); return false; });
}

FooterFeedbackForm.prototype.handleFocus = function (evt) {
    var t = this.$text.val();
    if (t==this.defaultText)
    {
        this.$text.val('');
    }
    return false;
};

FooterFeedbackForm.prototype.afterSubmit = function (j) {
    this.$form.find('.throbber-wrapper').empty();
    if (j.status=='error')
        alert(j.message);
    else
        this.$form.html("<div id='bottom-feedback-response'>" + j.message + "</div>");
    return undefined;
};

FooterFeedbackForm.prototype.handleSubmit = function (evt) {

    var text = this.$text.val();
    if (text==this.defaultText || text.length<4)
        return false;

    var qf = 'quick_feedback';
    var me = this;

    this.$form.find('.throbber-wrapper').empty().html(
        '<div><img class="rfloat" src="/images/throbbers/white-bar-on-dkblue.gif" alt="loading" /> sending... </div>'
    );

    $.ajax({
        url: '/b3/guestbook/' + qf,
        method: 'post', 
        dataType: 'json', 
        data: {
            message: text
        },
        success: function (j) { me.afterSubmit(j); }
    });

    return false;
};window.BBB_RANDOM_QUOTES = [
    // format: [ "quote", "signature" ] (comma, except if last entry)
    [   "I love your site, your jump rings & I'm addicted to your book Chained! Thanks!!!",
        'Daleann Stark, KY'
    ],
    [
        "I had thought to make chainmaille jewelry before, but was always so intimidated by the books and magazines. The instructions never made sense. I am sooooo glad to have purchased \"Chained\" I now have a new skill that will last a lifetime. Thank you!!!",
        "M. Pizarro, Brooklyn, NY"
    ],
    [
        "You have been very responsive to me and I thank you for that. I think your company is the very best and most cooperative. I have absolutely NO bones to pick with you....believe me! For heaven's sake, do not go away, except for a well needed vacation now and then.",
        "M.B.M., USA"
    ],
    [
        "I have only this to say: After only one purchase from you, I have decided to switch to you as my preferred and primary supplier. I don't ask for much, but you far exceed my expectations. Thank you kindly for being so amazing.",
        "Sinna Ogle, USA"
    ]

    // Check for superfluous commas at ends of list!  IE chokes on these.
];function AnodizedPackageGroup(data)
{
	this.quantities={ };
	
	for (var i in data) {
		if (isNaN(i))
			this[i]=data[i];
		else
			this.quantities[i]=data[i];
	}
	return this;
}

/*
 * Analyse quantities, and return the status value that's highest
 */
AnodizedPackageGroup.prototype.inventoryStatus = function () {
	var rv=0;
	for (var q in this.quantities)
	{
		var st = this.quantities[q][0];
		if (st>rv)
			rv=st;
	}
	return rv;
};

function AnodizedRingPicker(metal_code)
{
    this.metal_code=metal_code;
    this.metal_name='Niobium';  // FIX ME
    this.packageGroups={};
    this.colours={};
}

AnodizedRingPicker.prototype.setColours = function (c) {
    this.colours=c;
};

AnodizedRingPicker.prototype.finishSetup = function () {
    this.setupSelectMenus();
};


AnodizedRingPicker.prototype.setupSelectMenus = function () {
    var me = this;
    $('.select-package-group').change(
        function(evt) {return me.handleSelect(this,evt)}
    ).selectmenu({
        format: function(text) {
            return me.formatColourSelect(text);
        }
    });
};

AnodizedRingPicker.prototype.handleSelect = function (w, evt) {
    var size_code = w.id.replace('-select', '');
    var $w = $(w);
    var base_id = $.trim($w.val());
    
    return this.activateCartArea(size_code, base_id);
};

AnodizedRingPicker.prototype.activateCartArea = function (size_code, base_id) {
    var $cartarea= $('#'+size_code+'-cart-area');
    
    // First hide the forms - if all goes well we'll show them soon enough.
    $cartarea.find('.forms-box').hide(0);
    
    var packageGroup = this.activePackageGroup = this.getPackageGroup(base_id);
    var status = packageGroup.inventoryStatus();
    if (status < 100)
    {
        $cartarea.find('.instructions-box').html(
        		'<div class="error">' + 
        		"Sorry, this product is temporarily out of stock.  Please try another color or size." +
        		'</div>'
        		).show(0);
        return null;
    }
    
    $cartarea.find('.instructions-box').hide(0);
    var $forms = $cartarea.find('form');
    $forms.addClass('cart-form-disabled');
    
    if (!base_id || !packageGroup)
    {
        $cartarea.fadeOut('fast');
        return undefined;
    }
        
    var colourCode = packageGroup.c;
    var colour = this.colours[colourCode];
    
    // $cartarea.find('h4').text( base_id + " - " + colour.n);
    
    for (var qty in packageGroup.quantities)
    {
        var $form = $('#'+size_code+'-cart-' + qty);
        if ($form.size()<1) // form not found?
            continue;
        
        if (qty==1)
        	continue;
        
        this.populatePaypalForm($form, base_id, qty, packageGroup, size_code, colour);
    }

    $cartarea.find('.forms-box').show("slide", { direction: 'left' }, 700);

    return undefined;
};

AnodizedRingPicker.prototype.populatePaypalForm = function ($form, base_id, qty, packageGroup, size_code, colour) {
    var pkgInfo = packageGroup.quantities[qty];
    if (!pkgInfo)
	{
    	if (console) console.log("error no package info for qty " + qty);
	}
    var st = pkgInfo[0];
    var pr = +pkgInfo[1];
    
    $form.removeClass('cart-form-disabled');
    
    var formData = {
        item_number: base_id,
        // item_name: this.metal_code + " " + size_code + ", pack of " + qty + ", " + colour.n,

        // Pack of 250: D20 ring, Niobium, Berry (blend)
        item_name: "Pack of " + qty + ": " + size_code + " ring, " + this.metal_name + ", " + colour.n + 
            ( (colour.f.indexOf("B") > -1) ? ' (blend)' : '' ),   
        amount: pr
    };

 
    for (var fn in formData)
    {
        var $target = $form.find('input[name='+fn+']');
        if ($target.size() < 1)
        {
            if (console)
                console.log("ALERT - cannot find field " + fn + 
                " in form " + $form.attr('id'));
            $form.hide('fast');
            return null;
        }
        $target.val(formData[fn]);
    }
    
    // is buyable?
    if (st>=100 && (pr>0.001)) {
        // $form.find('.cart-qty-label').text("pack of " + qty);
        $form.find('.package-price').text('$' + pr.toFixed(2));
    } else {
        $form.find('.cart-qty-label').text("pack of " + qty + " out-of-stock ");
        $form.find('.package-price').text();
    }
    
    $form.show(0);
    return undefined;
}


AnodizedRingPicker.prototype.getPackageGroup = function (base_id) {
    var base_id = $.trim(base_id);
    
    var packageGroup = this.packageGroups[base_id];
    if (!packageGroup)
    {
        if (console) console.log("error - no package group for '" + base_id + "'");
        return null;
    }
    return packageGroup;
};

AnodizedRingPicker.prototype.formatColourSelect = function (text) {
    if (text.indexOf("Select") === 0)
        return text;
    
    var packageGroup = this.getPackageGroup(text);
    if (!packageGroup) 
        return text;
        
    window.PACKAGE_GROUP = packageGroup;
    
    var status = packageGroup.inventoryStatus();
    
    var colourCode = packageGroup.c;
    var colour = this.colours[colourCode];
    if (!colour)
        return text;
    
    var rv ='<img class="sample" src="'+this.colourImage(colourCode)+'" alt="'
        +colourCode+'" />';

    var mainText = '<span class="colour-name">'+colour.n+'</span>';
    if (colour.v)
        mainText += ' <span class="colour-value">#'+colour.v+'</span>';
    

    rv += '<div class="select-main">' + mainText + '</div>';
    
    var className = "option-in-stock";
    if (status < 100)
    {
    	className="option-out-of-stock";
	    rv +=  '<div class="select-subtitle-oos">(out of stock)</div>';
    } else {
	    if (colour.f.indexOf("B") > -1)
	        rv +=  '<div class="select-subtitle">(color blend)</div>';
    }
    rv = '<div class="' +className+ '">' + rv + '</div>';
    return rv;
};

AnodizedRingPicker.prototype.colourImage = function (colour_code) {
    return "/images/colours/"+this.metal_code+"/100px/"+colour_code+"-100px.jpg";
};

AnodizedRingPicker.prototype.addPackages = function (base_id, packageGroup) {
    this.packageGroups[base_id] = new AnodizedPackageGroup(packageGroup);
};

function doPopup(url, name, x,y)
{
    if ( (typeof(name)=='undefined') || (!name) )
        name = "popup"+Math.floor(100000*Math.random());

    myPopup = window.open(url, name,
        "width=" + x + ",height=" +y + ",menubar=no,location=no,scrollbars=yes,resizable");
    myPopup.focus();
    return void(0);
}

function popupTall(url, name)
{
    return doPopup(url,name, 600, 900);
}

function popupSmall(url, name)
{
    return doPopup(url,name, 500, 400);
}

function popupLarge(url, name)
{
    return doPopup(url,name, 800, 600);
}

function popupHuge(url, name)
{
    return doPopup(url, name, 1024, 768);
}

function LoginBox(opts)
{
    // Nuke old form.
    $('#login-box').remove();

    // Create a new login-box widget, and load the form into it ajaxily.
    var me = this;
    
    this.$wrapper = this.setupFrame();
    this.loadLoginForm();
}

LoginBox.prototype.setupFrame = function() { 
    var me = this;
    
    var $w  = $('<div id="login-box" />');
    
    var $link = $('<a href="#" id="login-box-close-button"></a>');
    $w.append($link);
    
    var $innerBox = $('<div id="login-box-inner" />');
    this.$innerBox = $innerBox;
    $w.append($innerBox);
    
    $('#container').prepend($w);    
    
    $link.click(function() { return me.closeLoginBox(); });
    
    this.$throbber = this.makeThrobber();
    this.$innerBox.append(this.$throbber);
    this.showPanel(this.$throbber);
    
    return $w;
}

LoginBox.prototype.loadLoginForm = function() { 
    var me = this;
    
    $.get('/b3/user_sessions/mini', {}, function(x) { 
        me.handleFormLoaded(x) 
    } );
    
};

LoginBox.prototype.closeLoginBox = function() { 
    $('#login-box').remove();
    
    this.$mainPanel=null;
    this.$innerBox=null;
    this.$wrapper=null;
    
    return undefined;
};

LoginBox.prototype.hideThrobber = function () {
    this.$throbber.hide();
};

LoginBox.prototype.handleFormLoaded = function(x) { 
    this.hideThrobber();
    
    // parse xml and keep it.
    this.$mainPanel = $(x); //.css('display: none');
    this.$innerBox.append(this.$mainPanel);
    
    var me = this;
    
    this.$wrapper.find('form').submit(function() { 
        me.handleAjaxSubmit();
        return false;
    });
    
    var me = this;
    this.showPanel(this.$mainPanel, function() { me.readyForm() });
};

LoginBox.prototype.readyForm = function() { 
    var me = this;
    this.$pwfield = $('#mini-login-pw');
    this.$pwfield.val('').unbind('keyup').bind('keyup', 
        function(evt) { return me.handlePasswordKeypress(evt); }
    );
        
    this.handlePasswordKeypress(null);
    
    var $em = $('#mini-login-email');
    if ($em[0])
        $em[0].focus();
};

LoginBox.prototype.handlePasswordKeypress = function(evt) { 
    if (!this.$pwfield)
        this.$pwfield = $('#mini-login-pw');
    
    var val = "" + this.$pwfield.val();
    var len = val.length;
    
    // 320 is width of image.
    var offset = 16*len - 320;
    
    this.$pwfield.css('background-position', offset + 'px 4px');
    this.$pwfield.css('background-position-x', offset + 'px');
    
    return true;
};

LoginBox.prototype.handleAjaxSubmit = function() { 
    var me=this;
    
    this.hidePanel(this.$mainPanel);
    this.showPanel(this.$throbber);
    
    var inputs = {
        'authenticity_token': $('#mini-login-auth').val(), 
        'user_session[email]' : $('#mini-login-email').val(), 
        'user_session[password]' : $('#mini-login-pw').val()
    };
    
    $.ajax({
        url: '/b3/user_sessions/create.json',
        method: 'post',
        dataType: 'json',
        data: inputs, 
        success: function (j) { return me.handleLoginResponse(j); }
    });

    return false;
}

LoginBox.prototype.hidePanel = function ($p) { 
    if ($p)
        $p.hide('drop', { direction: 'left', mode: 'hide' }, 400);
    return undefined;
};

LoginBox.prototype.showPanel = function ($p, fn) { 
    if (!fn)
        fn = function() { };
    
    if ($p)
        $p.show('drop', { direction: 'right', mode: 'show' }, 400, fn);
    return undefined;
};

LoginBox.prototype.handleLoginResponse = function (response) { 
    var me = this;
    
    if (response.status=='success')
    {
        $('#login-box-close-button').unbind('click').click(function() { 
            window.location.reload();
        });

        $.get('/b3/account/after_login', {}, function (x) {
            me.handleAfterLogin(x);
        });
        
    } else {
        this.hideThrobber();
        
        var $err = $('<div class="login-failed">').text(
            response.message ? response.message : "Login error.");
        
        $('#mini-login-messages').empty().append($err);
        
        this.showPanel(this.$mainPanel, function() { me.readyForm(); });
    }
    
    return undefined;
};

LoginBox.prototype.handleAfterLogin = function (x) { 
    this.$innerBox.empty();
    var $al = $(x);
    $al.addClass('login-box-contents').css('display: none');
    this.$innerBox.append($al);
    $al.show('drop', { direction: 'up', mode: 'show' }, 800);
    
};

LoginBox.prototype.makeThrobber = function () { 
    var $t = $('<div class="login-box-contents" id="login-box-throbber"><img src="/images/throbbers/blue-circle.gif" alt="loading..." /></div>');
    $t.css('display: none');
    return $t;
};

function BBBPage() {
    this.foo=1;
    this.initPage();
    return this;
}


BBBPage.prototype.initPage = function () {
    var me = this;
    //    this.initLegacyHeader();
    try { this.initNewHeader(); } catch (e) {  console_log(e); }
    try { this.initFancyBoxen(); } catch (e) { console_log(e);  }
    try { this.initTabs(); } catch (e) { console_log(e);  }
    try { this.initPopupLinks(); } catch (e) { console_log(e); }
    try { this.initRolloverImages(); } catch (e) {  console_log(e); }
    try { this.initMiscFields(); } catch (e) { console_log(e);  }
    try { this.showRandomQuote(); } catch (e) { console_log(e);  }
    try { 
        window.footerFeedback = new FooterFeedbackForm('new-footer-feedback');
        this.initLogin();
    } catch (e) {  
        console_log(e);
    }


    return this;
}

BBBPage.prototype.initLogin = function () {
    var me = this;
    if (window.location.href.indexOf('login') > 0)
    {
        $('#top-login').show(0);
    }

    $('#top-login-link').click(function() { 
        me.loginBox = new LoginBox({}); 
    }).attr('href', 'javascript:void(0)');
};

BBBPage.prototype.initTabs = function () {
    $('.standard-tabs').each(function () {
        $(this).tabs({});
    });
};

BBBPage.prototype.initMiscFields = function () {
    // clicking on a '' textarea makes the grey go away
    $('input.with-prompt,textarea.with-prompt').focus(function() {
        var $f=$(this);
        $f.removeClass('');
        if ($f.val() == $f[0].defaultValue)
            $f.val('');
    });

    $('#site-search-field').focus(function() {
        if (this.value==this.defaultValue)
            this.value="";
    }).blur(function() {
        if (this.value=="")
            this.value=this.defaultValue;
    });
};

BBBPage.prototype.initRolloverImages = function () {
    var me = this;
    $('.rollover-image').hover(function () { 
        return me.handleImageRollover(this, true);
    }, function () {
        return me.handleImageRollover(this, false);
    });
};

BBBPage.prototype.showRandomQuote = function() {
    var quote = this.getRandomQuote();
    if (!quote)
        quote = this.getRandomQuote();

    $('#footer-wts-quote').empty().text(quote.quote);
    $('#footer-wts-sig').empty().html('&mdash; ' + quote.author);
};

BBBPage.prototype.getRandomQuote = function() {
    var qlist = window.BBB_RANDOM_QUOTES;
    if (qlist)
    {
        var qid = Math.floor( qlist.length * Math.random());
        var q = qlist[qid];
        if (q && q.length>1)
        {
            return { quote: q[0], author: q[1] };
        }
    }
    return null;
};

BBBPage.prototype.handleImageRollover = function (img, whichway) {
    var $img = $(img);
    var src = $img.attr('src');
    if (!src)
    {
        $img = $img.find('img');
        src = $img.attr('src');

    }

    if (src)
    {
        var dot = src.lastIndexOf('.');        
        var basename = src.substring(0,dot);
        var ext = src.substring(dot);

        // in any case, trim -ro suffix from basename.
        var ropos = basename.lastIndexOf('-ro');
        if (ropos && ropos >= basename.length - 3)
            basename = basename.substr(0,ropos);

        // and re-add, if needed
        if (whichway)
            $img.attr('src', basename + '-ro' + ext);
        else
            $img.attr('src', basename + ext);
    } 

    return false;
};

BBBPage.prototype.initPopupLinks = function () {
    var me = this;

    $('.popup-link').click(function() { 
        return me.handlePopupLink(this);
    });
};


BBBPage.prototype.handlePopupLink = function (link) {
    var $link = $(link);

    var callbackPopup = popupLarge;
    if ($link.hasClass('popup-small'))
        callbackPopup = popupSmall;
    else if ($link.hasClass('popup-huge'))
        callbackPopup = popupHuge;
    else if ($link.hasClass('popup-tall'))
        callbackPopup = popupTall;
        
    if (callbackPopup)
    {
        callbackPopup(link, 'bbbpop');
    } else {
        window.open(link);
    }
    return false;
};

BBBPage.prototype.initLegacyHeader = function () {
    // legacy stuff
    this.hoverlinks = $('#logo-box a,#top-nav a');
    this.hoverimages = this.hoverlinks.find('img');

    this.hoverlinks.hover(
        function(e) { me.highlightNavLink(e, true) },
        function(e) { me.highlightNavLink(e, false) }
    );
};

BBBPage.prototype.initNewHeader = function () {
    var me = this;

    // NEWSTUFF
    $('#top-search-field').bind('focus', function(evt) {
        if (this.defaultValue==this.value)
            this.value='';
    });


    $('.toplink').hover(
        function() { return me.hoverTopLink(this, true); },
        function() { return me.hoverTopLink(this, false); }
    );

    $('#logo').hover(
        function() { $('#logo img').attr('src', '/images/logo/bbb-8col-shadow.png'); },
        function() { $('#logo img').attr('src', '/images/logo/bbb-8col-shiny.png'); }
    );
   $("#drop-menu").dropmenu({});


};

BBBPage.prototype.hoverTopLink = function (toplink, isActive) {
    var $backing = $('#' + toplink.id.replace('toplink-', 'wraplink-'));

    /*
     * Jquery will only 'animate' a position that's a simple number (or number + px); 
     * it can't figure out how to parse anything else.

     * MSIE has no 'backgroundPosition: X Y', but it has backgroundPositionY.
     * Firefox has only the combined property, not the individual ones.
     */
    var yOffset = isActive ? '0' : '50';
    if ($.browser.msie)
    {
        $backing.stop().animate(
			{ backgroundPositionY: yOffset + 'px' },
			{ duration: 200 }
        );
    } else {
        $backing.stop().css('background-position',  '0 ' + yOffset + 'px');
    }

    return undefined;
};

BBBPage.prototype.initFancyBoxen = function () {
    // fancybox - used on the ring picker page
    try {
        var me = this;

       $('.fancybox-link').fancybox({
          zoomSpeedIn: 0,
          zoomSpeedOut:0,
          overlayShow: true,
          transitionIn: 'none',
          speedIn: 0, speedOut:0 //, 
          //onStart: function () { console.log("fb start"); },
          //onCleanup: function () { console.log("fb clean"); },
          //onClosed: function () { console.log("fb close"); }
       });

       $('.big-fancybox-link').fancybox({
          width: 800, 
          height: 800, 
            autoDimensions: false, 
          zoomSpeedIn: 0,
          zoomSpeedOut:0,
          overlayShow: true,
          transitionIn: 'none',
          speedIn: 0, speedOut:0 //, 
          //onStart: function () { console.log("fb start"); },
          //onCleanup: function () { console.log("fb clean"); },
          //onClosed: function () { console.log("fb close"); }
       });

        //    $(this).fancybox({ hideOnOverlayClick: true, enableEscapeButton: true , onStart: function() { console.log('fb start'); }, onClosed: function() { console.log('fb close'); }
    } catch (ex) {
        alert('fb setup error' + ex);
    }
};


BBBPage.prototype.clearNavLinks = function() {
    this.hoverimages.each(function () { 
        if (this.src)
            this.src = this.src.replace('-over\.', '.');
    });
};

BBBPage.prototype.highlightNavLink = function (e, state) {
    this.clearNavLinks();
    if (state)
    {
        var img = e.target ? e.target : e;
        if (img && img.src)
        {
            img.src = img.src.replace('.gif', '-over.gif'); 
        } 
    }
    return void(0);
};



$(document).ready(function() {
    try {
        window.bbbpage = new BBBPage();
    } catch (ex) {
        alert("error initializing page: " + ex);
    }
});

