// check if browser supports everything needed function SLIDE_general_support() { var d = document; var b = d.body; if (!b) return 1; if (!d.getElementById) return 2; } // check if named element supports everything needed function SLIDE_element_support(elementName, checkLevel) { var d = document; var e = d.getElementById(elementName); if (!e) return 1; if (checkLevel=='basic') return 0; if (typeof(e.offsetTop)!='number') return 2; if (typeof(e.offsetHeight)!='number') return 3; if (checkLevel=='position') return 0; if (!e.style) return 4; if (typeof(e.style.top)!='string') return 5; if (typeof(e.style.position)!='string') return 6; return 0; } // how much window has scrolled // courtesy of www.quirksmode.org function SLIDE_scrollTop() { var d = document; if (self.pageYOffset) { // all except IE return self.pageYOffset; } else if (d.documentElement && d.documentElement.scrollTop) { // Explorer 6 Strict return d.documentElement.scrollTop; } else { // all other Explorers var b = d.body; return b.scrollTop; } } // viewport height // courtesy of www.quirksmode.org function SLIDE_clientHeight() { var d = document; if (self.innerHeight) { // all except Explorer return self.innerHeight; } else if (d.documentElement && d.documentElement.clientHeight) { // Explorer 6 Strict Mode return d.documentElement.clientHeight; } else { // other Explorers var b = d.body; return b.clientHeight; } } // function that updates the slider position function SLIDE_update(sliderName, containerName, slideSpeed, updateInterval, breakerName, cDelta) { // grab elements var d = document; var slider = d.getElementById(sliderName); var container = d.getElementById(containerName); if (breakerName) var breaker = d.getElementById(breakerName); // init slider position var topStopper = container.offsetTop + cDelta; var wantedPosition = topStopper; // determine would-be position in regard to viewport var clientHeight = SLIDE_clientHeight(); var scrollTop = SLIDE_scrollTop(); // if element is shorter than or equal with the viewport if (slider.offsetHeight <= clientHeight) { // align element top margin with viewport top margin wantedPosition = scrollTop; } // if element is bigger than the viewport else { // if element top margin is lower than the viewport top margin if (scrollTop < slider.offsetTop) { // align element top margin with top viewport margin wantedPosition = scrollTop; } // if element bottom margin is higher than the bottom viewport margin else if (scrollTop + clientHeight > slider.offsetTop + slider.offsetHeight) { // align element bottom margin with bottom viewport margin wantedPosition = scrollTop + clientHeight - slider.offsetHeight; } else { // we're in the middle, and the element is taller than the viewport, leave as it is wantedPosition = slider.offsetTop; } } // next, we have to adjust position in regard to container // did the slider go up past the top of the container? if (wantedPosition < topStopper) { wantedPosition = topStopper; } else { // did the slider go down past the bottom of the container? if (wantedPosition + slider.offsetHeight >= topStopper + container.offsetHeight) { wantedPosition = topStopper + container.offsetHeight - slider.offsetHeight; } else { // slider is in the visible area with either both margins or none // no adjustment needed, let user scroll it normally } } // if there's a breaker, use it if (breaker) { if (wantedPosition + slider.offsetHeight > breaker.offsetTop) { wantedPosition = breaker.offsetTop - slider.offsetHeight; } } // adjust jump according to requested speed if (slideSpeed != 0) { var delta = Math.ceil(Math.abs(slider.offsetTop - wantedPosition) * slideSpeed); wantedPosition = (slider.offsetTop > wantedPosition) ? slider.offsetTop - delta : slider.offsetTop + delta; } // ** SWITCH FROM ABSOLUTE (PAGE VALUE) TO RELATIVE (INSIDE CONTAINER) VALUE ** var wPold = wantedPosition; relativePosition = wantedPosition - topStopper; // sanity checks // did it pass over the top margin of the container? if (relativePosition < 0) { relativePosition = 0; } // did it pass over the lower margin of the container? if (relativePosition + slider.offsetHeight > container.offsetHeight) { relativePosition = container.offsetHeight - slider.offsetHeight; } // set the new position slider.style.top = relativePosition + 'px'; // detect anomalies; most likely user resized fonts if (wantedPosition != slider.offsetTop) { // recalculate cDelta cDelta = slider.offsetTop - container.offsetTop; // force a reset jump slider.style.top = '0px'; } //debugging /*window.status= 'rP='+relativePosition +', wP='+wantedPosition +(wantedPosition!=slider.offsetTop?'*':'') +', c.oT='+container.offsetTop +', s.oT='+slider.offsetTop +', s.oH='+slider.offsetHeight +', tS='+topStopper +', cH='+clientHeight +', sT='+scrollTop +', cD='+cDelta ;*/ // set hook to call myself again later; this is better than calling myself directly, // because the used memory is freed and reallocated, rather than allocated over and over setTimeout("SLIDE_update('"+sliderName+"','"+containerName+"',"+slideSpeed+","+updateInterval+",'"+breakerName+"',"+cDelta+")", updateInterval); } // function that tests slider data and launches it if it checks out function SLIDE_launch_slider(sInfo) { // init vars var d = document; var er = 0; // test and init slider er = SLIDE_element_support(sInfo[0], 'style'); if (er) return 0; s = d.getElementById(sInfo[0]); // test and init container er = SLIDE_element_support(sInfo[1], 'position'); if (er) return 0; var c = d.getElementById(sInfo[1]); // test and init breaker if (sInfo[4]) { er = SLIDE_element_support(sInfo[4], 'position'); if (er) return 0; var b = d.getElementById(sInfo[4]); } else { var b = false; } // force relative positioning s.style.position = 'relative'; // launch slider SLIDE_update(sInfo[0], sInfo[1], sInfo[2], sInfo[3], sInfo[4], s.offsetTop - c.offsetTop); }