/************************************************************************
 * Define the global Blurb module/object. 
 */
if (typeof Blurb == "undefined"){ var Blurb = {}; }
/**
 * A global JavaScript error handler. 
 * Can be passed the Exception object that was thrown as the first argument.
 */
Blurb.handle_exception = function () {
    var msg = 'An unexpected JavaScript error occurred. Please contact Blurb support.';
    var e   = arguments[0];
    if (e) msg += '\n\nerror: ' + e.toString();
    alert(msg);
    if (e) throw e;
};


/************************************************************************
 * A module for utility functionality used throughout and built upon in Blurby.
 */
Blurb.Util = {};

/**
 * True if the given link is part of the BLURB.COM domain (blurb.com or any 
 * subdomain thereof).
 */
Blurb.Util.isLocalUrl = function (url_string) {
    if (!url_string || url_string.length < 1) return null;
    base_domain_pattern = /^http[s]{0,1}\:\/\/[a-z0-9-\.]*(blurb.com)/i;
    m = url_string.match(base_domain_pattern);
    if (m && m[1]) return true; // match found - it is a local URL
    return false; // no match - not a local URL
};

/*return the value of the given GET parameter 'name' in the current url request*/
Blurb.Util.getParam = function( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

/**
 * True if the given link is part of the same domain the 
 * user is currently on.
 */
Blurb.Util.isSameDomain = function (url_string) {
	if (!url_string || url_string.length < 1) return null;
//check if it is a blurb.com domain
	b = url_string.match("blurb.com");
	if (b && b[0]) return true; // link is part of the blurb.com domain so no need to track links
    m = url_string.match(location.host);
    if (m && m[0]) return true; // match found - it is a local URL (used for a catch for custhelp site)
    return false; // no match - not a local URL - send utmLinker onClick to not track as refferal
};


/************************************************************************
 * A module for functionality related to Google Analytics (GA).
 */
Blurb.GA = {};

/**
 * Sets the onClick handler to prevent referrals from being counted for links to 
 * Blurb's 3rd party domains sites such as blurb.custhelp.com.
 * The "this" keyword is available thanks to Prototype's bindAsEventListener method.
 */
Blurb.GA.doClickForExtneralLink = function () {
    try{
        pageTracker._link(this.href);
    }
    catch (e) {}; return true; // fail quietly to allow the link to function regardless.
};

/**
 * This function serves the purpose of preventing referrals between blurb.com and our
 * non-blurb.com domains that we do not wish to count as refferals.
 * Works by applying the doClickForExtneralLink function to the click event of 
 * external-pointing links. Does not matter which site the external link points to because
 * the receiving GA code on should behave accordingly.
 */
Blurb.GA.normalizeReferrals = function () {
    var all_links = $$('a');
    all_links.each( function (item) {
        if (!Blurb.Util.isSameDomain(item.href)) {
            Event.observe(item, 'click', Blurb.GA.doClickForExtneralLink.bindAsEventListener(item));
        }
    });
};


/************************************************************************
 * various other javascripts..
 */

/*
 * Used for SideBar to toggle images
 */
var h = [];

function sideBarToggleImage(element) {
    e = $(element);

    if (h[element] != undefined) {
        if (h[element]) {
            e.style.backgroundPosition = "left top";
            h[element] = false
        } else {
            e.style.backgroundPosition = "right top";
            h[element] = true
        }
    } else {
            e.style.backgroundPosition = "right top";
            h[element] = true
    }
}

// the form elements are popped on the FORM array in reverse order, hence the num_element subtraction.
// if all elements are filled, give focus to the first element.
function give_form_focus(form_element)
{
  try {
    var formObj = $(form_element);
	var num_elements = formObj.length;
    var focusGiven = false;
	for (i=0; i<formObj.length; i++)
    {
    	if (formObj[num_elements-(i+1)].value == '')
    	{
			
			formObj[num_elements-(i+1)].focus();
    		focusGiven = true;
    	}
    }
    if (!focusGiven)
		formObj[0].focus();
  } catch (e) {} // fail silently
}



/*=========================================================================
 * Tooltip
 *=========================================================================*/
var fade_rate = 0.5;

function toggle_tooltip_element(element_id, evt, offset_x, offset_y)
{
  try {
	/* hide all open tooltips first */
	var hideThese = document.getElementsByClassName("tooltipDialog");
	for (i = 0; i < hideThese.length; i++) {
		hideThese[i].style.display = 'none';
	}
	/**/
	obj = $(element_id);
    
    /**
     * The conditional browser type vars come from browser_detect.js.
     * Special handling for IE on 2 counts:
     * - there is no equivalent for the position pageX or pageY as in other browsers
     * - Blurb uses STRICT markup, which requires the use of document.documentElement...
     */
    if (is_ie) // IE is  special
    {
      obj_x = evt.clientX + document.documentElement.scrollLeft + offset_x;
      obj_y = evt.clientY + document.documentElement.scrollTop + offset_y;
    }
    else // other browsers can handle it
    {
      obj_x = evt.pageX + offset_x;
      obj_y = evt.pageY + offset_y;
    }
    if(  !obj.style.left ){
      obj.style.left = obj_x + "px";
    }
    obj.style.top = obj_y + "px";

    Effect.toggle(obj, 'appear', {duration:fade_rate});
  } catch (e) {} // fail silently
}

function hide_tooltip_element(element_id) {
  try {
    Effect.Fade($(element_id), {duration:fade_rate});
  } catch (e) {} // fail silently
}


/*=========================================================================
 * Cursor
 *=========================================================================*/
function cursor_wait(element) {
	actual_cursor_wait(element);
}

function cursor_clear(element) {
	actual_cursor_clear(element);
}

// Changes the cursor to an hourglass
function actual_cursor_wait(element) {
    if (element) element.style.cursor = 'wait';
}

// Returns the cursor to the default pointer
function actual_cursor_clear(element) {
  	if (element) element.style.cursor = 'default';
}

// new style spinner - uses a hidden div called 'spinner' 
// and moves it to the even coordinates before shoping it.
function spinner_cursor_wait(element) {	
	if (!element) return;
	e = Try.these(
	    function() { return $(element) }
    ) || false;
	    
	s = $('spinner');
	if (s && e) { 
		var position = Position.cumulativeOffset(e)
		s.style.left = (position[0] - 25) + "px";
		s.style.top =  (position[1] - 2) + "px";
		s.show();
	}
}

function spinner_cursor_clear(element) {
	s = $('spinner')
	if (s && s.visible) s.hide()
}


// CSS Browser Selector   v0.2.5
// Documentation:         http://rafael.adm.br/css_browser_selector
// License:               http://creativecommons.org/licenses/by/2.5/
// Author:                Rafael Lima (http://rafael.adm.br)
// Contributors:          http://rafael.adm.br/css_browser_selector#contributors
var css_browser_selector = function() {
	var 
		ua=navigator.userAgent.toLowerCase(),
		is=function(t){ return ua.indexOf(t) != -1; },
		h=document.getElementsByTagName('html')[0],
		b=(!(/opera|webtv/i.test(ua))&&/msie (\d)/.test(ua))?('ie ie'+RegExp.$1):is('gecko/')? 'gecko':is('opera/9')?'opera opera9':/opera (\d)/.test(ua)?'opera opera'+RegExp.$1:is('konqueror')?'konqueror':is('applewebkit/')?'webkit safari':is('mozilla/')?'gecko':'',
		os=(is('x11')||is('linux'))?' linux':is('iphone')?' iphone':is('mac')?' mac':is('win')?' win':'';
	var c=b+os+' js';
	h.className += h.className?' '+c:c;
}();

// Display warning if entering PO/APO/FPO Box address
function warnIfPostOfficeBox(addr, po_box_checked)
{
  var match = /^\s*(P\.?\s*O\.?\s*Box|[AF]\.?\s*P\.?\s*O\.?(\s*Box)?)/i;
  var is_po_box = match.test(addr);
  if (is_po_box && !po_box_checked ) {
    alert("It appears that you're trying to ship to a PO Box, UPO or APO address.  If so, please check the box just above Address Line 1 and click Save.  If not, simply continue by clicking Save." );
  }
  return is_po_box;
}



/**
 * this handles the character countdown/limitation for textarea fields by 
 * truncating the value of the textarea once the limit specified has been exceeded.
 */
function limitAnswer(limitField, limitCount, limitNum)
{
	if( limitField )
	{
		if (limitField.value.length > limitNum) {
			limitField.value = limitField.value.substring(0, limitNum);
			limitField.scrollTop = limitField.scrollHeight - limitField.clientHeight;
		}
		updateLimitCounter(limitField, limitCount, limitNum);
	}
}
/**
 * handles updating the character countdown display with the new text length of the textarea.
 */
function updateLimitCounter(limitField, limitCount, limitNum)
{
    x = limitNum - limitField.value.length;
    // js and rb count chars and line breaks differently, so root this at zero
	limitCount.innerHTML = (x < 0? 0: x);
}


var TabSwitcher = Class.create({
  // Sets up tab switching behavior for the tabs in the given +tab_group+.
  // Expects +tab_group+ to contain tabs and their associated panes.
  //
  // A +tab+ is a 'li' element, contained in a wrapper with the 'tabs' class.
  // Each tab should have an 'a' link within it.  Clicks on this link will
  // switch to the appropriate pane, hiding the other panes.  Clicks will also
  // give the tab the "selected" class, to allow styling.
  //
  // A tab's +pane+ is an element whose id is tab.id + '_pane'.
  //
  // Depends on Prototype.
  //
  // To maintain functionality when JS is disabled, the tab's anchor can 
  // reference a named anchor in the appropriate pane.
  //
  // Example:
  //
  // <div id="add_to_cart_tab_group">
  //   <div class="tabs">
  //     <ul>
  //       <li id="store_price" class="selected"><a href="#store-price">Store Price</a></li>
  //       <li id="my_price"><a href="#my-price">My Price</a></li>
  //     </ul>
  //   </div>
  //   <div>
  //     <div id="store_price_pane">
  //       <a name="store-price"></a>
  //       ... store price pane ...
  //       See <a href="#my-price">personal prices</a>. <!-- optional -->
  //     </div>
  //     <div id="my_price_pane">
  //       <a name="my-price"></a>
  //       ... my price pane ...
  //     </div>
  //   </div>
  // </div>
  //
  // <script type="text/javascript" charset="utf-8">
  //   new TabSwitcher($('add_to_cart_tab_group'))
  // </script>
  initialize: function(tab_group, default_tab) {
    this._tabs = tab_group.select('.tabs li');
    this._panes = this._tabs.map(function(tab) { return this.pane_for_tab(tab) }.bind(this));
    this._default_tab = $(default_tab) || this._tabs.first();

    this._tabs.each(this.observe_tab.bind(this));

    var initial_url_anchor = tab_group.select('a[href="' + window.location.hash + '"]').first();
    this.switch_to(initial_url_anchor ? initial_url_anchor.up('li') : null);
  },

  switch_to: function(tab) {
    var tab = $(tab) || this._default_tab;
    this.select_tab(tab);
    this.switch_to_pane(this.pane_for_tab(tab));
    return false;
  },
  
  select_tab: function(tab) {
    this._tabs.invoke('removeClassName', 'selected');
    tab.addClassName('selected');
  },

  switch_to_pane: function(pane) {
    this._panes.invoke('hide');
    pane.show();
  },

  observe_tab: function(tab) {
    // Make clicks on anchors anywhere in the page invoke TabSwitcher.switch_to.
    this.links_to_tab(tab).each(function(link) {
      link.observe('click', this.switch_to.bind(this, tab));
    }.bind(this));
    
    // Stop jumping to anchors, so tab switches don't scroll the page as much.
    this.anchors_from_tab(tab).invoke('remove');
  },
  
  pane_for_tab: function(tab) {
    return $(tab.id + '_pane');
  },

  // All anchors, anywhere on the page, that link to a +tab+.  Of course,
  // this includes the anchors in the tabs themselves.
  // These anchors will each get an observer that invokes switch_to, 
  // so you can switch to a tab from anywhere on the page, not just from
  // clicks on the tabs.  For example, to jump to the Author Bookshelf tab
  // from within the About Book pane, add:
  //   <a href="#author-bookshelf">All books by author</a>
  links_to_tab: function(tab) {
    // IE needs the $, otherwise add-to-cart tabs are broken after
    // any Ajax request that updates add-to-cart.
    return $$('a[href$="#' + this.hash_for_tab(tab) + '"]');
  },
  
  anchors_from_tab: function(tab) {
    return $$('a[name="' + this.hash_for_tab(tab) + '"]');
  },
  
  hash_for_tab: function(tab) {
    return tab.down('a').href.split('#').last();
  }
})


function initTruncateExpand() {
  $$('span.truncate_expand').each(function(element) {
    var see_more_link = new Element('a', { href: '#' }).update("…");
    element.insert({ before: see_more_link })
    var empty_span = new Element('span').update(' ')
    see_more_link.insert({ before: empty_span })
    see_more_link.observe('click', function(clickEvent) {
      see_more_link.remove()
      empty_span.remove()
      element.show()
      clickEvent.stop()
    }.bindAsEventListener(this))
    element.hide()
  })
}

var BlurbMenu = Class.create();

BlurbMenu.prototype = {
	
	// initialize()
	// Constructor runs on completion of the DOM loading. Loops through span tags looking for 
	// 'dv' references and applies fills the span with the corresponding dynamic value
	initialize: function() {
		if (!document.getElementsByTagName){ return; }
		var spans = document.getElementsByTagName('span');
		var authenticated = this.seemsAuthenticated();
		// loop through all spans tags
		for (var i=0; i<spans.length; i++){
			var span = $(spans[i]);
			var relAttribute = String(span.getAttribute('rel'));
			
			// use the string.match() method to catch 'dv' references in the rel attribute
			if ( relAttribute.toLowerCase().match('dv') ){
				dynamicValue = this.getMenuVaule(span.id)
				if( dynamicValue ){
					span.update(dynamicValue);
					$(span).show
				}
			}else if ( relAttribute.toLowerCase().match('dm') ){
				//for each dynic meny item type, show it if it has given class
				if( span.hasClassName('authenticated') ){
					(authenticated) ? this.show(span) : this.hide(span);
				}
				if( span.hasClassName('notAuthenticated')){ 
					(!authenticated ) ? this.show(span) : this.hide(span);
				}
				if( span.hasClassName('hasCart') && this.hasCartItems() ){ 
					this.show(span);
				}
				if( span.hasClassName('syp')){ 
					( this.isSypUser ) ? this.show(span) : this.hide(span);
				}
				if( span.hasClassName('noSyp')){ 
					( !this.isSypUser  ) ? this.show(span) : this.hide(span);
				}
				
			}
			
		}
	},
	
	getMenuVaule: function(name){
		var data = JSON.parse(unescape(Cookie.get('dm')));
		if(!data) data = {};
		return ( data[name] ) ? data[name].toString().gsub(/\+/, ' ') : null;
	},
	
	hasCartItems: function(){
		cartString = this.getMenuVaule('cart_count');
		if(cartString && cartString.charAt(0) != '0'){
			 return true;
		}else{
			return false;
		}
	},
	
	isSypUser: function(){
		return this.getMenuVaule('syp_member');
	},

	seemsAuthenticated: function(){
		return this.getMenuVaule('username') != null && this.getMenuVaule('username') != '' ? true : false;
	},
	
	show: function(element){
		if( element.hasClassName('hide')){element.removeClassName('hide');}
		if(!element.hasClassName('show')){element.addClassName('show');}
	},
	
	hide: function(element){
		if( element.hasClassName('show')){element.removeClassName('show');}
		if(!element.hasClassName('hide')){element.addClassName('hide');}
	}
}

function ceTrack(){
	var ce = Blurb.Util.getParam("ce");
	if(ce.length > 0){
		new Ajax.Request('/home/ce_track?ce=' + ce, {method: 'post',asynchronous:true});
	}
}

function initBlurbMenu() { myBlurbMenu = new BlurbMenu(); }
Event.observe(window, 'load', initBlurbMenu, false);
Event.observe(window, 'load', ceTrack, false);



// call this function with the onsubmit of a form tag,
// any input buttons with class='to_disable' will
// disable preventing double clicks
function disable_submit(form)
{ 
  // form.disable() - looks cool, but messes up form submission
  // disabled form elements can't be serialized

  // only disable this form's submit elements, not
  // every form on the page
  var to_disable = $(form).select('input.to_disable'); // $(form) required for IE; bare form won't work
    
  to_disable.each(function(e)
  {
    e.disabled = "disabled";
    e.addClassName('disabled');
  });
  return true; // proceed with the form submission
}
