/*  Condenet Slider Version 1.0:  */
function Slider(args){
    //read & apply arguments
    this.args = args;
    this.setArgs();
    //store dom elements
    this.container = document.getElementById(args.containerid);
    this.contentWrapper = getElements('content_wrapper','DIV',this.container)[0];
    this.contentLists = this.container.getElementsByTagName('UL');
    //set up the slider
	var slider = this;
    setTimeout(function(){slider.initialize()},750);
}
/*  NOTES:
        Fix saf 2 premature measurement (see init call)
        var isSafari = (navigator.userAgent. indexOf('WebKit')!=-1 ? true : false); //temp fix

*/
/*  Argument Setup
    -------------- */
    Slider.prototype.setArgs = function(){
        //required arguments
        this.groupSize = this.args.groupsize;
        this.direction = this.args.direction;
        this.effectType = this.args.effect || false;
        
        //optional arguments
        this.hasGroupNav = (this.args.hasgroupnav === null) ? true : this.args.hasgroupnav; 
        this.hasLoop = this.args.hasloop || false;
        this.hasAutoAdvance = this.args.hasautoadvance || false;
        this.advanceSeconds = this.args.advanceseconds || 5;
        this.hasTabs = this.args.hastabs || false;
        this.tabs = this.args.tabs; //required for tabbed modules
        this.speed = this.args.speed || 7;
	 /* to grayed out selected element and show it on current page */
        this.groupToStart = this.args.groupToStart;
    }

/*  Initialization
    -------------- */
    Slider.prototype.initialize = function(){
        this.setContext(0);     //set the context of the content initially displayed in the slider to the first list
        this.activeGroup = 1;   //set a flag used as a current group indicator
        this.assembleScrollControls();  //create a group of slider controls which applies to this content
        this.updateControlDisplay();     //update display of the controls to match behavior of this module;
        if(this.hasTabs) this.assembleTabs( );    //for sliders used to display more than one context of content, create the tab controls
        this.setupLayout();  //set up the layout properties constraining container and content list
        if(this.hasAutoAdvance) this.autoAdvance();     //if this slider autoadvances, begin the process
          /* to grayed out selected element and show it on current page */
	if(this.groupToStart) this.setToGroup(this.groupToStart);
    }

/*  Set the Context of Displayed Content
    ------------------------------------ */
    Slider.prototype.setContext = function(context_index){
        this.contentList = this.contentLists[context_index];    //set the active content list
        //capture useful properties of the content list
        this.contentItems = this.contentList.getElementsByTagName('li');
        this.numItems = this.contentItems.length;
        this.numGroups = Math.ceil(this.numItems/this.groupSize);
        this.itemWidth = this.getItemWidth();
        this.itemHeight = this.getItemHeight();
    }

