/* Class: PopImg Author: Kory Sharp Last Update: 08/12/08 Dependencies: prototype.js, scriptaculous.js?load=effects, builder Usage: Single Image: text or thumbnail Multiple Images: text or thumbnail */ var PopImg = Class.create({ images: [], // images in current pop set loaded: [], // images that have been preloaded heights: [], // store heights of loaded images speed: .3, // duration for transitions below pos: undefined, // index position (from var images) of the current image initialize: function() { // makes sure the keyboard event as well as "this" (PopImg class) are available this.key_events = this.key_events.bindAsEventListener(this); // build out the skeleton of the popimg viewer (overlay and interior) var body = $$('body')[0]; new Insertion.Bottom(body, $(Builder.node('div', { id: 'overlay' })).hide()); $('overlay').observe('click', (function(event) { Event.stop(event); this.close(); }).bind(this)); new Insertion.Bottom(body, $(Builder.node('div', { id: 'popimg' }, [ Builder.node('a', { href: '#', id: 'popimg_close' }), Builder.node('div', { id: 'popimg_image_holder' }, [ $(Builder.node('img', { id: 'popimg_image' })).hide(), Builder.node('div', { id: 'popimg_loading' }) ]), Builder.node('div', { id: 'popimg_caption_holder' }, [ Builder.node('div', { id: 'popimg_caption' }), $(Builder.node('div', { id: 'popimg_nav' }, [ Builder.node('span', { id: 'photo_num' }), Builder.node('a', { href: '#', id: 'popimg_previous' }), Builder.node('a', { href: '#', id: 'popimg_next' }) ])).hide() ]) ])).hide() ); // generate onclick events for the navigational items $('popimg_previous').observe('click', (function(event) { Event.stop(event); this.switch_image(this.pos - 1); }).bind(this)); $('popimg_next').observe('click', (function(event) { Event.stop(event); this.switch_image(this.pos + 1); }).bind(this)); $('popimg_close').observe('click', (function(event) { Event.stop(event); this.close(); }).bind(this)); // read the click event for any link containing popimg document.observe('click', (function(event){ var img = event.findElement('a[rel^=popimg]'); if (img) { event.stop(); this.open(img); } }).bind(this)); }, open: function(img) { // set the height of the overlay $('overlay').setStyle({ height: this.get_window_height() + "px" }); // set the left position of the popimg viewer $('popimg').setStyle({ left: (document.viewport.getWidth() / 2) - ($('popimg').getWidth() / 2) + 'px' }); // load the initial caption during opening (so there is no change when the popimg div fades in) $('popimg_caption').update(img.readAttribute('title')); // fade in the overlay and the popimg container new Effect.Appear('overlay', { from: 0, to: .84, duration: this.speed, afterFinish: (function() { new Effect.Appear('popimg', { from: 0, to: 1, duration: this.speed, afterFinish: (function() { this.find_images(img); this.enable_keyboard(); }).bind(this) }); }).bind(this) }); }, close: function() { $('popimg').hide(); $('popimg_image').hide(); this.disable_keyboard(); new Effect.Fade('overlay', { duration: this.speed }); }, find_images: function(img) { this.images = []; this.loaded = []; this.pos = 0; if (img.readAttribute('rel') == 'popimg') { title = img.readAttribute('title').split('|'); this.images.push([img.readAttribute('href'), title[0], title[1], title[2]]); this.loaded.push(false); } else { $$('a[href][rel="' + img.readAttribute('rel') + '"]').uniq().each((function(img) { title = img.readAttribute('title').split('|'); this.images.push([img.readAttribute('href'), title[0], title[1], title[2]]); this.loaded.push(false); }).bind(this)); for (var i = 0; i < this.images.length; i++ ) { if (this.images[i][0] == img.readAttribute('href')) { this.pos = i; break; } } } this.switch_image(this.pos); }, switch_image: function(pos) { if (this.images.length < 2) $('popimg_nav').hide(); else $('popimg_nav').show(); if (this.images.length > 1 || !$('popimg_image').visible()) { // make sure pos is in range if (pos < 0) pos = this.images.length - 1; else if (pos >= this.images.length) pos = 0; this.pos = pos; // update the image caption caption = ''; title = this.images[this.pos][1]; credit = this.images[this.pos][2]; desc = this.images[this.pos][3]; if (title != '') { caption = "

" + title; if (credit != '') caption += " by " + credit + ""; caption += "

"; } caption += desc; $('popimg_caption').update(caption); $('photo_num').update('photo ' + (this.pos + 1) + '/' + this.images.length); new Effect.Fade('popimg_image', { duration: this.speed, afterFinish: (function() { if (!this.loaded[this.pos]) $('popimg_loading').show(); var preload = new Image(); preload.onload = (function() { new_height = arguments[0].height; this.loaded[this.pos] = true; this.heights[this.pos] = new_height; this.preload(); $('popimg_loading').hide(); new Effect.Morph('popimg_image_holder', { style: 'height: ' + new_height + 'px', duration: .5, afterFinish: (function() { $('overlay').setStyle({ height: this.get_window_height() + "px" }); $('popimg_image').src = this.images[this.pos][0]; new Effect.Appear('popimg_image', { duration: this.speed }); }).bind(this) }); }).bind(this, preload); preload.src = this.images[this.pos][0]; }).bind(this) }); } }, preload: function() { // preload the previous and next images var previous = (this.pos > 0 && !this.loaded[this.pos - 1]) ? this.pos - 1 : this.images.length - 1; var back_preload = new Image(); back_preload.onload = (function() { this.loaded[previous] = true; }).bind(this); back_preload.src = this.images[previous][0]; var next = (this.pos < (this.images.length - 1) && !this.loaded[this.pos + 1]) ? this.pos + 1 : 0; var next_preload = new Image(); next_preload.onload = (function() { this.loaded[next] = true; }).bind(this); next_preload.src = this.images[next][0]; }, enable_keyboard: function() { Event.observe(document, "keydown", this.key_events); }, disable_keyboard: function() { Event.stopObserving(document, "keydown", this.key_events); }, key_events: function(event) { switch (event.keyCode) { // 'b' or left arrow case 37: case 66: this.switch_image(this.pos - 1); break; // 'n' or right arrow case 39: case 78: this.switch_image(this.pos + 1); break; // esc, 'x', or 'c' case 27: case 67: case 88: this.close(); break; default: break; } }, get_window_height: function() { // retrieve the height of the document including scrollable area var document_height, window_height; if (window.innerHeight && window.scrollMaxY) document_height = window.innerHeight + window.scrollMaxY; else if (document.body.scrollHeight > document.body.offsetHeight) document_height = document.body.scrollHeight; else document_height = document.body.offsetHeight; if (self.innerHeight) window_height = self.innerHeight; else if (document.documentElement && document.documentElement.clientHeight) window_height = document.documentElement.clientHeight; else if (document.body) window_height = document.body.clientHeight; return (document_height < window_height) ? window_height : document_height; } }); Event.observe(document, "dom:loaded", function() { var pop = new PopImg(); });