//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;

        var objLiMarginLeftSelected = $j(this.objDivContainer).find(".intLiMarginLeftSelected").get(0);
        var intLiMarginLeftSelected = (objLiMarginLeftSelected) ? parseInt(objLiMarginLeftSelected.value) : -1;
        this.intLiMarginLeftSelected = (isNaN(intLiMarginLeftSelected) || intLiMarginLeftSelected < 1) ? this.intLiMarginLeftSelected : intLiMarginLeftSelected;

        var objLiMarginLeftDefault = $j(this.objDivContainer).find(".intLiMarginLeftDefault").get(0);
        var intLiMarginLeftDefault = (objLiMarginLeftDefault) ? parseInt(objLiMarginLeftDefault.value) : -1;
        this.intLiMarginLeftDefault = (isNaN(intLiMarginLeftDefault) || intLiMarginLeftDefault < 1) ? this.intLiMarginLeftDefault : intLiMarginLeftDefault;

        this.AttachEvents();
    }
    this.AttachEvents = function() {
        $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(objLi).addClass("SelectedImage");

                //remargin li
                $j(this.objDivContainer).find(".CarouselImageList li").css("margin-left", this.intLiMarginLeftSelected + "px");

                //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(objLi.style.marginLeft);
                    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").css("margin-left", this.intLiMarginLeftDefault + "px");
        if (objSelectedLi) {
            objSelectedLi.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 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 intMargin = (this.objOverlay) ? this.intLiMarginLeftDefault : this.intLiMarginLeftSelected;
        if (isPrev) {
            intMargin = this.intLiMarginLeftDefault;
        }
        //get li widths to establish scroll amount
        var objLi = $j(this.objDivContainer).find(".CarouselImageList li:not(.SelectedImage)")[0];
        var intLiWidth = parseInt($j(objLi).width()) + intMargin;
        var intScroll = (intLiWidth * this.intThumbVisible);


        //alert("intLi count = " + intScroll);
        //isNext = intScroll = 420
        //isPrev = intScroll = 468
        //

        //hide previous
        var objSupDesc = $j(this.objDivContainer).find(".SupImgDesc");
        var objSelectedLi = $j(this.objDivContainer).find(".SelectedImage");
        this.Hide(objSelectedLi, objSupDesc);

        // get new html from AJAX		
        var strHTML = "" + this.objXml;

        //remove SelectedImage
        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());
        }

        //update css and events for new html
        //add margin left												
        $j(this.objDivContainer).find(".CarouselImageList li").css("margin-left", intMargin + "px");

        //add onmouse out				
        $j(this.objDivContainer).find(".CarouselImageList li").unbind("mouseout");
        var strMouseOut = this.strInstName + '.TimerHide(event)';
        $j(this.objDivContainer).find(".CarouselImageList li").attr("onmouseout", strMouseOut);

        //$j(this.objDivContainer).find(".CarouselImageList li").bind("mouseout",{objInst:this},function(e){
        //e.data.objInst.TimerHide(e);																
        //});

        //add onmouseover
        $j(this.objDivContainer).find(".CarouselImageLink").unbind("mouseover");
        var strMousOver = this.strInstName + '.Show(event,this)';
        $j(this.objDivContainer).find(".CarouselImageLink").attr("onmouseover", strMousOver);


        //$j(this.objDivContainer).find(".CarouselImageList a").bind("mouseover",{objInst:this},function(e){
        //alert("link mouse over");
        //e.data.objInst.Show(e,this);																
        //});	

        //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);

        //$j(this.objDivContainer).find(".WrapForIE").append(objScrollClone);

        //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";
        //alert("intScroll = " + $j(this.objDivContainer).find(".Scroll").css("width"));

        //begin scroll transaction
        //prevent overlay from hover during scrolling because it messes up position
        $j(this.objDivContainer).find(".Scroll")[0].isScrolling = true;

        //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);
            $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 = 500;
            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);
            }
        }
    }

}