/*  Scroll Control Creation & Event Handling
    ------------------------------------- */
    Slider.prototype.assembleScrollControls = function(){
        var moduleObject = this;
        if( this.numGroups > 1 ){   //only create controls if they are needed
            //create & register handlers for next/previous controls
            this.nextTrigger = this.createTrigger('slide_control_next');
            this.prevTrigger = this.createTrigger('slide_control_previous');
            if(window.addEventListener){
                this.nextTrigger.addEventListener("click", function(event){ moduleObject.advance(1); }, false);
                this.prevTrigger.addEventListener("click", function(event){ moduleObject.retract(1); }, false);
            }
            if(window.attachEvent){
                this.nextTrigger.attachEvent("onclick", function(event){ moduleObject.advance(1); }, false);
                this.prevTrigger.attachEvent("onclick", function(event){ moduleObject.retract(1); }, false);
            }
            //create & register handlers for group nav
            if( this.hasGroupNav ){
                this.groupNav = this.createGroupNav();
                this.groupTriggers = this.groupNav.getElementsByTagName('A');
                for(var i=0; i<this.groupTriggers.length; i++){
                    if(window.addEventListener)
                        this.groupTriggers[i].addEventListener("click", function(event){ moduleObject.switchGroup(event); }, false);
                    if(window.attachEvent)
                        this.groupTriggers[i].attachEvent("onclick", function(event){ moduleObject.switchGroup(event); },false);
                }
            }
        }
    }
    /*  Next/Prev Creation */
    Slider.prototype.createTrigger = function(){
        var triggerClass = arguments[0];
        var control = document.createElement('A');
        control.className = triggerClass;
        this.container.appendChild(control);
        return control;
    }
    /*  Group Nav Creation  */
    Slider.prototype.createGroupNav = function(){
        var groupNav = document.createElement('DIV');
        groupNav.className = 'group_nav';
        this.container.appendChild(groupNav);
        
        for(var i=0; i<this.numGroups; i++){
            var navButton = document.createElement('A');
            navButton.className = 'group_activator';
            navButton.id = this.container.id + '_group_' + (i+1);
            groupNav.appendChild(navButton);
        }
    
        if( this.direction == 'horizontal'){
            var buttonWidth = navButton.offsetWidth;
            var dynamicGroupNavWidth = this.numGroups * buttonWidth;
            groupNav.style.width = dynamicGroupNavWidth + 'px';
        }
        return groupNav;
    }
    /*  Refresh Display of all Slider Controls */
    Slider.prototype.updateControlDisplay = function(){
        if( this.numGroups <=1 ) return;
        if( this.hasGroupNav ) {
            for(var i=0; i<this.groupTriggers.length; i++)
                this.groupTriggers[i].className = '';
            this.groupTriggers[this.activeGroup - 1].className = 'active';
        }
        if( !this.hasLoop ){
        this.activeGroup == 1 ? this.prevTrigger.className += ' previous_disabled' : this.prevTrigger.className = 'slide_control_previous';
        this.activeGroup == this.numGroups ? this.nextTrigger.className += ' next_disabled' : this.nextTrigger.className = 'slide_control_next';
        }
    }

/*  Scroll Control Destructor
    ------------------------- */
    Slider.prototype.destroyScrollControls = function(){
        //remove dom elements
        this.groupNav ? this.groupNav.parentNode.removeChild(this.groupNav) : '';
        this.nextTrigger ? this.nextTrigger.parentNode.removeChild(this.nextTrigger) : '';
        this.prevTrigger ? this.prevTrigger.parentNode.removeChild(this.prevTrigger) : '';
        //remove references
        delete this.groupNav;
        delete this.nextTrigger;
        delete this.prevTrigger;
    }
    
/*  Tab Creation and Event Handling
    ------------------------------- */
    Slider.prototype.assembleTabs = function(){
        var moduleObject = this;
        for( var i = 0; i < this.tabs.length; i++ ){
			this.tabs[i].deactivate();
            this.tabs[i].tabElement.onclick = function(event){
				moduleObject.switchTab(event)
			}
		}
        this.tabs[0].activate();
    }
    Slider.prototype.switchTab = function(evt){
		var event = evt || window.event;
        this.effectReset();
        var focusElement = event.currentTarget || event.srcElement;
		if(focusElement.nodeName != 'A') focusElement = focusElement.parentNode;
        var activeTabIndex;
        for( var i=0; i < this.tabs.length; i++ ){      
            this.tabs[i].deactivate();  
            if( this.tabs[i].tabElement == focusElement)
                activeTabIndex = i;
        }
        this.destroyScrollControls();
        this.setContext(activeTabIndex);
        this.assembleScrollControls();
        this.setupLayout();
        this.tabs[activeTabIndex].activate();
        this.activeGroup = 1;
        this.setToGroup(1);
    }

