/*
 * ShopIgniter jQuery interface for direct DOM manipulation
 */

(function($) {
	$.fn.extend({
		/*-----General SI interface plug-ins----*/
		/*--------------------------------------*/
		
        //initializes pagination and loads list views
		siPaginate: function(options, callback) {
			
			// set defaults
			var defaults = {
				type : 'input',
				requestType : 'ajax',
				viewAllDefault : 'gridSmall',
				links : 'div.paginationWrapper',
				wrapperTag : 'div',
				loadingTarget : 'p.prodCount',
				currentObj : si.products,
				results	: si.products.list,
                noResults : '<p class="noResults">No Products Found</p>',
				resultsMessage : '<span class="productsFound">{results_total}</span> products found in {results_title}'
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			si.paginate.target				= '#' + this.attr("id"); //TODO, we really should pass the object(this), but everything will need to be set up that way... product.search, etc.
			si.paginate.target_links 		= opts.links;
			si.paginate.type 				= opts.type;
			si.paginate.request_type 		= opts.requestType;
			si.paginate.view_all_type 		= opts.viewAllDefault;
			si.paginate.current_obj 		= opts.currentObj;
			si.paginate.results 			= opts.results;
			si.paginate.target_loading  	= opts.loadingTarget;
			si.paginate.wrapper_tag			= opts.wrapperTag;
			si.paginate.results_found		= opts.resultsMessage;
			si.paginate.no_results_label    = opts.noResults;
			if (typeof callback == 'function') {
				si.paginate.callback = callback;
			}
			
			// set the view mode
			si.paginate.view_mode = si.view.mode;
			
			si.paginate.init();
			
			return this;
		},
		
		//toggle between list view layouts
		siViewToggle: function(options) {
			
			// set defaults
			var defaults = {
				linkWrapper : 'ul'
			}
			
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				
                //activate the proper icon based on admin settings
                if( $(this).attr('rel') == si.paginate.data['view_type']) {
                    $(this).addClass('active');
                }
                
				$(this).click (function(){
					// remove previous active class
					$(this).parents(opts.linkWrapper).find(".active").removeClass("active");
					
					// set the view type
					var view_type = $(this).attr('rel');
					if (view_type != '') {
						si.paginate.view_type = view_type;
					}
					
					// clear the view mode (no view all for toggle)
					si.paginate.view_mode = '';
					
					if (si.paginate.request_type == 'local') {
						// set the loading state, add active class,
						$(this).addClass("active");
						si.paginate.data.per_page = si.settings.page_limits[si.paginate.view_type]; // set per page based on view type
						si.paginate.cur_page = 0;
						si.paginate.per_page = si.settings.page_limits[si.paginate.view_type];
						si.paginate.init();
					} else {
						// set the loading state, add active class,
						$(this).addClass('loading active');
						si.paginate.check_request_method('', $(this));
					}
					
					return false;	
				});
				
				return $(this);	
			});
		},
		
		// sitewide hints for input fields
		siHint: function() {
			return this.each(function(){
				var t = $(this);
				var title = t.attr("title");
                
				if(title != '') {
                    // on blur, set value to title attr if text is blank
                    t.blur(function (){
                      if (t.val() == '') {
                        t.val(title);
                        t.addClass('blur');
                      }
                    });
                    
                    // on focus, get rid of hint text
                    t.focus(function (){
                      if (t.val() == title) {
                        t.val('');
                        t.removeClass('blur');
                      }
                    });
                      
                    // clear the pre-defined text when form is submitted
                    t.parents('form:first').submit(function(){
                        if (t.val() == title) {
                            t.val('');
                            t.removeClass('blur');
                        }
                    });
                      
                    if (t.val()=="" || t.val() == title) { 
                      // blur all
                      t.blur();
                    }
                }
				return $(this);
			});
		},
        
        siDropdown: function(options) {
            // set defaults
			var defaults = {
				arrows : false,
                delay : 800
			}
			
			var opts = $.extend(defaults, options);
            
            return this.each(function(){
                var menuList = $(this);
                    
                    $(document).bind("click.hideMenu", function(e){
                        menuList.find('ul').clearQueue().hide();
                    });
                    
                    menuList.find('li').each(function(){
                      
                        if($(this).is(":has('ul')") && opts.arrows) {
                            $(this).addClass("children").prepend("<span></span>");
                        }
                        
                        $(this).mouseenter(function(){
                            menuList.find('ul').clearQueue();
                            $(this).siblings().find("ul").removeAttr('style').hide();
                            $(this).find("ul:first").delay(300).fadeIn("fast");
                        });
                        
                        $(this).mouseleave(function(){
                            menuList.find('ul').clearQueue();
                            $(this).find("ul").delay(700).fadeOut("fast");
                        });
                    });
                return $(this);
            });
        },
		
		// hide target elements that exceed the width of their parents
		siHideOverflow: function(options) {
			// set defaults
			var defaults = {
				target: 'li',
				menuWrapper: '<ul></ul>',
				targetWrapper: '<li></li>'
			}
			
			//extend defaults with provided options and declare vars
			var opts = $.extend(defaults, options);
				
			return this.each(function(){
				
				var $target = opts.target;
				var menuWrapper = opts.menuWrapper;
				var targetWrapper = opts.targetWrapper;
				var $offsetParent = $(this).offsetParent();
				
				// save width of element we are hiding overflow on
				var containerWidth = $(this).width();
		
				// check for elements that aren't target element and subtract their widths form the avail area
				var childrenWidth = 0;
				$(this).children().not($target).each(function(){
					childrenWidth += $(this).width();
				});
				var availArea = containerWidth - childrenWidth;
				
				// calculate total with of all target elements and check against avail area, add overflow class if overflow
				var targetWidthTotal = 0;
				$(this).find($target).each(function(){
					targetWidthTotal += $(this).width();
					if (targetWidthTotal + 20 >= availArea) {
						$(this).addClass("overflow");
					}
				});
				
				//if this has overflow grab overflow elements and separate into menu
				if ($(this).is(":has('.overflow')")) {
					$(menuWrapper).addClass("overflowMenu").css("display","none").appendTo($offsetParent);
					
					var $overflowMenu = $offsetParent.find(".overflowMenu");
					var $overflow = $(this).find(".overflow");
					
					$overflow.appendTo($overflowMenu);
					$(targetWrapper).html("<a href='#' class='invisiText showOverflow' title='view more'>more</a>").appendTo($(this));
				}
				
				// add 'click outside' to hide menu
				$(this).find("a.showOverflow").click(function(){
					$overflowMenu.show();
					$(document).bind("click.overflow", function(e){
						if(!$(e.target).is(".overflowMenu")) {
							$overflowMenu.hide();
							$(document).unbind("click.overflow");
						}
					});
					return false;
				});
				return $(this);
			});
		},
		
		siSlider: function(options) {
			// set defaults
			var defaults = {
				frame: '.calloutWindow',
				slider: '.calloutStrip',
				child: 'div',
				next: '.next',
				previous: '.prev'
			}
			
			//extend defaults with provided options and declare vars
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				
				//declare vars
				var frame = $(this).find(opts.frame);
				var slider = frame.children(opts.slider);
				var child = slider.children(opts.child);
				var next = $(this).find(opts.next);
				var prev = $(this).find(opts.previous);
				var total = child.length;
				var count = 0;
				var offset = 0;
				
				//calculate total width of frame
				var frameWidth = frame.width();
				//calculate total width of the child
				var childWidth = child.outerWidth() + parseInt(child.css('marginLeft')) + parseInt(child.css('marginRight'));
				
				//show next and previous if needed (subtract marginRight once to negate any extra margin from creating nav)
				if (childWidth * total - parseInt(child.css('marginRight')) > frameWidth) {
					next.show();
					prev.show();
				}
				
				next.css('cursor', 'pointer').click(function(){
					slider.animate({marginLeft: -childWidth}, 'fast', function(){
						slider.children(child+':first').appendTo(slider);
						slider.css("marginLeft",0);
					});
				});
				
				prev.css('cursor', 'pointer').click(function(){
					//slider.find(child+':last').clone().show().prependTo(slider);
					slider.css("marginLeft",-childWidth);
					slider.children(child + ':last').prependTo(slider);
					
					slider.animate({marginLeft: 0}, 'fast');
				});
	
				return $(this);
			});
			
		},
		
		// general sitewide toggle functionality
		siToggle: function() {
			return this.each(function(){
				// find toggles target
				var toggleTarget = $(this).attr("href");
				$(this).click(function(){
					if ($(this).is(".active")) {
						// enable toggle for active 
						$(this).removeClass("active");
						$(toggleTarget).slideUp().removeClass("active");
						return false;
					}
					else {
						// enable toggle for inactive 
						$(this).addClass("active");
						$(toggleTarget).slideDown().addClass("active");
						return false;
					}
				});
				
				return $(this);
			});
		},
		
		//swaps two pieces of content amongst themselves based on the rel and href of a link
		siSwap: function(options) {
			// set defaults
			var defaults = {
				replacementText: ''
			}
			
			//extend defaults with provided options and declare vars
			var opts = $.extend(defaults, options);
			
			return this.each(function() {
				
				var replaceWith = $(this).attr("href")
				var replaceTarget = $(this).attr("rel");
				var origText = $(this).text();
				
				//set replacement text if provided
				if (opts.replacementText != '') {
					var replaceText = opts.replacementText;
				} else {
					var replaceText = origText;
				}
				
				
				$(this).toggle(
					function() {
						$(this).text(replaceText);
						
						$(replaceTarget).fadeOut('fast',function(){
							$(replaceWith).fadeIn('fast');
						});
						return false;
					},
					function() {
						$(this).text(origText);
						
						$(replaceWith).fadeOut('fast', function(){
							$(replaceTarget).fadeIn('fast');
						});
						return false;
					}
				);
				
				return $(this);
			});
		},
		
		// general sitewide message
		siMessage: function() {
			si.message_target = this;
			if (si.view.message.length > 0) {
				si.message(si.view.message);
			}
			return this;
		},
		
		// general sitewide popups/dialogs
		siPopup: function() {
			$(this).live( "click", function(){
				si.init_popup($(this));
				return false;
			});
			
			return this;
		},
		
		// toggles in sticky toolbar
		siStickyToggle: function() {
			
			//check to see if a footer pane is already open on page load
			si.checkStickyStatus();
			
			return this.each(function(){

				//attach toggle functionality
				$(this).click(function(){
			
					// find toggles target
					var toggleTarget = $(this).attr("href");
					var scrollWrapper = $(toggleTarget).find(".scrollWrapper");
					
					// set footer status
					si.setStickyStatus(toggleTarget);
					
					if ($(this).parent().is(".active")) {
						// enable toggle for active 
						$(this).parent().removeClass("active");
						$(toggleTarget).slideUp().removeClass("active stickyActive");
						return false;
					}
					else {
						// close any open tool panes
						if ($(this).parent().siblings().hasClass("active")) {
							$(this).parent().siblings("li.active").removeClass("active")
							.find(".toggleTarget").slideUp().removeClass("active");
						}
						// enable toggle for inactive 
						$(this).parent().addClass("active");
						$(toggleTarget).addClass("active").slideDown(function(){
							
							//reset existing styles if it has been resized
							scrollWrapper.height("auto").css("overflow-y","visible");
							
							//make sure it fits in the window
							if ($(toggleTarget).height() + 50 >= $(window).height()) {
								var difference = $(toggleTarget).height() - scrollWrapper.height();
								scrollWrapper.height($(window).height() - (55 + difference)).css("overflow-y","scroll");
							} 
						});
						
						return false;
					}
				});
				
				return $(this);
			});
		},
		
		//close buttons in sticky toolbar
		siStickyClose: function() {
			return this.each(function(){

				//attach close functionality
				$(this).click(function(){
					var toggleID = "#" + $(this).parents(".toggleTarget").attr("id");
					var $toggleLink = $("#stickyTools").find("a[href=" + toggleID + "]");
					$(this).parents(".toggleTarget").removeClass("active").slideUp(function(){$(this).removeClass("stickyActive");});
					// remove active class from toggle link
					$toggleLink.parent().removeClass("active");
					
					// remove footer status
					si.setStickyStatus(0);
					return false;
				});
				
				return $(this);
			});
		},
		
		
		/*-----SI loader/widget plug-ins----*/
		/*--------------------------------------*/
		
		//load store or content menu, takes a scope and/or type
		siLoadMenu: function(options) {
			// set defaults
			var defaults = {
				scope: 'store',
                from: undefined,
				contextual: false,
                hideInactive: false,
				showParent: false,
				maxDepth: undefined
			}
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			var menu = '';
			
			return this.each(function() {
				
				switch(opts.scope) {
					case 'store':
						menu = si.store.build_menu('category', opts.hideInactive, opts.maxDepth);
						if (si.brands.list.length) {
							menu += '<li class="open children"><a href="/' + si.settings.routes.brands + '">' + si.brands.name + '</a>' +
								'<ul>' + si.store.build_menu('brand', opts.hideInactive, opts.maxDepth) + '</ul></li>';
						}
						menu += si.collections.build_menu (opts.hideInactive);
						break;
					case 'content':
						if (opts.from == undefined) {
							if (opts.contextual) {
								// render only the active branch and the children of the content being displayed
								menu = si.store.build_menu_item('content', si.content.find_top_level_parent(si.content.obj), opts.hideInactive, opts.max_depth, opts.showParent);
							} else {
								// render the full content menu
								menu = si.store.build_menu('content', opts.hideInactive, opts.maxDepth);
							}
						} else {
							// render the menu from the specified content
							menu = si.store.build_menu_item('content', si.content.find_by_key(opts.from), opts.hideInactive, opts.max_depth, opts.showParent);
						}
						break;
					case 'categories':
						if (opts.from == undefined) {
							if (opts.contextual) {
								// render only the active branch and the children of the category being displayed
								menu = si.store.build_menu_item('category', si.categories.find_top_level_parent(si.store.get_cur_obj('category')), opts.hideInactive, opts.max_depth, opts.showParent);
	                        } else  {
								// render the full category menu
								menu = si.store.build_menu('category', opts.hideInactive, opts.maxDepth);
							}
						} else {
							// render the menu from the specified category
							menu = si.store.build_menu_item('category', si.categories.find_by_key(opts.from), opts.hideInactive, opts.max_depth, opts.showParent);
						}
						break;
					case 'brands':
						// renders the full brands menu
						menu = si.store.build_menu('brand');
						break;
					case 'collections':
						if (opts.from == undefined) {
							if (opts.contextual) {
								collection = si.store.get_cur_obj('collection');
								if (si.view.type == 'collection_group') {
									// render the current collection group and children
									menu = si.collections.build_menu_item(si.collections.group.obj, opts.hideInactive, true);
								} else if (collection != undefined) {
									// render the parent collection group and children
									menu = si.collections.build_menu_item(si.collections.get_collection_group(collection.collection_group_id), opts.hideInactive, opts.showParent);
								}
							} else {
								// renders full collection group/collection menu
								menu = si.collections.build_menu(opts.hideInactive);
							}
						} else {
							// renders the menu from the specified collection group
							menu = si.collections.build_menu_item(si.collections.find_collection_group_by_key(opts.from), opts.hideInactive, opts.showParent);
						}
						break;
				}
				
				return $(this).append(menu);
			});
		},
		
		//create breadcrumbs, takes a type (current template type) and a divider
		//TODO: get rid of need to pass in a type
		siLoadBreadcrumb: function(options){
			// set defaults
			var defaults = {
				divider: '<span class="crumbDivider">&raquo;</span>'
			}
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				
				var str = si.store.build_breadcrumb(opts.divider);
				
				return $(this).append(str);
			});
		},
		
		// load filters in list views, TODO: will be expanded to allow for ULs and links as opposed to DIVS/select menus
		siLoadFilters: function(options){
			// set defaults
			var defaults = {
				currentFilterWrapper: "#appliedFilters",
				titles: true
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			si.search.filter_titles_enabled = opts.titles;
			
			//set applied filters target and build necessary HTML
			si.search.current_filters_target = $(opts.currentFilterWrapper);
			si.search.build_current_filters();
			
			if(si.search.filter_markup != undefined) {
				//build HTML structure for filters
				this.append(si.search.build_filters());
				//load filters
				si.search.load_filters();
			}
			
			// clear filter click
			$(opts.currentFilterWrapper).find('a.clearFilters').click (function() {
				si.search.clear_filters();
				return false;
			});
			
			return this;
		},
		
		// load featured products
		siLoadFeaturedProducts: function(options){
			
			// set default id
			var id = 0;
			
			//get current object to use for default from 
			var obj = si.store.get_obj(si.view.type);
			if (obj != undefined && obj.obj != undefined) {
				id = obj.obj.id;
			}
			
			// set defaults
			var defaults = {
				from : id,
				type : si.view.type,
				slider : true
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			// make sure the from id is an integer
			opts.from = parseInt(opts.from);
			
			return this.each(function(){
				var str = '';
				
				if(opts.slider) {
                    $(this).css('zoom',1);
					str = '<div class="calloutNav"><span class="prev">previous</span><span class="next">next</span></div>' +
					'<div class="calloutWindow" style="overflow:hidden;position:relative;">' +
						'<div class="calloutStrip" style="position:absolute;top:0;left:0;width:9000px;">' + si.products.load_featured_list(opts.from, opts.type); + '</div>' +
					'</div>';
					
					$(this).append(str).siSlider();
				} else {
					str = si.products.load_featured_list(opts.from, si.singularize(opts.type));
					$(this).append(str);
				}
				
				return $(this);
				
			});
		},
		
		// load sale products
		siLoadSaleProducts: function(options){
			
			// set default id
			var id = 0;
			
			//get current object to use for default from 
			var obj = si.store.get_obj(si.view.type);
			if (obj != undefined && obj.obj != undefined) {
				id = obj.obj.id;
			}
			
			// set defaults
			var defaults = {
				from : id,
				type : si.view.type,
				slider : true
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			// make sure the from id is an integer
			opts.from = parseInt(opts.from);
			
			return this.each(function(){
				var str = '';
				
				if(opts.slider) {
					str = '<div class="calloutNav"><span class="prev">previous</span><span class="next">next</span></div>' +
					'<div class="calloutWindow" style="overflow:hidden;position:relative;">' +
						'<div class="calloutStrip" style="position:absolute;top:0;left:0;width:9000px;">' + si.products.load_sale_list(opts.from, opts.type); + '</div>' +
					'</div>';
					
					$(this).html(str).siSlider();
				} else {
					str = si.products.load_sale_list(opts.from, si.singularize(opts.type));
					$(this).append(str);
				}
				
				return $(this);
			});
		},
		
		// load related products
		siLoadRelatedProducts: function(options){
			
			// set defaults
			var defaults = {
				slider : true
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				var str = '';
				
				if(opts.slider) {
					str = '<div class="calloutNav"><span class="prev">previous</span><span class="next">next</span></div>' +
					'<div class="calloutWindow" style="overflow:hidden;position:relative;">' +
						'<div class="calloutStrip" style="position:absolute;top:0;left:0;width:9000px;">' + si.products.load_related_list(); + '</div>' +
					'</div>';
					
					$(this).html(str).siSlider();
				} else {
					str = si.products.load_related_list();
					$(this).append(str);
				}
				
				return $(this);
			});
		},
		
		//load subitems, could be categories, brands, or collections depending on the template
		siLoadSubitems: function(options) {
			//get current object to use for default from
			var defaultObj = si.store.get_cur_obj(si.view.type);
			var defaultFrom = {};
			
			// brand list do not have an id, since they are specific to a brand
			if (si.view.type == 'brand_list') {
				defaultFrom = defaultObj;
			} else {
				defaultFrom = defaultObj.id;
			}
			
			// set defaults
			var defaults = {
				type: si.view.type,
				from: defaultFrom
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			//new obj based on opts
			var obj = si.store.get_obj(opts.type);
			var str = obj.build_subitem_list(opts.from);
			
			return this.append(str);
		},
		
		siLoadAreaAsset: function(options) {
			//get current object to use for default from
			var obj = si.store.get_cur_obj(si.view.type);
			
			// set defaults
			var defaults = {
				from: obj,
				type: si.view.type
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			
			var str = si.store.load_area_asset(opts.from, opts.type);
			
			return this.append(str);
		},
		
		siLoadGallery: function(options) {
			// set defaults
			var defaults = {
				mainImage : "#mainImagePlaceholder",
				galleryImages : "#galleryPlaceholder",
				zoomWidth : $("#productDetail").width(),
				zoomHidden : "#productDetail div.prodInfo",
                zoomEnabled : true,
                from : si.products.obj
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
            
            //set the gallery object based on the plug-in settings
            si.gallery.obj = opts.from;
            si.gallery.zoom_enabled = opts.zoomEnabled;
			
			//replaces placeholders for main image and image gallery
			$(opts.mainImage).append(si.gallery.build_main_image);
			$(opts.galleryImages).append(si.gallery.build_images);

			this.addClass("SIgallery");
			
			//feed gallery js its parameters
			si.gallery.params = {
				"galleryWrapper" : this,
				"mainImage" : this.find("#mainImageWrapper img"),
				"mainImageWrapper" : this.find("#mainImageWrapper"),
				"nonGalleryContent" : $(opts.zoomHidden), //area to fade out
				"zoomGalleryWidth" : opts.zoomWidth //width gallery will expand to
			};
			
            if(opts.zoomEnabled) {
                //apply cick to main image to activate zooming
                si.gallery.params.mainImage.live('click', function(){
                    if(si.gallery.zoom_on == false) {
                        si.gallery.init_zoom('#SIzoomLink');
                    }
                });
            }
            
			//apply click image swapping for product gallery
			this.find("div.gallery img").click(function(){
				var asset_id = $(this).attr("id").replace("asset","");
				if (asset_id > 0) {
					var asset = si.assets.get_asset_by_id(si.gallery.obj, asset_id);
					
					//remove current active class and set new active class
					$(opts.galleryImages).find(".active").removeClass("active");
					$(this).addClass("active");
					
					// click function for regular view
					if (asset_id != undefined && !si.gallery.zoom_on) {si.gallery.swap_main_image(asset_id, asset);} 
					
					//click function for zoom mode
					else if (asset_id != undefined && si.gallery.zoom_on) {si.gallery.swap_zoom_image(asset_id, asset);}
				}
			});
			
			return this; 
		},
		
		siLoadDescriptions: function(options) {
			// set defaults
			var defaults = {
				display: 'accordion',
				products: undefined,
				attributes: true,
				brands: undefined,
				collections: undefined,
				collectionGroups: false,
				exclude: ['short-description']
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				var descriptions = [];
				
				// find descriptions
				if (opts.products == undefined || opts.products) {
					for (i in si.products.obj.descriptions) {
						var description = si.products.obj.descriptions[i];
						if ($.inArray(description.key, opts.exclude) == -1) {
							descriptions.push(description);
						}
					}
				}
				
				// add brand descriptions
				if (opts.brands == undefined || opts.brands) {
					for (i in si.products.obj.brand_ids) {
						var brand = si.brands.get(si.products.obj.brand_ids[i]);
						if (brand.description && (opts.brands != undefined || (!brand.settings.override && si.settings.brands.descriptions || brand.settings.override && brand.settings.descriptions))) {
							descriptions.push({ name: brand.name, description: brand.description });
						}
					}
				}
				
				// add collection descriptions
				if (opts.collections == undefined || opts.collections) {
					var collections = [];
					for (i in si.products.obj.collection_ids) {
						collections.push(si.collections.get(si.products.obj.collection_ids[i]));
					}
					
					// check if collections should be nested in their groups, or displayed on their own
					if (opts.collectionGroups) {
						for (i in si.products.obj.collection_group_ids) {
							var collection_group = si.collections.get_group(si.products.obj.collection_group_ids[i]);
							var children = [];
							
							// find the collections of the group
							for (j in collections) {
								if (collections[j].collection_group_id == collection_group.id) {
									if (collections[j].description && (opts.collections != undefined || (!collections[j].settings.override && collection_group.settings.descriptions || collections[j].settings.override && collections[j].settings.descriptions))) {
										children.push({ name: collections[j].name, description: collections[j].description });
									}
								}
							}
							
							// display settings might have prevented the descriptions from being add, so check if there are any first
							if (children.length > 0) {
								descriptions.push({ name: collection_group.name, description: collection_group.description, 'children': children });
							}
						}
						
					} else {
						for (i in collections) {
							var collection_group = si.collections.get_group(collections[i].collection_group_id);
							if (collections[i].description && (opts.collections != undefined || (!collections[i].settings.override && collection_group.settings.descriptions || collections[i].settings.override && collections[i].settings.descriptions))) {
								descriptions.push({ name: collections[i].name, description: collections[i].description });
							}
						}
					}
				}
				
				// build the markup for the descriptions
				$(this).append(si.store.build_descriptions(descriptions, opts.display));
				
				//activate appropriate UI and add additional attributes, brand desc, etc. 
				switch(opts.display) {
					case("accordion"): 
						//add attributes
						if(opts.attributes) {
							$(this).append(si.products.build_prodAttributes(si.products.obj, "desc_accordion"));
						}
						
						//initialize jquery UI accordian for product descriptions if there is more than one
						if ($(this).find(".prodDescWrapper").length > 1) {
							$(this).accordion({
								header: "h3",
                                autoHeight: false,
								icons: {
						    		header: "toggleOpen",
						   			headerSelected: "toggleClose"
								}
							});
						}
					break;
					case("tabs"):
						//add attributes
						if(opts.atributes) {
							$(this).append(si.products.build_prodAttributes(si.products.obj, "desc_tabs"));
						}
                        
                        if ($(this).find(".prodDescWrapper").length > 1) {
                            $(this).tabs();
                        }
					break;
				}
				
				return $(this);
			});
		},
        
        siLoadDescription: function(options) {
			// set defaults
			var defaults = {
				type: 'description',
                from: ''
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				//build descriptions
				return $(this).append(si.products.get_description(opts.type));
			});
		},
		
		// load brand links from a specific product ID
		siLoadBrandLinks: function(options){
			
			// set defaults
			defaults = {
				from: si.products.obj,
                wrapper: si.products.brand_link_defaults.wrapper,
				separator: si.products.brand_link_defaults.separator
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				var str = si.products.build_brand_links(opts.from, {wrapper:opts.wrapper,separator:opts.separator});
				
				return $(this).append(str);
			});
		},
		
		// load tag links from a specific product ID
		siLoadTagLinks: function(options){
			
			// set defaults
			defaults = {
				from: si.products.obj,
				wrapper: si.products.tag_link_defaults.wrapper,
				separator: si.products.tag_link_defaults.separator
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				var str = si.products.build_tag_links(opts.from, {wrapper:opts.wrapper,separator:opts.separator});
				
				return $(this).append(str);
			});
		},
		
		//load the product purchase form on the product detail page
		siLoadPurchaseForm: function(options){
			// set defaults
			defaults = {
				obj: si.products.obj
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			str = si.products.build_purchase_form(opts.obj);
			
			return this.append(str);
		},
		
		//load the product price on the product detail page
		siLoadPrice: function(options){
			// set defaults
			defaults = {
				obj: si.products.obj
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			str = si.products.build_price(opts.obj);
			
			return this.append(str);
		},
		
		//load the product price on the product detail page
		siLoadStock: function(options){
			// set defaults
			defaults = {
				obj: si.products.obj
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			str = si.products.build_stock(opts.obj);
			
			return this.append(str);
		},
		
		// load cart totals and assign class for dynamic updating
		siLoadCartCount: function(){
			return this.each(function(){
				var str = si.cart.get_cart_count('product');
				$(this).addClass('siCartCount').html(str);
				return $(this);
			});
		},
		
		// load user links
		siLoadUserLinks: function(options) {
			// set defaults
			var defaults = {
				fbConnect : true,
                fbConnectText : 'connect',
                showUserName : true,
                loginText : 'login',
                registerText : 'register',
                accountText : 'your account',
                signOutText : 'sign out', 
                cartLink : true,
                cartLinkText : 'your cart'
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
            //set si vars based on plugin settings
            si.users.fb_connect = opts.fbConnect; //determines whether to show fbConnect
            si.users.fb_connect_text = opts.fbConnectText; //text on fb connect
            si.users.show_user_name = opts.showUserName; //determines whether to show user name
            si.users.login_text = opts.loginText; //text on login link
            si.users.register_text = opts.registerText; //text on register link
            si.users.account_text = opts.accountText; //text on account link
            si.users.sign_out_text = opts.signOutText; //text on signout link
            si.users.cart_link = opts.cartLink;
            si.users.cart_link_text = opts.cartLinkText;
            
			return this.each(function(){
				var str = si.users.build_links();
				return $(this).append(str);
			});
		},
		
		// load microcart
		siLoadMicroCart: function(options){
			//TODO: create options for various types of microcarts, including a table version
			// set defaults
			var defaults = {
				type: "list",
				cartMessages: true,
				cartMessageTarget: "#microCartTool",
				emptyMessage : "your cart is empty"
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			if (opts.cartMessages && ! si.settings.facebook.in_iframe) {
				//set micro cart messages to active and not inside FB
				si.cart.microcart_messages_enabled = true;
			}
			
			//set message area as global var
			si.cart.message_target = opts.cartMessageTarget;
			
			//set empty message
			si.cart.microcart_empty_message = opts.emptyMessage;
			
			//set cart type
			si.cart.microcart_type = opts.type;
			
			//build cart based on type
			switch(opts.type) {
				case("list"):
					var str = '<form id="microCartContentsForm">' +
					'<ul class="zebra scrollWrapper cartContentWrapper">' + si.cart.get_microCart() + '</ul>' +
					'</form>';
					this.append(str).find("ul.zebra li:even").addClass("stripe");
				break;
				case("table"):
					var str = '<form id="microCartContentsForm">' +
					'<table width="100%" class="zebra"><tbody class="cartContentWrapper">' + si.cart.get_microCart() + '</tbody></table>' +
					'</form>';
					this.append(str).find("table.zebra tr:even").addClass("stripe");
				break;
			}
			
			
			return this;
		},
        
        //load checkout steps
		siLoadCheckoutSteps: function(options) {
			
            var defaults = {
				
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
            return this.append(si.checkout.build_steps());
			
		},
        
        //load cart total
		siLoadCartTotal: function(options) {
			
            var defaults = {
				
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
            return this.append(si.cart.build_total());
			
		},
		
		//load store search with or without select
		siLoadStoreSearch: function(options) {
			var defaults = {
				buttonText: "go",
				select: true
			}
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			return this.each(function(){
				
				return $(this).append(si.search.build_query_search_form(opts.buttonText, opts.select));
			});
		},
		
		//Category select powered nav
		siLoadCategorySelect: function(options) {
			var category = si.store.get_cur_obj('category');
			var defaults = {
				id: category != undefined ? category.id : 0,
				instruction: "shop by category...",
				type: "link",
				name: "shop_category_menu",
				selectId: "shop_category_menu"
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			this.append(si.categories.build_list_select(opts.id, opts.instruction, opts.type, opts.name, opts.selectId))
			
			$('#' + opts.selectId).change(function () {
				$('#' + opts.selectId + ' option:selected').each(function() {
					var url = $(this).val();
					if (url.length > 0 && url != 0) {
						document.location=$(this).val();
					}
				});
			});
			
			return this;
		},
		
		//Brand select powered nav
		siLoadBrandSelect: function(options) {
			var defaults = {
				id: 0,
				instruction: "shop by brand...",
				type: "link",
				name: "shop_brand_menu",
				selectId: "shop_brand_menu"
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			this.append(si.brands.load_list_select(opts.id, opts.instruction, opts.type, opts.name, opts.selectId))
			
			$('#' + opts.selectId).change(function () {
				$('#' + opts.selectId + ' option:selected').each(function() {
					document.location=$(this).val();
				});
			});
			
			return this;
		},
        
        //Brand select powered nav
		siLoadCollectionSelect: function(options) {
			var defaults = {
				id: 0,
				instruction: "shop by collection...",
				type: "link",
				name: "shop_collection_menu",
				selectId: "shop_collection_menu"
			};
			
			//extend defaults with provided options
			var opts = $.extend(defaults, options);
			
			this.append(si.collections.load_list_select(opts.id, opts.instruction, opts.type, opts.name, opts.selectId))
			
			$('#' + opts.selectId).change(function () {
				$('#' + opts.selectId + ' option:selected').each(function() {
					document.location=$(this).val();
				});
			});
			
			return this;
		}
		
	});
	$.si = {
		defaults: {
			gallery: {},
			overFlow: {
				target: '<li>'
			}
		},
        
        fn: {
            delayHideDropdown: function(menu, delay) {
                si.menuDelayHide = setTimeout(function(){
                   menu.find(".SIhover").removeClass("SIhover").find("ul").fadeOut("fast");
                }, delay);
            }
        }
	};
})(jQuery);