//IMAGE CAROUSEL
//Author: Steve Tomlin
//Date: 2008 11 18
//Requires:
//Javascript files:
// js/jquery.js
// js/is_mouse_out.js

//Works with:
//ImageCarousel.htm		

function GetJqueryElementFromString(strAll, strSelector) {
    //strAll = "<div> <span class="test"></span></div>"
    //strSelector = ".test"	
    
    var objClone = null;
    if (strAll) {
        var obj = document.createElement("div");
        obj.id = "regex1";
        obj.style.display = "none";
        $j(document.body).append(obj);
        $j("#" + obj.id).html(strAll);
        var objClone = $j("#" + obj.id).find(strSelector).clone();


        $j("#" + obj.id).remove();


    } else {
        alert("strAll = " + strAll);
    }        
    return objClone;
}


//instantiating: 
//var objCarousel1 = new ClassImageGallery("objCarousel1");	
//$(document).ready(function(){objCarousel1.Init();});	

function ClassImageCarousel(strInstName) {
    this.strInstName = strInstName;
    
    //client default parameters		
    this.intThumbVisible = 4;
    this.intLiMarginLeftSelected = 8;
    this.intLiMarginLeftDefault = 20;
    this.objDivContainer = $j(".ImageCarousel:eq(0)")[0];

    //null items
    this.objTimerHide = null;
    this.objXml = null;

    this.Init = function() {
        //overide client default parameters from form inputs
        var objDivContainer = $j(this.objDivContainer).find(".intDivContainer").get(0);
        var intDivContainer = (objDivContainer) ? parseInt(objDivContainer.value) : -1;
        this.objDivContainer = (isNaN(intDivContainer) || intDivContainer < 1) ? this.objDivContainer : $j(".ImageCarousel:eq(" + (intDivContainer - 1) + ")")[0];

        var objOverlay = $j(this.objDivContainer).filter(".ImageCarousel-Overlay").get(0);
        this.objOverlay = (objOverlay) ? objOverlay : $j(this.objDivContainer).find(".ImageCarousel-Overlay").get(0);

        var objThumbVisible = $j(this.objDivContainer).find(".intThumbVisible").get(0);
        var intThumbVisible = (objThumbVisible) ? parseInt(objThumbVisible.value) : -1;
        this.intThumbVisible = (isNaN(intThumbVisible) || intThumbVisible < 1) ? this.intThumbVisible : intThumbVisible;

        //set thumb visible to current visible. If user specifies greater number than images that actually exist
        //then set to current visible
        var intCurrentVisible = $j(this.objDivContainer).find(".CarouselImageList li").length;
        this.intThumbVisible = (this.intThumbVisible > intCurrentVisible) ? intCurrentVisible : this.intThumbVisible;

        this.AttachEvents();
    }
    this.AttachEvents = function() {		
		//unbind
		$j(this.objDivContainer).find(".CarouselImageList li a").unbind("mouseover");
		$j(this.objDivContainer).find(".CarouselImageList li, .SupImgDesc").unbind("mouseout");
			
        //rebind
        $j(this.objDivContainer).find(".CarouselImageList li a").bind("mouseover", { objInst: this }, function(e) {
            e.data.objInst.Show(e, this);
        });
        $j(this.objDivContainer).find(".CarouselImageList li, .SupImgDesc").bind("mouseout", { objInst: this }, function(e) {
            e.data.objInst.TimerHide(e);
        });
    }
    this.Show = function(e, objA) {//,isOveridePrevious

        var objScroll = $j(this.objDivContainer).find(".Scroll")[0];
        if (!this.objOverlay || objScroll.isScrolling != true) {
            //clear all previous hide timers
            if (this.objTimerHide) {
                clearTimeout(this.objTimerHide);
            }
            //init variables
            var isOveridePrevious = (arguments.length > 2) ? arguments[2] : null;
            var objLi = objA.parentNode;
            var objPreviousLi = $j(this.objDivContainer).find(".SelectedImage")[0];
            objPreviousLi = (objPreviousLi) ? objPreviousLi : null;

            //dont repeat on current selected li
            if (objLi != objPreviousLi || isOveridePrevious) {

                //hide previous
                var objSupDesc = $j(this.objDivContainer).find(".SupImgDesc");
                var objSelectedLi = $j(this.objDivContainer).find(".SelectedImage");
                this.Hide(objSelectedLi, objSupDesc);
                var intMarginCenter = null;

                //select li

                $j(this.objDivContainer).find(".CarouselImageList li:not(.SelectedImage)").addClass("UnSelectedImage");
                $j(objLi).removeClass("UnSelectedImage");
                $j(objLi).addClass("SelectedImage");

                //write html into supDesc from li
                $j(objSupDesc[0]).find(".SupImgDescBox")[0].innerHTML = $j(objLi).find(".SupImgDescBox")[0].innerHTML;


                //overlay - centering SupDesc
                var objOverlay = this.objOverlay;
                if (objOverlay) {
                    //get margin center
                    var intSupDescMarginLeftCenter = 0;
                    var intSupBoxWidth = $j(this.objDivContainer).find(".SupImgDescBox").width(); //parseInt(objSupDesc[0].style.width);

                    var intLiWidth = $j(objLi).width();
                    intLiWidth = (isNaN(intLiWidth)) ? 139 : intLiWidth;
                    var intLiOffsetLeft = parseInt(objLi.offsetLeft);

                    var intLiMarginLeft = parseInt($j(objLi).css("margin-left"));
                    intSupDescMarginLeftCenter = ((intLiOffsetLeft + (intLiMarginLeft / 2) + (intLiWidth / 2)) - (intSupBoxWidth / 2));

                    //set margin center 									
                    objSupDesc.css("margin-left", intSupDescMarginLeftCenter + "px");
                }

                //show supDesc
                $j(objSupDesc[0]).css("opacity", "1");
                //$(objSupDesc[0]).fadeIn("slow");

            }
        }
    }
    this.TimerHide = function(e) {
        //only mouse out if overlay object.				
        var objOverlay = this.objOverlay;
        if (objOverlay) {
            var objSupDesc = $j(this.objDivContainer).find(".SupImgDesc");
            var objSelectedLi = $j(this.objDivContainer).find(".SelectedImage");
            var arrAllowedMouseOut = new Array(objSelectedLi[0], objSupDesc[0]);
            var objIsMouseOut = new ClassIsMouseOut();
            var isMouseOut = objIsMouseOut.isMouseOutObjectArea(e, arrAllowedMouseOut);
            if (isMouseOut) {
                clearTimeout(this.objTimerHide);
                var objInst = this;
                this.objTimerHide = setTimeout(function() { objInst.Hide(objSelectedLi, objSupDesc, true) }, 200, objInst, objSelectedLi, objSupDesc);
            }
        }
    }
    this.Hide = function(objSelectedLi, objSupDesc) {
        $j(this.objDivContainer).find(".CarouselImageList li").removeClass("UnSelectedImage");
        $j(this.objDivContainer).find(".CarouselImageList li").removeClass("SelectedImage");

        if (this.objOverlay) {
            objSupDesc.css("opacity", "0");
        }
    }
    this.PrevNextReload = function(e, intPrevNext, strXmlPath, intIndex) {
        var objScroll = $j(this.objDivContainer).find(".Scroll").get(0);
        if (objScroll.isScrolling != true) {
            //init variables
            var objInst = this;

            //Get live xml feed	
            try {
                $j.get(strXmlPath, { intIndex: intIndex }, function(xml, isSuccess) { if (isSuccess) { objInst.objXml = xml; objInst.PrepareLisAndScroll(e, intPrevNext); } else { alert("IMAGE CAROUSEL CLASS\nThere is a problem with AJAX and this xml path:" + objInst.strXmlPath) } });
            } catch (e) {
                alert("IMAGE CAROUSEL CLASS\nSome problem with Jquery Get");
            }
        }
    }

    this.PrepareLisAndScroll = function(e, intPrevNext) {

        //previous or next clicked
        var isPrev = (intPrevNext == -1)
        var isNext = (intPrevNext == 1)

        //get intMarginSelected				
        //if next and not overlay
        //get margin selected
        var intMarginSelected = null;
        if (!this.objOverlay) {
            intMarginSelected = $j(this.objDivContainer).find(".CarouselImageList li.SelectedImage").css("margin-left");
        }

        //1) hide previous
        var objSupDesc = $j(this.objDivContainer).find(".SupImgDesc");
        var objSelectedLi = $j(this.objDivContainer).find(".SelectedImage");
        this.Hide(objSelectedLi, objSupDesc);

        //get scroll width 
        // get default margin
        //if previous
        //margin left needs to be the larger default value
        //because the selected item will unselect before scrolling back
        //when the current thumb unselects, the margins will spread out to the default margin
        //if we dont set this margin to the default margin
        //then initial intResetScroll position will not be large enough			

        var objLi = $j(".CarouselImageList li:eq(1)");
        //if next and not overlay
        if (isNext && !this.objOverlay) {
            intMargin = (intMarginSelected) ? parseInt(intMarginSelected) : this.intLiMarginLeftSelected;
        } else {
            var intMargin = objLi.css("margin-left");
            intMargin = (intMargin) ? parseInt(intMargin) : this.intLiMarginLeftDefault;
        }
        var intLiWidth = parseInt($j(objLi).width()) + intMargin;
        var intScroll = (intLiWidth * this.intThumbVisible);

        // get new html from AJAX		
        var strHTML = "" + this.objXml;

        //remove SelectedImage and UnSelectedImage
        strHTML = strHTML.replace(/UnSelectedImage/g, "");
        strHTML = strHTML.replace(/SelectedImage/g, "");

        //Extract list items from new html
        //update styles and events according to current view
        var objCarouselImageList = GetJqueryElementFromString(strHTML, ".CarouselImageList");

        //replace current view lis with new html
        if (isNext) {//note: must append elements, not element.html otherwise ie doesnt pick up the length property of carouselImageList
            $j(this.objDivContainer).find(".CarouselImageList").append(objCarouselImageList.children());
        } else if (isPrev) {
            $j(this.objDivContainer).find(".CarouselImageList").prepend(objCarouselImageList.children());
        }

        //fix scroll bug 
        //note, the reason Scroll is completely  replaced here, 
        //is because scrollLeft doesn't seem to animate again after being animated once before.					
        var objScroll = $j(this.objDivContainer).find(".Scroll");
        //get sibling
        var objSibling = objScroll.siblings().filter(":last");
        var objScrollClone = objScroll.clone();
        objScroll.remove();
        //inserts scroll after its sibling
        objSibling.after(objScrollClone);

        //rebind events after scroll replace
        this.AttachEvents();

        //scroll to initial position before html was changed to prepare the scroll
        //updating the html above will shift the current visible 4
        //so we need an instant scroll to original position to make it look 
        //to the user like nothing happened.
        if (isPrev) {
            $j(this.objDivContainer).find(".Scroll").scrollLeft(intScroll);
            intScroll = 0;
        }
        var strScroll = intScroll + "px";

        //begin scroll transaction
        //prevent overlay from hover during scrolling because it messes up position
        $j(this.objDivContainer).find(".Scroll")[0].isScrolling = true;

        //add scrolling class 
        if (isNext) {
            $j(this.objDivContainer).find(".ForwardScrollControl .NextLink").addClass("IsScrolling");
        } else {
            $j(this.objDivContainer).find(".BackScrollControl .PreviousLink").addClass("IsScrolling");
        }

        //scroll ul
        $j(this.objDivContainer).find(".Scroll").animate({
            scrollLeft: strScroll
        }, 1400);

        //after scroll update page items  - Image Status and Links
        var objInst = this;
        $j(this.objDivContainer).find(".Scroll").queue(function(e) {
            //select item after scroll
            //this is in two places.
            if (!objInst.objOverlay) {

                //get isSelectedOutOfRange
                //if a user hovers an item during the scroll and its outside of the scroll range
                var objSelected = $j(objInst.objDivContainer).find(".SelectedImage");
                var objLi = $j(objInst.objDivContainer).find(".CarouselImageList li");
                var intIndex = parseInt(objLi.index(objSelected));

                isSelectedOutOfRange = ((isNext && intIndex < objInst.intThumbVisible) || (isPrev && intIndex > (objInst.intThumbVisible - 1))) ? true : false;
                if (isSelectedOutOfRange) {
                    //reselect the first item after the animated scroll.				
                    intLiSelected = (isPrev) ? 0 : objInst.intThumbVisible;
                    intTimer = 0;
                    objInst.SelectThumbAfterScroll(e, intPrevNext, intTimer, intLiSelected);
                }
            }

            //update html back to 4 
            //- this resets the lis when appending to them
            //- it fix overlay position when clicking next
            var objLis = (isNext) ? $j(".CarouselImageList li:gt(" + (objInst.intThumbVisible - 1) + ")") : $j(".CarouselImageList li:lt(" + objInst.intThumbVisible + ")");
            $j(".CarouselImageList").empty();
            $j(".CarouselImageList").append(objLis);

            //rebind events after scroll replace.
            objInst.AttachEvents();

            $j(this.objDivContainer).find(".Scroll").scrollLeft(0);

            //update image status
            //<h3 class="ImageNumberStatus">
            var objNewImageStatus = GetJqueryElementFromString("" + objInst.objXml, ".ImageNumberStatus");
            $j(this.objDivContainer).find(".ImageNumberStatus").html(objNewImageStatus.html());

            //update previous and next links
            //class="BackScrollControl"
            //class="ForwardScrollControl"
            var objBackScrollControl = GetJqueryElementFromString("" + objInst.objXml, ".BackScrollControl");
            $j(this.objDivContainer).find(".BackScrollControl").html(objBackScrollControl.html());




            var objForwardScrollControl = GetJqueryElementFromString("" + objInst.objXml, ".ForwardScrollControl");
            $j(this.objDivContainer).find(".ForwardScrollControl").html(objForwardScrollControl.html());

            //enable hovers again by turning off scrolling
            $j(this)[0].isScrolling = false;
        });
        //end scroll transaction 

        //select item after scroll
        //this is in two places.
        //1 here, half way through scroll for visual effect.
        //and one right after the scroll, in case a user hovers an item just before its finished.
        if (!this.objOverlay) {
            intLiSelected = (isPrev) ? 0 : this.intThumbVisible;
            intTimer = 1000;
            this.SelectThumbAfterScroll(e, intPrevNext, intTimer, intLiSelected);
        }
    }

    this.SelectThumbAfterScroll = function(e, intPrevNext, intTimer, intLiSelected) {
        var isPrev = (intPrevNext == -1);
        var isNext = (intPrevNext == 1);
        //only select new item if not overlay
        objOverlay = this.objOverlay;
        if (!objOverlay) {
            //var objA = $j(objUL).find("li:eq(0) .CarouselImageLink")[0];					

            var objA = $j(this.objDivContainer).find(".CarouselImageList li:eq(" + intLiSelected + ") .CarouselImageLink")[0];
            var objInst = this;
            var isOveridePrevious = true;
            if (intTimer > 0) {
                var objTimerSelectNewThumb = setTimeout(function() { objInst.Show(e, objA, isOveridePrevious) }, intTimer, objInst, isOveridePrevious);
            } else {
                objInst.Show(e, objA, isOveridePrevious);
            }
        }
    }

}		