/*  Layout Preparation
    ------------------ */
    /*sets the widths of the list & the wrapper*/
    Slider.prototype.setupLayout = function(){
        switch(this.direction){
            case 'horizontal':
                this.groupWidth = this.setContentWrapperWidth(); //set the content wrapper width to be the width of one group
                this.setScrollingListWidth(); //set the content list width to be large enough to hold all floated items within the active list side by side
                break;
            case 'vertical':
                this.groupHeight = this.setContentWrapperHeight(); break;
        }
    }
    /*returns the width of one list item*/
    Slider.prototype.getItemWidth = function(){
        return this.contentItems[0].offsetWidth;
    }
    /*returns the height of one list item*/
    Slider.prototype.getItemHeight = function(){
        return this.contentItems[0].offsetHeight;
    }
    /*returns the total width of n items in the content list*/
    Slider.prototype.calcuateScrollingListWidth = function(){
        return this.numItems * this.itemWidth;
    }
    /*sets the width of the list to a number large enough to contain all items side by side*/
    Slider.prototype.setScrollingListWidth = function(){
        var activeListWidth = this.calcuateScrollingListWidth();
        this.contentList.style.width = activeListWidth + 'px';
    }
    /*sets width of content_wrapper (dom element) to the width of one group & returns this width as an int*/
    Slider.prototype.setContentWrapperWidth = function(){
        this.contentWrapper.style.width = (this.itemWidth * this.groupSize) + 'px';
        return (this.itemWidth * this.groupSize)
    }
    /*sets height of content_wrapper (dom element) to the height of one group & returns this height as an int*/
    Slider.prototype.setContentWrapperHeight = function(){    
        this.contentWrapper.style.height = (this.itemHeight * this.groupSize) + 'px';
        return (this.itemHeight * this.groupSize)
    }
    /*returns the current value for the css 'left' of the content list*/
    Slider.prototype.getPositionLeft = function(){
        var leftValue = parseInt(this.contentList.style.left) || 0;
        return leftValue;
    }
    /*returns the current value for the css 'top' of the content list*/
    Slider.prototype.getPositionTop = function(){
        var topValue = parseInt(this.contentList.style.top) || 0;
        return topValue;
    }

/*  Event Handlers:  Advance, Retract, SwitchGroup, SetToGroup
    ---------------------------------------------------------- */
    /*advances the list by 'freq' groups*/
    Slider.prototype.advance = function(freq){    
        if( this.activeGroup == this.numGroups && !this.hasLoop ) return;   //if this is the last group in a module that doesn't loop, exit
        
        var currentPosition = (this.direction == 'horizontal' ? this.getPositionLeft() : this.getPositionTop());
        var groupDimension = (this.direction == 'horizontal' ? this.groupWidth : this.groupHeight);
        
        if( currentPosition != 0 && Math.abs(currentPosition) % groupDimension != 0 ) return;   //if we are already moving, exit
        
        var numScroll = freq || 1;
        var destinationPosition = currentPosition - (groupDimension * numScroll);
        var cssDirection = (this.direction == 'horizontal' ? 'left' : 'top');
        var contentList = this.contentList; //active content list
        var speed = this.speed;
        var moduleObject = this;
        
        if( this.activeGroup == this.numGroups ){this.retract(this.numGroups - 1); return;}  //if this is the last group, slide back to the first group
        
        this.activeGroup = this.activeGroup + numScroll;    //update active group status
        
        if( this.effectType) this.effectStart();    //start the effect before movement begins
        
        var clearer = setInterval(function(){   //begin the movement
                if(currentPosition - speed >= destinationPosition){
                    contentList.style[cssDirection] = (currentPosition-speed) + 'px';
                    currentPosition -= speed;
                }else{
                    contentList.style[cssDirection] = destinationPosition + 'px';
                    clearInterval(clearer); //clear the interval
                    if( moduleObject.effectType ) moduleObject.effectEnd(); //& end the effect
                }
        },10);
        
        this.updateControlDisplay();    //update the control display to match that of the new group
    }
    /*retracts the list by 'freq' groups*/
    Slider.prototype.retract = function(freq){
        if( this.activeGroup == 1 && !this.hasLoop ) return;    //if this is the first group in a module that doesn't loop, exit
    
        var currentPosition = (this.direction == 'horizontal' ? this.getPositionLeft() : this.getPositionTop());
        var groupDimension = (this.direction == 'horizontal' ? this.groupWidth : this.groupHeight);
    
        if( Math.abs(currentPosition) % groupDimension != 0 ) return;   //if we are already moving, exit
        
        if( this.activeGroup == 1){ this.advance(this.numGroups - 1); return;}  //if this is the last group, slide back to the first group
        
        var numScroll = freq || 1;
        var destinationPosition = currentPosition + (groupDimension * numScroll);
        var cssDirection = (this.direction == 'horizontal' ? 'left' : 'top');
        var contentList = this.contentList;
        var speed = this.speed;
        var moduleObject = this;
        
        this.activeGroup = this.activeGroup - numScroll;    //update active group status
        
        if( this.effectType) this.effectStart();    //call the effect start before movement begins
        
        var clearer = setInterval(function(){   //begin the movement
                if(currentPosition + speed <= destinationPosition){ //at the end of the movement
                    contentList.style[cssDirection] = (currentPosition + speed) + 'px';
                    currentPosition = currentPosition + speed;
                }else{
                    contentList.style[cssDirection] = destinationPosition + 'px';
                    clearInterval(clearer); //clear the interval
                    if( moduleObject.effectType ) moduleObject.effectEnd(); //& end the effect
                }
        },10);
        
        this.updateControlDisplay();    //update the control display to match that of the new group
    }
    /*  navigates from the current group to a destination group */
    Slider.prototype.switchGroup = function(event){
        var focusElement = event.currentTarget || event.srcElement;
        var startingGroup = this.activeGroup;
        var destinationGroup = focusElement.id.replace(/\D+/,'');
        var distance = Math.abs(startingGroup - destinationGroup);
        if( distance == 0 ) return;
        var direction = (startingGroup < destinationGroup ? 'advance' : 'retract');
        direction == 'advance' ? this.advance(distance) : this.retract(distance);
    }
    /*hard switch over to argument group without slideing transition*/
    Slider.prototype.setToGroup = function(index){
        var targetGroupIndex = index;
        var groupDimension = (this.direction == 'horizontal' ? this.groupWidth : this.groupHeight);
        var targetGroupPosition = (targetGroupIndex - 1) * groupDimension;
        var cssDirection = (this.direction == 'horizontal' ? 'left' : 'top');
        this.contentList.style[cssDirection] = '-' + targetGroupPosition + 'px';
        this.activeGroup = targetGroupIndex;
        this.updateControlDisplay();
    }


