YE = YAHOO.util.Event; YD = YAHOO.util.Dom; YL = YAHOO.util.Lang; YUA = YAHOO.env.ua; CWS = { debug: false, log: function() { if(CWS.debug && typeof console === 'object' && typeof console.log !== 'undefined') { if(YUA.gecko > 0) console.log.apply(this, arguments); else if (YUA.ie > 0 || YUA.webkit) console.log(CWS.sprintf.apply(this, arguments)); } }, hasAllProperties: function(o, properties) { var hasAll = true; for(var i = 0; i < properties.length; i++) { if(!(properties[i] in o)) { CWS.log('Missing property: %s', properties[i]); hasAll = false; } } return hasAll; }, sprintf: function() //from http://code.google.com/p/sprintf/ { var i = 0, a, f = arguments[i++], o = [], m, p, c, x; while (f) { if (m = /^[^\x25]+/.exec(f)) o.push(m[0]); else if (m = /^\x25{2}/.exec(f)) o.push('%'); else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) { if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments."); if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) throw("Expecting number but found " + typeof(a)); switch (m[7]) { case 'b': a = a.toString(2); break; case 'c': a = String.fromCharCode(a); break; case 'd': a = parseInt(a); break; case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break; case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break; case 'o': a = a.toString(8); break; case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break; case 'u': a = Math.abs(a); break; case 'x': a = a.toString(16); break; case 'X': a = a.toString(16).toUpperCase(); break; } a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a); c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' '; x = m[5] - String(a).length; p = m[5] ? CWS.str_repeat(c, x) : ''; o.push(m[4] ? a + p : p + a); } else throw ("Huh ?!"); f = f.substring(m[0].length); } return o.join(''); }, str_repeat: function(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); } }; /** * CWS.Carousel fades images in and out and can display arbitrary html over * each image at arbitrary positions. * * You should only need to call the init function. init() will add * a listener for the canvas id being added to the dom so you can call * init() whether the canvas div is present in the dom or not. The same is * true of the nav unordered list. * * Example: * * * * * * * * * * * * * * *
* * * * */ CWS.Carousel = function() { // private properties of CWS.Carousel var that = null, imageInstances = [], readyImages = [], items = [], imagePath = null, width = null, height = null, canvas = null, currentIndex = null, fadeinImage = null, fadeinOverlay = null, navTemplate = null, nav = null, stop = true, a = null, b = null, current = null, notCurrent = null, showNextDelayTimeout = null; /** * Called once the animation displaying a new image is finished. */ var delayShowNext = function() { CWS.log('Showing: index=%d, duration=%dms', currentIndex, items[currentIndex].displayDuration); YD.setStyle(notCurrent.image, 'opacity', 0); YD.setStyle(notCurrent.overlay, 'opacity', 0); showNextDelayTimeout = setTimeout(showNext, items[currentIndex].displayDuration); }; /** * Called once displayDuration has passed. */ var showNext = function() { if(stop) { CWS.log('Aborting show next'); return; } var nextI = nextIndex(); if(readyImages[nextI] !== true) { CWS.log('Delaying showNext until image %d loaded.', nextI); YE.on(imageInstances[nextI], 'load', function() { readyImages[nextI] = true showNext(); }); return; } var firstShowNext = (currentIndex == -1); increment(); swapCurrent(); current.image.innerHTML = getImageTag(currentIndex); current.overlay.innerHTML = items[currentIndex].overlay; if (YUA.ie > 0) { // internet explorer, text gets ugly if there's no background YD.setStyle(current.overlay, 'background-image', 'url('+getImageSrc(currentIndex)+')'); } positionOverlay(); preloadImage(nextIndex()); if(firstShowNext) { delayShowNext(); return; } var animationType = 'YAHOO.util.Easing.'+items[currentIndex].fadeType; var animDuration = items[currentIndex].transitionDuration; CWS.log('Fading in: index=%d, src=%s, duration=%dms, type=%s', currentIndex, getImageSrc(currentIndex), animDuration, animationType); animDuration = animDuration/1000; animationType = window[animationType]; fadeinImage = new YAHOO.util.Anim( current.image, {opacity: {from: 0, to: 1}}, animDuration, animationType ); fadeinImage.onComplete.subscribe(delayShowNext); fadeinOverlay = new YAHOO.util.Anim( current.overlay, {opacity: {from: 0, to: 1}}, animDuration, animationType ); fadeinImage.animate(); fadeinOverlay.animate(); setTimeout(setActiveNav, items[currentIndex].transitionDuration/2); }; /** * Called when a nav item is clicked. */ var showIndex = function(i) { CWS.log('Show index (nav clicked): index=%d', i); currentIndex = i; preloadImage(i); swapCurrent(); current.image.innerHTML = getImageTag(i); current.overlay.innerHTML = items[i].overlay; positionOverlay(); YD.setStyle(current.image, 'opacity', 1); YD.setStyle(notCurrent.image, 'opacity', 0); YD.setStyle(current.overlay, 'opacity', 1); YD.setStyle(notCurrent.overlay, 'opacity', 0); setActiveNav(); preloadImage(nextIndex()); }; var setActiveNav = function() { //currentIndex will be -1 if initNav happens before initCanvas var i = (currentIndex == -1) ? 0 : currentIndex; that.onChange.fire(items[i]); if(typeof items[0].nav === 'undefined') return; for(var j = 0; j < items.length; j++) { YD.removeClass(items[j].nav, 'carousel-nav-active'); } YD.addClass(items[i].nav, 'carousel-nav-active'); } var swapCurrent = function() { YE.removeListener(current.image, 'click'); YD.setStyle(current.image, 'cursor', 'default'); var t = current; current = notCurrent; notCurrent = t; if(YL.isString(items[currentIndex].url) && items[currentIndex].url.length > 0) { YE.on(current.image, 'click', function(){document.location = items[currentIndex].url}); YD.setStyle(current.image, 'cursor', 'pointer'); } YD.setStyle(current.image, 'z-index', 22); YD.setStyle(current.overlay, 'z-index', 24); YD.setStyle(notCurrent.image, 'z-index', 12); YD.setStyle(notCurrent.overlay, 'z-index', 14); }; var positionOverlay = function() { YD.setStyle(current.overlay, 'left', items[currentIndex].overlayPosition[0]); YD.setStyle(current.overlay, 'top', items[currentIndex].overlayPosition[1]); if (YUA.ie > 0) { // internet explorer YD.setStyle(current.overlay, 'background-position', '-'+items[currentIndex].overlayPosition[0] + ' -' + items[currentIndex].overlayPosition[1]); } }; var preloadImage = function(i) { if(YD.get(getImageId(i))) { CWS.log('Image id %s present already?', getImageId(i)); } if(YL.isObject(imageInstances[i])) { CWS.log('Image already preloaded: index=%d', i); return; } CWS.log('Preloading image: index=%d', i); imageInstances[i] = new Image(); readyImages[i] = false; YE.on(imageInstances[i], 'load', function() { CWS.log('Image %d ready', i); readyImages[i] = true }); imageInstances[i].src = getImageSrc(i); }; var increment = function() { currentIndex = nextIndex(); }; var nextIndex = function() { return (currentIndex+1) % items.length; } var getImageId = function(i) { return 'carousel-image-'+i; }; var getImageTag = function(i) { return '