function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (typeof value.length === 'number' &&
                    !(value.propertyIsEnumerable('length')) &&
                    typeof value.splice === 'function') {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}


if(!window.BN){
	window.BN={};
}


BN.imageHost = 'images.barnesandnoble.com';


//Enclosing and protecting all symbolds, use BN for link to outside world
(function($){   

	
BN.getLibrary=function(libName){
	if( !(BN.Has) || !(BN.Has[libName])){
		$(document).append('<script type="text/javascript" src="http://images.barnesandnoble.com/presources/js/'+libName+'.js"></script>');
	}
}


BN.uniqueId=function(){
   var newDate = new Date;
   return newDate.getTime()+ BN.uniqueId.inc++;
}
BN.uniqueId.inc=0;



})(jQuery); // end of enclosure

(function($){   
	/*all functions defined within this block are within the scope of this annonymous function */
//	                                       JQUERY Extensions- later extract to separate file
//***********************************************************************************************************************************************

					//All code that extends JQuery goes in the sections below

//********************************************************************************************
//									Chainable Extensions
//********************************************************************************************

				//Chainable extinsions are defined here (they return this)

//**********************************
//	functions: togglers
//**********************************
	//Options:
	//	contentSelector - selector that identifies toggleable content
	//  clickSelector - selector that identifies the control that toggles the content.
	//  speed - rate at which content appears and disappears - optional
	//  showText - text that should be present within the control when content is hidden - and replaced with,optional
	//  hideText - when content is shown. and vice versa ,optional
var maketoggle = function(contentSelector,rev,showText,hideText,speed){
	showText = (showText)?showText:'show';
	hideText = (hideText)?hideText:'hide';
	var rate = (speed)?speed:'normal';
	var toAffect = contentSelector;
	if(rev != true){
		$(this).toggle(
			function(){
				$(toAffect).each(function(){$(this).hide(rate)});
				$(this).html($(this).html().replace(hideText,showText).replace(hideText.charAt(0).toUpperCase() + hideText.substr(1),showText.charAt(0).toUpperCase() + showText.substr(1)));
			}, /*end toggle param 1 */
			function(){
				$(toAffect).each(function(){$(this).show(rate)})
				$(this).html($(this).html().replace(showText,hideText).replace(showText.charAt(0).toUpperCase() + showText.substr(1),hideText.charAt(0).toUpperCase() + hideText.substr(1)));
			}/*end toggle param 2 */);/*close toggle */
	}else{
		$(this).toggle(
			function(){
				$(toAffect).each(function(){$(this).show(rate)})
				$(this).html($(this).html().replace(showText,hideText).replace(showText.charAt(0).toUpperCase() + showText.substr(1),hideText.charAt(0).toUpperCase() + hideText.substr(1)));
			}, /*end toggle param 1 */
			function(){
				$(toAffect).each(function(){$(this).hide(rate)});
				$(this).html($(this).html().replace(hideText,showText).replace(hideText.charAt(0).toUpperCase() + hideText.substr(1),showText.charAt(0).toUpperCase() + showText.substr(1)));
			}/*end toggle param 2 */);/*close toggle */
	}
	return this;
};


var togglewith = function(clickSelector,rev,showText,hideText,speed){
	showText = (showText)?showText:'show';
	hideText = (hideText)?hideText:'hide';
	var rate = (speed)?speed:'normal';
	var toAffect = this;
	if(rev != true){
		$(clickSelector).toggle(
			function(){
				$(toAffect).each(function(){$(this).hide(rate)});
				$(this).html($(this).html().replace(hideText,showText).replace(hideText.charAt(0).toUpperCase() + hideText.substr(1),showText.charAt(0).toUpperCase() + showText.substr(1)));
			}, /*end toggle param 1 */
			function(){
				$(toAffect).each(function(){$(this).show(rate)})
				$(this).html($(this).html().replace(showText,hideText).replace(showText.charAt(0).toUpperCase() + showText.substr(1),hideText.charAt(0).toUpperCase() + hideText.substr(1)));
				}/*end toggle param 2 */);/*close toggle */
	}else{
		$(clickSelector).toggle(
			function(){
				$(toAffect).each(function(){$(this).show(rate)})
				$(this).html($(this).html().replace(showText,hideText).replace(showText.charAt(0).toUpperCase() + showText.substr(1),hideText.charAt(0).toUpperCase() + hideText.substr(1)));
				}, /*end toggle param 1 */
			function(){
				$(toAffect).each(function(){$(this).hide(rate)});
				$(this).html($(this).html().replace(hideText,showText).replace(hideText.charAt(0).toUpperCase() + hideText.substr(1),showText.charAt(0).toUpperCase() + showText.substr(1)));
			}/*end toggle param 2 */);/*close toggle */
	}			
	return this;
}


var inject = function(obj){
	$(this).each(function(){
		for(var x in obj){
			var nam = x;
			var typ ='markup';
			if(x.substr(0,4)=='href'){
				nam = x.substr(4);
				typ = 'href';
			}
			var dest = $('.'+nam,this);
			if(dest.get().length == 0){
				dest=$('#'+nam);
				if(dest.get().length == 0){
					dest='';
				}
			}
			if(dest != ''){
				if(typ != 'markup'){
					dest[typ](obj[x]);
				}else{
					dest.html(obj[x]);
				}
			}else{
				obj[handle+'x'](this);
			}
		}
	});
	return this;
}



var extract = function(obj){
	$(this).children().each(function(){
		var nam = (this.id) ? this.id : $(this).attr('class');
		//alert(nam);
		obj[nam]=$(this).html();		
	});
	return this;
}

// the idselector must be a unique node
var hoverCopyFrom=function(idSelector){
	$(this).each(function(){
		var instanceClass;
		var clearPopup=null;
		$(this).hover(function(){
			if(clearPopup){
				clearTimeout(clearPopup);
				$(instanceClass).remove();
			}
			instanceClass='openHoverItem';
			var content = $(idSelector).clone();
			content.appendTo('#cloneSafe'); //ie clone fix cannot apply attribute to elment that is not inside the dom
			content.addClass(instanceClass);
			$(this).after(content);
			content.show();
		},function(){
			instanceClass='.'+instanceClass; //reusing variable, usage from here needs to have a '.';
			var removePopup=function(){
				$(instanceClass).remove();
			};
			
			clearPopup = setTimeout(removePopup, 100);
			$(instanceClass).hover(function(){
				clearTimeout(clearPopup);
			}, removePopup);
		});
	});
};
// This hods keys that represent things that must occur for each domitem. Each key contains the domitems under which the key's "action" has been invoked.
var uniqueProcessingKeyStore={};
var once=function(unqKey){
		
	var key='once_'+unqKey;
	var unqDomItems=(uniqueProcessingKeyStore[key])?uniqueProcessingKeyStore[key]:(uniqueProcessingKeyStore[key]={});
	return  $(this).filter(function(){
		var processed = $(this).attr('processed');
		if(typeOf(processed)=='null'){
			var processed = 'bnid'+BN.uniqueId();
			$(this).attr('processed',processed);
		}
		
		var ran=false;
		for(var domItem in unqDomItems){
			if(domItem == processed){
				ran=true;
				break;
			}
		}
				
		if(!ran){
			unqDomItems[processed]=true;
		}
		return !(ran);
	});
}


//********************************************************************************************
//									Non-Chainable Extensions
//********************************************************************************************

		//utility extinsions are defined here

var data=function(str){
	if($(this).get().length == 0){
		return this['data-'+str];
	}else{
		var arr=[];
		$(this).each(function(){
			arr[arr.length]= this['data-'+str];	
		});
		return arr;
	}
}







//********************************************************************************************
//									Code to extend jquery here
//********************************************************************************************
		//actual extending of jquery goes here - give extend jquery object - making the methods accesible outside of this annonymous function
$.fn.makeToggle = maketoggle;
$.fn.toggleWith = togglewith;
$.fn.inject = inject;	
$.fn.extract = extract;
$.fn.data = data;
$.fn.hoverCopyFrom = hoverCopyFrom;
$.fn.once=once;


//************************************************************************************************************
// End plugin section here
})(jQuery);
//*******