/*  Effect Application
    ------------------ */
    Slider.prototype.effectStart = function(){
        switch(this.effectType){
        case 1: this.startPlop(); break;
        case 2: this.startImageFade(); break;
        case 3: this.startTransSlide(); break;    
        }
    }
    Slider.prototype.effectEnd = function(){
        switch(this.effectType){
        case 1: this.endPlop(); break;
        case 2: this.endImageFade(); break;
        case 3: this.endTransSlide(); break;
        }
    }
    Slider.prototype.effectReset = function(){
        for(var i=0; i<this.contentItems.length; i++){
            var item = this.contentItems[i];
            var imageData = item.getElementsByTagName('IMG')[0];
            var textData = getElements('text_data','DIV',item)[0];
            var itemTitle = getElements('item_title','DIV',item)[0];
            if(imageData) imageData.style.visibility = ''
            if(textData) setCssOpacity(textData, 99);
            if(itemTitle) setCssOpacity(itemTitle,99);
        }
    }
    /* Effect 1: Plop */
    Slider.prototype.startPlop = function(){
        for(var i=0; i<this.contentItems.length; i++){
            var item = this.contentItems[i];
            var imageData = item.getElementsByTagName('IMG')[0];
            var textData = getElements('text_data','DIV',item)[0];
            var itemTitle = getElements('item_title','DIV',item)[0];
            if(imageData) imageData.style.visibility = 'hidden'
            if(textData) setCssOpacity(textData, 0);
            if(itemTitle) setCssOpacity(itemTitle,0);
        }
    }
    Slider.prototype.endPlop = function(){
        var firstItemIndex = (this.activeGroup-1) * this.groupSize;
        var lastItemIndex = (firstItemIndex + (this.groupSize - 1) < this.contentItems.length ? firstItemIndex + (this.groupSize-1) : this.contentItems.length - 1);
        var currentItemIndex = firstItemIndex;
        var moduleObject= this;
        var fade_clearer = setInterval(function(){
            var item = moduleObject.contentItems[currentItemIndex];
            var imageData = item.getElementsByTagName('IMG')[0];
            var textData = getElements('text_data','DIV',item)[0];
            var itemTitle = getElements('item_title','DIV',item)[0];
           
            if(imageData){
                setCssOpacity(imageData,0);
                imageData.style.visibility = 'visible';
                fade(imageData,7);
            }
            if(textData) fade(textData, 7);
            if(itemTitle) fade(itemTitle, 7);
            
            currentItemIndex < (lastItemIndex) ? currentItemIndex++ : clearInterval(fade_clearer);
        },50)
    }
    
    /* Effect 2: Image Fader */
    Slider.prototype.startImageFade = function(){
        var contentImages = this.contentList.getElementsByTagName('IMG');
        for( var i=0; i<contentImages.length; i++ )
            setCssOpacity(contentImages[i], 0);
        
    }
    Slider.prototype.endImageFade = function(){
        var contentImages = this.contentList.getElementsByTagName('IMG');
        var currentOpacity = 0;
        var maxOpacity = 99;
        var clearer = setInterval(function(){
                for( var i=0; i<contentImages.length; i++){
                    if(currentOpacity < maxOpacity){
                        setCssOpacity(contentImages[i], currentOpacity);
                        currentOpacity++;
                    }
                }
                if(currentOpacity == maxOpacity){
                    clearInterval(clearer);
                }
        },75);
    }
    
    /*  Effect 3: Context Transparency */
    Slider.prototype.startTransSlide = function(){
        var firstItemIndex = (this.activeGroup-1) * this.groupSize;
        var lastItemIndex = (firstItemIndex + this.groupSize < this.contentItems.length ? firstItemIndex + this.groupSize : this.contentItems.length);
        for(var i=0; i<this.contentItems.length; i++)
            setCssOpacity(this.contentItems[i],20)
        for(var i=firstItemIndex; i<lastItemIndex; i++)
            setCssOpacity(this.contentItems[i], 99)
    }
    Slider.prototype.endTransSlide = function(){
        for(var i=0; i<this.contentItems.length; i++)
            setCssOpacity(this.contentItems[i],99)        
    }
    
