// lightbox_plus.js // == written by takuya otani === // == copyright (c) 2006 simpleboxes/serendipitynz ltd. == /* copyright (c) 2006 takuya otani/simpleboxes - http://serennz.cool.ne.jp/sb/ copyright (c) 2006 serendipitynz - http://serennz.cool.ne.jp/snz/ this script is licensed under the creative commons attribution 2.5 license http://creativecommons.org/licenses/by/2.5/ basically, do anything you want, just leave my name and link. */ /* original script : lightbox js : fullsize image overlays copyright (c) 2005 lokesh dhakar - http://www.huddletogether.com for more information on this script, visit: http://huddletogether.com/projects/lightbox/ */ // ver. 20090729 - fixed a bug ( lightbox may not be closed properly ) // ver. 20090709 - fixed a bug ( loading image is not shown properly ) // ver. 20090707 - implemented animation feature // ver. 20090318 - fixed a bug ( prev/next are not shown in some occasions ) // ver. 20061027 - fixed a bug ( not work at xhtml documents on netscape7 ) // ver. 20061026 - fixed bugs // ver. 20061010 - implemented image set feature // ver. 20060921 - fixed a bug / added overall view // ver. 20060920 - added flag to prevent mouse wheel event // ver. 20060919 - fixed a bug // ver. 20060918 - implemented functionality of wheel zoom & drag'n drop // ver. 20060131 - fixed a bug to work correctly on internet explorer for windows // ver. 20060128 - implemented functionality of echoic word // ver. 20060120 - implemented functionality of caption and close button // === elements === document.getelemetsbyclassname = function(name,target) { var result = []; var object = null; var search = new regexp(['(^|\\s)',name,'(\\s|$)'].join('')); if (target && target.getelementsbytagname) object = target.getelementsbytagname('*'); if (!object) object = document.getelementsbytagname ? document.getelementsbytagname('*') : document.all; for (var i=0,n=object.length;i d.body.offsetwidth) ? d.body.scrollwidth : d.body.offsetwidt; var h = (window.innerheight && window.scrollmaxy) ? window.innerheight + window.scrollmaxy : (d.body.scrollheight > d.body.offsetheight) ? d.body.scrollheight : d.body.offsetheight; var updated = this.win.update(); if (w < this.win.w) w = this.win.w; if (h < this.win.h) h = this.win.h; if (updated || w != this.w || h != this.h) { this.w = w; this.h = h; return true; } return false; }; function pagepos() { // page position object this.x = 0; this.y = 0; return this; } pagepos.prototype.update = function() { var d = document; var x = (window.pagexoffset) ? window.pagexoffset : (d.documentelement && d.documentelement.scrollleft) ? d.documentelement.scrollleft : (d.body) ? d.body.scrollleft : 0; var y = (window.pageyoffset) ? window.pageyoffset : (d.documentelement && d.documentelement.scrolltop) ? d.documentelement.scrolltop : (d.body) ? d.body.scrolltop : 0; if (x != this.x || y != this.y) { this.x = x; this.y = y; return true; } return false; }; // === browser === if ( !window.spica ) { var spica = {}; spica.browser = new function() { this.name = navigator.useragent; this.iswinie = this.ismacie = false; this.isgecko = this.name.match(/gecko\//); this.issafari = this.name.match(/applewebkit/); this.issafari3 = (this.name.match(/applewebkit\/(\d\d\d)/) && parseint(regexp.$1) > 500); this.iskhtml = this.issafari || navigator.appversion.match(/konqueror|khtml/); this.isopera = window.opera; if (document.all && !this.isgecko && !this.issafari && !this.isopera) { this.iswinie = this.name.match(/win/); this.ismacie = this.name.match(/mac/); this.isnewie = (this.name.match(/msie (\d\.\d)/) && regexp.$1 > 6.5); } }; spica.event = { cache : false, getevent : function(evnt) { return (evnt) ? evnt : ((window.event) ? window.event : null); }, getkey : function(evnt) { if (!evnt) return; // do nothing return (evnt.keycode) ? evnt.keycode : evnt.charcode; }, stop : function(evnt) { if (!evnt) return; // do nothing try { evnt.stoppropagation(); } catch(err) {}; evnt.cancelbubble = true; try { evnt.preventdefault(); } catch(err) {}; return (evnt.returnvalue = false); }, register : function(object, type, handler) { if (!object) return; if (type == 'keypress' && !object.addeventlistener) type = 'keydown'; if (type == 'mousewheel' && spica.browser.isgecko) type = 'dommousescroll'; if (!this.cache) this.cache = []; if (object.addeventlistener) { this.cache.push([object,type,handler]); object.addeventlistener(type, handler, false); } else if (object.attachevent) { this.cache.push([object,type,handler]); object.attachevent('on' + type,handler); } else { object['on' + type] = handler; } }, deregister : function(object, type, handler) { if (!object) return; if (type == 'keypress' && !object.addeventlistener) type = 'keydown'; if (type == 'mousewheel' && spica.browser.isgecko) type = 'dommousescroll'; if (object.removeeventlistener) object.removeeventlistener(type, handler, false); else if (object.detachevent) object.detachevent('on' + type, handler); else object['on' + type] = null; }, deregisterall : function() { if (!spica.event.cache) return for (var i=0,n=spica.event.cache.length;i= targ.w || orig.h >= targ.h) && orig.h && orig.w) ratio = ((targ.w / orig.w) < (targ.h / orig.h)) ? targ.w / orig.w : targ.h / orig.h; self._expandable = (ratio < 1.0) ? true : false; self._anim.w = math.floor(orig.w * ratio); self._anim.h = math.floor(orig.h * ratio); if (self._resizable) self._expandable = true; if (spica.browser.iswinie) self._box.style.display = "block"; self._imgpos.x = self._pos.x + (targ.w - self._img.width) / 2; self._imgpos.y = self._pos.y + (targ.h - self._img.height) / 2; navi.y = math.floor(self._img.height / 2) - 10; self._show_overall(false); var loading = document.getelementbyid('loadingimage'); if (loading) { loading.style.left = [(self._img.width - 30) / 2,'px'].join(''); loading.style.top = [(self._img.height - 30) / 2,'px'].join(''); } } else { // zoomed or actual sized image var width = parseint(self._imgs[self._open].w * self._level); var height = parseint(self._imgs[self._open].h * self._level); self._minpos.x = self._pos.x + targ.w - self._img.width; self._minpos.y = self._pos.y + targ.h - self._img.height; if (self._img.width <= targ.w) self._imgpos.x = self._pos.x + (targ.w - self._img.width) / 2; else { if (self._imgpos.x > self._pos.x) self._imgpos.x = self._pos.x; else if (self._imgpos.x < self._minpos.x) self._imgpos.x = self._minpos.x; zoom.x = 15 + self._pos.x - self._imgpos.x; navi.p = self._pos.x - self._imgpos.x - 5; navi.n = self._img.width - self._page.win.w + self._imgpos.x + 25; if (spica.browser.iswinie) navi.n -= 10; } if (self._img.height <= targ.h) { self._imgpos.y = self._pos.y + (targ.h - self._img.height) / 2; navi.y = math.floor(self._img.height / 2) - 10; } else { if (self._imgpos.y > self._pos.y) self._imgpos.y = self._pos.y; else if (self._imgpos.y < self._minpos.y) self._imgpos.y = self._minpos.y; zoom.y = 15 + self._pos.y - self._imgpos.y; navi.y = math.floor(targ.h / 2) - 10 + self._pos.y - self._imgpos.y; } self._anim.w = width; self._anim.h = height; self._show_overall(true); } self._box.style.left = [self._imgpos.x,'px'].join(''); self._box.style.top = [self._imgpos.y,'px'].join(''); self._zoomimg.style.left = [zoom.x,'px'].join(''); self._zoomimg.style.top = [zoom.y,'px'].join(''); self._wrap.style.left = self._pos.x; if (self._prev && self._next) { self._prev.style.left = [navi.p,'px'].join(''); self._next.style.right = [navi.n,'px'].join(''); self._prev.style.top = self._next.style.top = [navi.y,'px'].join(''); } self._changed = true; }, _show_overall : function(visible) { var self = this; if (self._overall == null) return; if (visible) { if (self._open == -1) return; var base = 100; var outer = { w:0, h:0, x:0, y:0 }; var inner = { w:0, h:0, x:0, y:0 }; var orig = { w:self._img.width , h:self._img.height }; var targ = { w:self._page.win.w - 30, h:self._page.win.h - 30 }; var max = orig.w; if (max < orig.h) max = orig.h; if (max < targ.w) max = targ.w; if (max < targ.h) max = targ.h; if (max < 1) return; outer.w = parseint(orig.w / max * base); outer.h = parseint(orig.h / max * base); inner.w = parseint(targ.w / max * base); inner.h = parseint(targ.h / max * base); outer.x = self._pos.x + targ.w - base - 20; outer.y = self._pos.y + targ.h - base - 20; inner.x = outer.x - parseint((self._imgpos.x - self._pos.x) / max * base); inner.y = outer.y - parseint((self._imgpos.y - self._pos.y) / max * base); self._overall.style.left = [outer.x,'px'].join(''); self._overall.style.top = [outer.y,'px'].join(''); self._overall.style.width = [outer.w,'px'].join(''); self._overall.style.height = [outer.h,'px'].join(''); self._indicator.style.left = [inner.x,'px'].join(''); self._indicator.style.top = [inner.y,'px'].join(''); self._indicator.style.width = [inner.w,'px'].join(''); self._indicator.style.height = [inner.h,'px'].join(''); self._overall.style.display = 'block' self._indicator.style.display = 'block'; } else { self._overall.style.display = 'none'; self._indicator.style.display = 'none'; } }, _set_size : function(onresize) { var self = this; if (self._open == -1) return; if (!self._page.update() && !self._pos.update() && !self._changed) return; if (spica.browser.iswinie) { self._wrap.style.width = [self._page.win.w,'px'].join(''); self._wrap.style.height = [self._page.win.h,'px'].join(''); self._wrap.style.top = [self._pos.y,'px'].join(''); } if (onresize) self._set_photo_size(); }, _set_cursor : function(obj) { var self = this; if (spica.browser.iswinie && !spica.browser.isnewie) return; obj.style.cursor = 'pointer'; }, _current_setindex : function() { var self = this; if (!self._openedset) return -1; var list = self._sets[self._openedset]; for (var i=0,n=list.length;i -1) { if (check > 0) self._prev.style.display = 'inline'; if (check < self._get_setlength() - 1) self._next.style.display = 'inline'; } if (!self._expandable || !self._zoomimg) return; self._zoomimg.src = (self._expanded) ? self._shrink : self._expand; self._zoomimg.style.display = 'inline'; }, _hide_action : function() { var self = this; if (self._zoomimg) self._zoomimg.style.display = 'none'; if (self._open > -1 && self._expanded) self._dragstop(null); if (self._prev) self._prev.style.display = 'none'; if (self._next) self._next.style.display = 'none'; }, _zoom : function() { var self = this; var closebtn = document.getelementbyid('closebutton'); if (self._expanded) { self._reset_func(); self._expanded = false; if (closebtn) closebtn.style.display = 'inline'; } else if (self._open > -1) { self._level = 1; self._imgpos.x = self._pos.x; self._imgpos.y = self._pos.y; self._expanded = true; self._funcs.drag = function(evt) { self._dragstart(evt) }; self._funcs.dbl = function(evt) { self._close(null) }; if (self._resizable) { self._funcs.wheel = function(evt) { self._onwheel(evt) }; spica.event.register(self._box,'mousewheel',self._funcs.wheel); } spica.event.register(self._img,'mousedown',self._funcs.drag); spica.event.register(self._img,'dblclick',self._funcs.dbl); self._show_caption(false); if (closebtn) closebtn.style.display = 'none'; } self._set_photo_size(); self._show_action(); }, _reset_func : function() { var self = this; if (self._funcs.wheel != null) spica.event.deregister(self._box,'mousewheel',self._funcs.wheel); if (self._funcs.move != null) spica.event.deregister(self._img,'mousemove',self._funcs.move); if (self._funcs.up != null) spica.event.deregister(self._img,'mouseup',self._funcs.up); if (self._funcs.drag != null) spica.event.deregister(self._img,'mousedown',self._funcs.drag); if (self._funcs.dbl != null) spica.event.deregister(self._img,'dblclick',self._funcs.dbl); self._funcs = {'move':null,'up':null,'drag':null,'wheel':null,'dbl':null}; }, _onwheel : function(evt) { var self = this; var delta = 0; evt = spica.event.getevent(evt); if (evt.wheeldelta) delta = event.wheeldelta/-120; else if (evt.detail) delta = evt.detail/3; if (spica.browser.isopera) delta = - delta; var step = (self._level < 1) ? 0.1 : (self._level < 2) ? 0.25 : (self._level < 4) ? 0.5 : 1; self._level = (delta > 0) ? self._level + step : self._level - step; if (self._level > 8) self._level = 8; else if (self._level < 0.5) self._level = 0.5; self._set_photo_size(); return spica.event.stop(evt); }, _dragstart : function(evt) { var self = this; evt = spica.event.getevent(evt); self._curpos.x = evt.screenx; self._curpos.y = evt.screeny; self._funcs.move = function(evnt) { self._dragging(evnt); }; self._funcs.up = function(evnt) { self._dragstop(evnt); }; spica.event.register(self._img,'mousemove',self._funcs.move); spica.event.register(self._img,'mouseup',self._funcs.up); return spica.event.stop(evt); }, _dragging : function(evt) { var self = this; evt = spica.event.getevent(evt); self._imgpos.x += evt.screenx - self._curpos.x; self._imgpos.y += evt.screeny - self._curpos.y; self._curpos.x = evt.screenx; self._curpos.y = evt.screeny; self._set_photo_size(); return spica.event.stop(evt); }, _dragstop : function(evt) { var self = this; evt = spica.event.getevent(evt); if (self._funcs.move != null) spica.event.deregister(self._img,'mousemove',self._funcs.move); if (self._funcs.up != null) spica.event.deregister(self._img,'mouseup',self._funcs.up); self._funcs.move = null; self._funcs.up = null; self._set_photo_size(); return (evt) ? spica.event.stop(evt) : false; }, _show_caption : function(enable) { var self = this; var caption = document.getelementbyid('lightboxcaption'); if (!caption) return; if (caption.innerhtml.length == 0 || !enable) { caption.style.display = 'none'; } else { // now display caption caption.style.top = [self._img.height + 10,'px'].join(''); // 10 is top margin of lightbox caption.style.left = '0px'; caption.style.width = [self._img.width + 20,'px'].join(''); // 20 is total side margin of lightbox caption.style.display = 'block'; } }, _toggle_wrap : function(flag) { var self = this; self._wrap.style.display = flag ? "block" : "none"; if (self._hiding.length == 0 && !self._first) { // some objects may overlap on overlay, so we hide them temporarily. var tags = ['select','embed','object']; for (var i=0,n=tags.length;i= self._imgs.length) return; self._open = num; // set opened image number self._prepare(); self._set_photo_size(); imag.onload = function() { self._expanded = false; if (self._imgs[self._open].w == -1) { // store original image width and height self._imgs[self._open].w = imag.width; self._imgs[self._open].h = imag.height; } var caption = document.getelementbyid('lightboxcaption'); if (caption) try { caption.innerhtml = self._imgs[self._open].title; } catch(e) {} self._anim.t = (new date()).gettime(); self._timer = window.setinterval( function() { self._run() }, 20); self._img.setattribute('title',self._imgs[self._open].title); self._anim.step = ( self._anim.f ) ? 0 : 2; self._set_photo_size(); // calc and set lightbox size if ( !self._anim.f ) // animator is disabled, so apply immediately self._show_image(); if (self._imgs[self._open].set != 'lightbox') { var set = self._imgs[self._open].set; if (self._sets[set].length > 1) self._openedset = set; if (!self._prev || !self._next) self._openedset = null; } }; self._expandable = false; self._expanded = false; self._anim.step = -1; imag.src = self._imgs[self._open].src; }, _run : function() { var self = this; var t = (new date()).gettime(); if ( t - self._anim.t < 50 ) return; self._anim.t = t; self._set_size(true); if ( self._anim.step == 0 || self._anim.w != self._img.width || self._anim.h != self._img.height ) { self._doresizing(); } else if ( self._anim.step == 1 ) { self._dofadein(); } else if ( self._anim.step == 3 ) { self._dofadeout(); } }, _show_image : function() { var self = this; if (self._open == -1) return; self._img.src = self._imgs[self._open].src; var loading = document.getelementbyid('loadingimage'); if (loading) loading.style.display = 'none'; var effect = document.getelementbyid('effectimage'); if (effect && (!effect.classname || self._imgs[self._open].cls == effect.classname)) effect.style.display = 'block'; var closebtn = document.getelementbyid('closebutton'); if (closebtn) closebtn.style.display = 'inline'; self._show_caption(true); }, _doresizing : function() { var self = this; var diff = { x: ( self._anim.f ) ? math.floor((self._anim.w - self._img.width) / 3) : 0, y: ( self._anim.f ) ? math.floor((self._anim.h - self._img.height) / 3) : 0 }; self._img.width += diff.x; self._img.height += diff.y; if ( math.abs(diff.x) < 1 ) self._img.width = self._anim.w; if ( math.abs(diff.y) < 1 ) self._img.height = self._anim.h; if ( self._anim.w == self._img.width && self._anim.h == self._img.height ) { self._changed = false; self._set_photo_size(); if ( self._anim.step == 0 ) { self._anim.step = 1; // move on the next stage self._anim.a = 0; self._show_image(); self._setopacity(self._img,self._anim.a); } else if ( self._anim.step == 2 && !self._expanded) self._show_caption(true); } }, _dofadein : function() { var self = this; self._anim.a += 2; if ( self._anim.a > 10 ) { self._anim.step = 2; // move on the next stage self._anim.a = 9.9; } self._setopacity(self._img,self._anim.a); }, _dofadeout : function() { var self = this; self._anim.a -= 1; if ( self._anim.a < 1 ) { self._anim.step = 2; // finish self._anim.a = 0; if ( self._timer != null ) { window.clearinterval(self._timer); self._timer = null; } self._toggle_wrap(false); } self._setopacity(self._wrap,self._anim.a); }, _setopacity : function(elem, alpha) { if (spica.browser.iswinie) elem.style.filter = 'alpha(opacity=' + (alpha * 10) + ')'; else elem.style.opacity = alpha / 10; }, _close_box : function() { var self = this; self._open = -1; self._openedset = null; self._hide_action(); self._reset_func(); self._show_overall(false); self._box.style.display = "none"; if ( !self._anim.f && self._timer != null ) { window.clearinterval(self._timer); self._timer = null; } }, _show_next : function(direction) { var self = this; if (!self._openedset) return self._close(null); var index = self._current_setindex() + direction; var targ = self._sets[self._openedset][index]; self._close_box(); self._show(targ); }, _close : function(evt) { var self = this; if (evt != null) { evt = spica.event.getevent(evt); var targ = evt.target || evt.srcelement; if (targ && targ.getattribute('id') == 'lightboximage' && self._expanded) return; } self._close_box(); if ( self._anim.f && self._anim.step == 2 ) { self._anim.step = 3; self._anim.a = 5; } else { self._toggle_wrap(false); } } }; spica.event.run(function() { var lightbox = new lightbox({ loadingimg:'resource/loading.gif', expandimg:'resource/expand.gif', shrinkimg:'resource/shrink.gif', blankimg:'resource/blank.gif', previmg:'resource/prev.gif', nextimg:'resource/next.gif', closeimg:'resource/close.gif', effectimg:'resource/zzoop.gif', effectpos:{x:-40,y:-20}, effectclass:'effectable', resizable:true, animation:true }); });