/** * Initializes pagers on this page after the document has been loaded */ YAHOO.util.Event.onDOMReady(function () { var pagers = YAHOO.util.Dom.getElementsByClassName('pager'); for (var i = 0; i < pagers.length; i++) { new Tidy.Pager(pagers[i]); } }); // create namespace if (typeof Tidy == 'undefined') { function Tidy() {} } /** * Pager widget * * @param DOMElement container */ Tidy.Pager = function(container) { this.container = container; if (!this.container.id) { YAHOO.util.Dom.generateId(this.container, 'Tidy-pager-'); } var pager_content_nodes = YAHOO.util.Dom.getElementsByClassName( 'pager-content', 'div', this.container); this.id = this.container.id; this.page_container = pager_content_nodes[0]; this.pages_by_id = {}; this.pages = []; this.previous_page = null; this.current_page = null; this.in_animation = null; this.out_animation = null; this.random_start_page = (YAHOO.util.Dom.hasClass(this.container, 'pager-random')); if (YAHOO.util.Dom.hasClass(this.container, 'pager-with-tabs')) { var pager_tab_nodes = YAHOO.util.Dom.getElementsByClassName( 'pager-tabs', 'ul', this.container); this.tabs = pager_tab_nodes[0]; } else { this.tabs = null; } if (YAHOO.util.Dom.hasClass(this.container, 'pager-with-nav')) { this.drawNav(); } else { this.nav = null; } this.history = (!YAHOO.util.Dom.hasClass(this.container, 'pager-no-history')); // add pages var page_nodes = YAHOO.util.Dom.getChildrenBy(this.page_container, function (n) { return (n.nodeName == 'DIV'); }); if (this.tabs) { // initialize pages with tabs var tab_nodes = YAHOO.util.Dom.getChildren(this.tabs); var index = 0; for (var i = 0; i < page_nodes.length; i++) { if (i < tab_nodes.length) { var tab_node = YAHOO.util.Dom.getFirstChildBy(tab_nodes[i], function(n) { return (n.nodeName == 'A'); }); if (tab_node) { this.addPage(new Tidy.Page(page_nodes[i], index, tab_node)); index++; } } } } else { // initialize pages without tabs for (var i = 0; i < page_nodes.length; i++) { this.addPage(new Tidy.Page(page_nodes[i], i)); } } // initialize current page var current_page = null; if (this.history) { var hash = location.hash; hash = (hash.substring(0, 1) == '#') ? hash.substring(1) : hash; if (hash.length) { current_page = this.pages_by_id[hash]; if (current_page) { this.setPage(current_page); } } // check if window location changes from back/forward button use // this doesn't matter in IE and Opera but is nice for Tidy and // recent Safari users. function setupInterval(pager) { var interval_function = function() { pager.checkLocation(); } setInterval(interval_function, (Tidy.Pager.LOCATION_INTERVAL * 1000), pager); } setupInterval(this); } if (!current_page && this.pages.length > 0) { if (this.random_start_page) { this.setPage(this.getPseudoRandomPage()); } else { this.setPage(this.pages[0]); } } } Tidy.Pager.prototype.getPseudoRandomPage = function() { var page = null; if (this.pages.length > 0) { var now = new Date(); page = this.pages[now.getSeconds() % this.pages.length]; } return page; } Tidy.Pager.PAGE_DURATION = 0.15; // seconds Tidy.Pager.LOCATION_INTERVAL = 0.20; // seconds Tidy.Pager.NEXT_TEXT = 'Next'; Tidy.Pager.PREV_TEXT = 'Previous'; Tidy.Pager.PAGE_NUMBER_TEXT = '%s / %s'; Tidy.Pager.prototype.prevPageWithAnimation = function() { var index = this.current_page.index - 1; if (index < 0) { index = this.pages.length - 1; } this.setPageWithAnimation(this.pages[index]); } Tidy.Pager.prototype.nextPageWithAnimation = function() { var index = this.current_page.index + 1; if (index >= this.pages.length) { index = 0; } this.setPageWithAnimation(this.pages[index]); } Tidy.Pager.prototype.drawNav = function() { // create previous link this.prev = document.createElement('a'); this.prev.href = '#'; YAHOO.util.Dom.addClass(this.prev, 'pager-prev'); this.prev.title = Tidy.Pager.PREV_TEXT; this.prev.appendChild(document.createTextNode('')); this.prev_insensitive = document.createElement('span'); this.prev_insensitive.style.display = 'none'; YAHOO.util.Dom.addClass(this.prev_insensitive, 'pager-prev-insensitive'); YAHOO.util.Event.on(this.prev, 'click', function (e) { YAHOO.util.Event.preventDefault(e); this.prevPageWithAnimation(); }, this, true); YAHOO.util.Event.on(this.prev, 'dblclick', function (e) { YAHOO.util.Event.preventDefault(e); }, this, true); // create next link this.next = document.createElement('a'); this.next.href = '#'; YAHOO.util.Dom.addClass(this.next, 'pager-next'); this.next.title = Tidy.Pager.NEXT_TEXT; this.next.appendChild(document.createTextNode('')); this.next_insensitive = document.createElement('span'); this.next_insensitive.style.display = 'none'; YAHOO.util.Dom.addClass(this.next_insensitive, 'pager-next-insensitive'); YAHOO.util.Event.on(this.next, 'click', function (e) { YAHOO.util.Event.preventDefault(e); this.nextPageWithAnimation(); }, this, true); YAHOO.util.Event.on(this.next, 'dblclick', function (e) { YAHOO.util.Event.preventDefault(e); }, this, true); // create navigation element var divider = document.createElement('span'); divider.appendChild(document.createTextNode('|')); YAHOO.util.Dom.addClass(divider, 'pager-nav-divider'); this.page_number = document.createElement('span'); YAHOO.util.Dom.addClass(this.page_number, 'pager-nav-page-number'); this.nav = document.createElement('div'); YAHOO.util.Dom.addClass(this.nav, 'pager-nav'); this.nav.appendChild(this.page_number); this.nav.appendChild(this.prev_insensitive); this.nav.appendChild(this.prev); this.nav.appendChild(divider); this.nav.appendChild(this.next); this.nav.appendChild(this.next_insensitive); this.container.insertBefore(this.nav, this.page_container); } Tidy.Pager.prototype.checkLocation = function() { var hash = location.hash; hash = (hash.substring(0, 1) == '#') ? hash.substring(1) : hash; var current_hash = this.current_page.id; if (hash && hash !== current_hash) { var page = this.pages_by_id[hash]; if (page) { this.setPageWithAnimation(page); this.current_page.focusTab(); // for accessibility } } } Tidy.Pager.prototype.addPage = function(page) { this.pages_by_id[page.id] = page; this.pages.push(page); if (page.tab) { YAHOO.util.Event.on(page.tab, 'click', function (e) { YAHOO.util.Event.preventDefault(e); this.setPageWithAnimation(page); }, this, true); } } Tidy.Pager.prototype.update = function() { if (this.tabs) { this.updateTabs(); } if (this.nav) { this.updateNav(); } } Tidy.Pager.prototype.updateTabs = function() { var class_name = this.tabs.className; class_name = class_name.replace(/pager-selected-[\w-]+/g, ''); class_name = class_name.replace(/^\s+|\s+$/g,''); this.tabs.className = class_name; this.current_page.selectTab(); YAHOO.util.Dom.addClass(this.tabs, 'pager-selected-' + this.current_page.id); } Tidy.Pager.prototype.updateNav = function() { // update page number var page_number = this.current_page.index + 1; var page_count = this.pages.length; var text = Tidy.Pager.PAGE_NUMBER_TEXT.replace(/%s/, page_number); text = text.replace(/%s/, page_count); if (this.page_number.firstChild) { this.page_number.replaceChild(document.createTextNode(text), this.page_number.firstChild); } else { this.page_number.appendChild(document.createTextNode(text)); } // update previous link this.setPrevSensitivity(this.current_page.index != 0); // update next link this.setNextSensitivity(this.current_page.index != this.pages.length - 1); } Tidy.Pager.prototype.setPrevSensitivity = function(sensitive) { if (sensitive) { this.prev_insensitive.style.display = 'none'; this.prev.style.display = 'inline'; } else { this.prev_insensitive.style.display = 'inline'; this.prev.style.display = 'none'; } } Tidy.Pager.prototype.setNextSensitivity = function(sensitive) { if (sensitive) { this.next_insensitive.style.display = 'none'; this.next.style.display = 'inline'; } else { this.next_insensitive.style.display = 'inline'; this.next.style.display = 'none'; } } Tidy.Pager.prototype.setPage = function(page) { if (this.current_page !== page) { if (this.current_page) { this.current_page.deselectTab(); this.current_page.hide(); } if (this.previous_page) { this.previous_page.hide(); } this.previous_page = this.current_page; this.current_page = page; this.current_page.show(); this.update(); } } Tidy.Pager.prototype.setPageWithAnimation = function(page) { if (this.current_page !== page) { if (this.history) { // set address bar to current page var base_location = location.href.split('#')[0]; location.href = base_location + '#' + page.id; } // deselect last selected page (not necessarily previous page) if (this.current_page) { this.current_page.deselectTab(); } // start opacity at current opacity if page was changed while another // page was fading in if (this.in_animation && this.in_animation.isAnimated()) { var start_opacity = parseFloat(YAHOO.util.Dom.getStyle( this.page_container, 'opacity')); this.in_animation.stop(false); } else { var start_opacity = 1.0; } // fade out if we're not already fading out if (!this.out_animation || !this.out_animation.isAnimated()) { // only set previous page if we are not already fading out this.previous_page = this.current_page; this.out_animation = new YAHOO.util.Anim(this.page_container, { opacity: { from: start_opacity, to: 0 } }, Tidy.Pager.PAGE_DURATION, YAHOO.util.Easing.easeOut); this.out_animation.onComplete.subscribe(this.fadeInPage, this, true); this.out_animation.animate(); } // always set current page this.current_page = page; this.update(); } // for Safari 1.5.x bug setting window.location. return false; } Tidy.Pager.prototype.fadeInPage = function() { if (this.previous_page) { this.previous_page.hide(); } this.current_page.show(); this.in_animation = new YAHOO.util.Anim(this.page_container, { opacity: { from: 0, to: 1 } }, Tidy.Pager.PAGE_DURATION, YAHOO.util.Easing.easeIn); this.in_animation.animate(); } /** * Page in a pager * * @param DOMElement element * @param DOMElement tab_element */ Tidy.Page = function(element, index, tab_element) { this.element = element; if (!this.element.id) { YAHOO.util.Dom.generateId(this.element, 'Tidy-pager-page-'); } // Change element id so updating the window.location does not navigate to // the page. This is mostly for IE. if (this.element.id.substring(0, 5) == 'page-') { this.id = this.element.id.substring(5); } else { this.id = this.element.id; } this.element.id = 'page-' + this.id; this.index = index; if (tab_element) { this.tab = tab_element; this.tab.href = '#' + this.id; } else { this.tab = null; } this.hide(); } Tidy.Page.prototype.selectTab = function() { if (this.tab) { YAHOO.util.Dom.addClass(this.tab, 'selected'); } } Tidy.Page.prototype.deselectTab = function() { if (this.tab) { YAHOO.util.Dom.removeClass(this.tab, 'selected'); } } Tidy.Page.prototype.focusTab = function() { if (this.tab) { this.tab.focus(); } } Tidy.Page.prototype.hide = function() { this.element.style.display = 'none'; } Tidy.Page.prototype.show = function() { this.element.style.display = 'block'; }