/*  Auto Advance
    ------------ */
    Slider.prototype.autoAdvance = function(){
        var moduleObject=this;
        var advanceInterval = this.advanceSeconds * 1000;
        var advancemethod =  
        function(){
			moduleObject.autoclearer = setInterval(
				function(){
					if(moduleObject.activeGroup < moduleObject.numGroups){
                            moduleObject.advance();
					} else {
						clearInterval(moduleObject.autoclearer);
						var toStart = moduleObject.activeGroup - 1;
						moduleObject.retract(toStart);
					}
				},advanceInterval);
			}
        
        window.addEventListener ? window.addEventListener('load', advancemethod, false) : window.attachEvent('onload', advancemethod);
        
        //stop the behavior if module is interacted with
        var interactionControls = [this.nextTrigger, this.prevTrigger];
        if(this.groupTriggers)
            for(var i=0; i<this.groupTriggers.length; i++)
                interactionControls.push(this.groupTriggers[i]);
        
        if(this.tabs)
            for(var i=0; i<this.tabs.length; i++)
                interactionControls.push(this.tabs[i].tabElement)
        
        //stop the periodic advancement if the user interacts with the module
        for(var i=0; i<interactionControls.length; i++){
            if(window.addEventListener) interactionControls[i].addEventListener("click", function(){clearInterval(moduleObject.autoclearer)}, false);
            if(window.attachEvent) interactionControls[i].attachEvent("onclick", function(){clearInterval(moduleObject.autoclearer)}, false);
        }
        
    }

/*****************
 *  TAB OBJECTS  *
 *****************/
 function Tab(args){
	 this.tabElement = document.getElementById(args.tabId);
     this.contentElement = document.getElementById(args.contentId); 
 }
 Tab.prototype.activate = function(){
     this.tabElement.className += ' active';
     this.contentElement.style.visibility = 'visible';
 }
 Tab.prototype.deactivate = function(){
     this.tabElement.className = this.tabElement.className.replace(' active', '');
     this.contentElement.style.visibility = 'hidden';
 }


 /* UTILITY FUNCTIONS
   ----------------- */

/*  Function:   getElements(classname,tagname,root)   
    Purpose:    Convenience Methods for Grabbing Elements. Returns all 
                elements which are members of a specified class
    -------------------------------------------------------------------------------------------------- */
    function getElements(classname, tagname, root){
        if(!root) root = document;
        else if (typeof root == "string") root = document.getElementById(root);
        if(!tagname) tagname = "*";
        var all = root.getElementsByTagName(tagname);
        if(!classname) return all;
        var elements = [];
        for(var i = 0; i < all.length; i++){
            var element = all[i];
            if(isMember(element,classname))
                elements.push(element)
        }
        return elements;
    }
    function isMember(element, classname){
        var classes = element.className;
        if(!classes) return false;
        if(classes ==classname) return true;
        var whitespace = /\s+/;
        if (!whitespace.test(classes)) return false;
        
        var c = classes.split(whitespace);
        for(var i = 0; i < c.length; i++){
            if (c[i] == classname) return true;
        }
        return false;
    }
    

/*  Function:   setCssOpacity(targetedElement, opacity)
    Purpose:    sets the CSS Opacity of an element
    -------------------------------------------------------------------------------------------------- */
    function setCssOpacity(targetedElement, opacity) {
        //if(detectMacXFF()) return; //Firefox/OSX cannot handle css opacity and opaque flash together
        opacity = (opacity == 100)?99.999:opacity; //only accept and set values up to 99.9
        targetedElement.style.filter = "alpha(opacity: "+opacity+")"; // IE/Win
        targetedElement.style.opacity = opacity/100;// Safari 1.2, newer Firefox and Mozilla, CSS3
    }

/*  Function:   fade(fadeElement)
    Purpose:    Uses timers and css opacity to produce a fading effect on an element
    -------------------------------------------------------------------------------------------------- */
    function fade(fadeElement, fadeSpeed){
        var fadeSpeed =  fadeSpeed || 9;
        var opacity = 0;
        var clearer = setInterval(function(){
            setCssOpacity(fadeElement, opacity);
            opacity < 99 ? opacity+=fadeSpeed : clearInterval(clearer);
        },10)
    }

    /** jQuery IE6 Hover fix Latest Module Tabs **/
    jQuery(document).ready(function() {
        jQuery('div#featured_stories_h a.slide_control_next').hover(function() {
            jQuery(this).addClass('LATESTHoverArrowIENext');
        }, function() {
            jQuery(this).removeClass('LATESTHoverArrowIENext');
        });
        jQuery('div#featured_stories_h a.slide_control_previous').hover(function() {
            jQuery(this).addClass('LATESTHoverArrowIEPrev');
        }, function() {
            jQuery(this).removeClass('LATESTHoverArrowIEPrev');
        });
    });
    /** jQuery IE6 Hover fix Latest Module Tabs **/
    jQuery(document).ready(function() {
        jQuery('div#designer_timeline a.slide_control_next').hover(function() {
            jQuery(this).addClass('TIMELINEHoverArrowIENext');
        }, function() {
            jQuery(this).removeClass('TIMELINEHoverArrowIENext');
        });
        jQuery('div#designer_timeline a.slide_control_previous').hover(function() {
            jQuery(this).addClass('TIMELINEHoverArrowIEPrev');
        }, function() {
            jQuery(this).removeClass('TIMELINEHoverArrowIEPrev');
        });
    });
    /** jQuery IE6 Hover fix Video Carousel **/
    jQuery(document).ready(function() {
        jQuery('div#featured_stories_v a.slide_control_next').hover(function() {
            jQuery(this).addClass('VIDEOHoverArrowIENext');
        }, function() {
            jQuery(this).removeClass('VIDEOHoverArrowIENext');
        });
        jQuery('div#featured_stories_v a.slide_control_previous').hover(function() {
            jQuery(this).addClass('VIDEOHoverArrowIEPrev');
        }, function() {
            jQuery(this).removeClass('VIDEOHoverArrowIEPrev');
        });
    });




