New file |
0,0 → 1,312 |
if(!dojo._hasResource["dojox.image.Lightbox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
dojo._hasResource["dojox.image.Lightbox"] = true; |
dojo.provide("dojox.image.Lightbox"); |
dojo.experimental("dojox.image.Lightbox"); |
|
dojo.require("dijit.Dialog"); |
dojo.require("dojox.fx"); |
|
dojo.declare("dojox.image.Lightbox", |
dijit._Widget,{ |
// summary: |
// a dojo-based Lightbox implementation. |
// |
// description: |
// an Elegant, keyboard accessible, markup and store capable Lightbox widget to show images |
// in a modal dialog-esque format. Can show individual images as Modal dialog, or can group |
// images with multiple entry points, all using a single "master" Dialog for visualization |
// |
// examples: |
// |
// <a href="image1.jpg" dojoType="dojox.image.Lightbox">show lightbox</a> |
// <a href="image2.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a> |
// <a href="image3.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a> |
// |
// FIXME: not implemented fully yet, though works with basic datastore access. need to manually call |
// widget._attachedDialog.addImage(item,"fromStore") for each item in a store result set. |
// <div dojoType="dojox.image.Lightbox" group="fromStore" store="storeName"></div> |
|
// group: String |
// grouping images in a page with similar tags will provide a 'slideshow' like grouping of images |
group: "", |
|
// title: String |
// A string of text to be shown in the Lightbox beneath the image (empty if using a store) |
title: "", |
|
// href; String |
// link to image to use for this Lightbox node (empty if using a store). |
href: "", |
|
// duration: Integer |
// generic time in MS to adjust the feel of widget. could possibly add various |
// durations for the various actions (dialog fadein, sizeing, img fadein ...) |
duration: 500, |
|
// _allowPassthru: Boolean |
// privately set this to disable/enable natural link of anchor tags |
_allowPassthru: false, |
_attachedDialog: null, // try to share a single underlay per page? |
|
startup: function(){ |
this.inherited("startup", arguments); |
// setup an attachment to the masterDialog (or create the masterDialog) |
var tmp = dijit.byId('dojoxLightboxDialog'); |
if(tmp){ |
this._attachedDialog = tmp; |
}else{ |
// this is the first instance to start, so we make the masterDialog |
this._attachedDialog = new dojox.image._LightboxDialog({ id: "dojoxLightboxDialog" }); |
this._attachedDialog.startup(); |
} |
if(!this.store){ |
// FIXME: full store support lacking, have to manually call this._attachedDialog.addImage(imgage,group) as it stands |
this._addSelf(); |
this.connect(this.domNode, "onclick", "_handleClick"); |
} |
}, |
|
_addSelf: function(){ |
this._attachedDialog.addImage({ |
href: this.href, |
title: this.title |
},this.group||null); |
}, |
|
_handleClick: function(/* Event */e){ |
// summary: handle the click on the link |
if(!this._allowPassthru){ e.preventDefault(); } |
else{ return; } |
this.show(); |
}, |
|
show: function(){ |
this._attachedDialog.show(this); |
}, |
|
disable: function(){ |
// summary, disables event clobbering and dialog, and follows natural link |
this._allowPassthru = true; |
}, |
|
enable: function(){ |
// summary: enables the dialog (prevents default link) |
this._allowPassthru = false; |
} |
|
}); |
|
dojo.declare("dojox.image._LightboxDialog", |
dijit.Dialog,{ |
// |
// Description: |
// |
// a widget that intercepts anchor links (typically around images) |
// and displays a modal Dialog. this is the actual Popup, and should |
// not be created directly. |
// |
// there will only be one of these on a page, so all dojox.image.Lightbox's will us it |
// (the first instance of a Lightbox to be show()'n will create me If i do not exist) |
// |
// note: the could be the ImagePane i was talking about? |
|
// title: String |
// the current title |
title: "", |
|
// FIXME: implement titleTemplate |
|
// inGroup: Array |
// Array of objects. this is populated by from the JSON object _groups, and |
// should not be populate manually. it is a placeholder for the currently |
// showing group of images in this master dialog |
inGroup: null, |
|
// imgUrl: String |
// the src="" attrib of our imageNode (can be null at statup) |
imgUrl: "", |
|
// an array of objects, each object being a unique 'group' |
_groups: { XnoGroupX: [] }, |
_imageReady: false, |
|
templateString:"<div class=\"dojoxLightbox\" dojoAttachPoint=\"containerNode\">\n\t<div style=\"position:relative\">\n\t\t<div dojoAttachPoint=\"imageContainer\" class=\"dojoxLightboxContainer\">\n\t\t\t<img dojoAttachPoint=\"imgNode\" src=\"${imgUrl}\" class=\"dojoxLightboxImage\" alt=\"${title}\">\n\t\t\t<div class=\"dojoxLightboxFooter\" dojoAttachPoint=\"titleNode\">\n\t\t\t\t<div class=\"dijitInline LightboxClose\" dojoAttachPoint=\"closeNode\"></div>\n\t\t\t\t<div class=\"dijitInline LightboxNext\" dojoAttachPoint=\"nextNode\"></div>\t\n\t\t\t\t<div class=\"dijitInline LightboxPrev\" dojoAttachPoint=\"prevNode\"></div>\n\n\t\t\t\t<div class=\"dojoxLightboxText\"><span dojoAttachPoint=\"textNode\">${title}</span><span dojoAttachPoint=\"groupCount\" class=\"dojoxLightboxGroupText\"></span></div>\n\t\t\t</div>\n\t\t</div>\t\n\t\t\n\t</div>\n</div>\n", |
|
startup: function(){ |
// summary: add some extra event handlers, and startup our superclass. |
this.inherited("startup", arguments); |
|
// FIXME: these are supposed to be available in dijit.Dialog already, |
// but aren't making it over. |
dojo.connect(document.documentElement,"onkeypress",this,"_handleKey"); |
this.connect(window,"onresize","_position"); |
|
this.connect(this.nextNode, "onclick", "_nextImage"); |
this.connect(this.prevNode, "onclick", "_prevImage"); |
this.connect(this.closeNode, "onclick", "hide"); |
|
}, |
|
show: function(/* Object */groupData){ |
// summary: starts the chain of events to show an image in the dialog, including showing the dialog |
// if it is not already visible |
|
dojo.style(this.imgNode,"opacity","0"); |
dojo.style(this.titleNode,"opacity","0"); |
|
// we only need to call dijit.Dialog.show() if we're not already open. |
if(!this.open){ this.inherited("show", arguments); } |
|
this._imageReady = false; |
|
this.imgNode.src = groupData.href; |
if((groupData.group && !(groupData == "XnoGroupX")) || this.inGroup){ |
if(!this.inGroup){ |
this.inGroup = this._groups[(groupData.group)]; |
var i = 0; |
// determine where we were or are in the show |
dojo.forEach(this.inGroup,function(g){ |
if (g.href == groupData.href){ |
this._positionIndex = i; |
} |
i++; |
},this); |
} |
if(!this._positionIndex){ this._positionIndex=0; this.imgNode.src = this.inGroup[this._positionIndex].href; } |
this.groupCount.innerHTML = " (" +(this._positionIndex+1) +" of "+this.inGroup.length+")"; |
this.prevNode.style.visibility = "visible"; |
this.nextNode.style.visibility = "visible"; |
}else{ |
this.groupCount.innerHTML = ""; |
this.prevNode.style.visibility = "hidden"; |
this.nextNode.style.visibility = "hidden"; |
} |
this.textNode.innerHTML = groupData.title; |
|
if(!this._imageReady || this.imgNode.complete === true){ |
this._imgConnect = dojo.connect(this.imgNode,"onload", this, function(){ |
this._imageReady = true; |
this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:this.duration }); |
dojo.disconnect(this._imgConnect); |
}); |
// onload doesn't fire in IE if you connect before you set the src. |
// hack to re-set the src after onload connection made: |
if(dojo.isIE){ this.imgNode.src = this.imgNode.src; } |
}else{ |
// do it quickly. kind of a hack, but image is ready now |
this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:1 }); |
} |
}, |
|
_nextImage: function(){ |
// summary: load next image in group |
if(this._positionIndex+1<this.inGroup.length){ |
this._positionIndex++; |
}else{ |
this._positionIndex = 0; |
} |
this._loadImage(); |
}, |
|
_prevImage: function(){ |
// summary: load previous image in group |
if(this._positionIndex==0){ |
this._positionIndex = this.inGroup.length-1; |
}else{ |
this._positionIndex--; |
} |
this._loadImage(); |
}, |
|
_loadImage: function(){ |
// summary: do the prep work before we can show another image |
var _loading = dojo.fx.combine([ |
dojo.fadeOut({ node:this.imgNode, duration:(this.duration/2) }), |
dojo.fadeOut({ node:this.titleNode, duration:(this.duration/2) }) |
]); |
this.connect(_loading,"onEnd","_prepNodes"); |
_loading.play(10); |
}, |
|
_prepNodes: function(){ |
// summary: a localized hook to accompany _loadImage |
this._imageReady = false; |
this.show({ |
href: this.inGroup[this._positionIndex].href, |
title: this.inGroup[this._positionIndex].title |
}); |
}, |
|
resizeTo: function(/* Object */size){ |
// summary: resize our dialog container, and fire _showImage |
var _sizeAnim = dojox.fx.sizeTo({ |
node: this.containerNode, |
duration:size.duration||this.duration, |
width: size.w, |
height:size.h+30 |
}); |
this.connect(_sizeAnim,"onEnd","_showImage"); |
_sizeAnim.play(this.duration); |
}, |
|
_showImage: function(){ |
// summary: fade in the image, and fire showNav |
dojo.fadeIn({ node: this.imgNode, duration:this.duration, |
onEnd: dojo.hitch(this,"_showNav") |
}).play(75); |
}, |
|
_showNav: function(){ |
// summary: fade in the footer, and setup our connections. |
dojo.fadeIn({ node: this.titleNode, duration:200 }).play(25); |
}, |
|
hide: function(){ |
// summary: close the Lightbox |
dojo.fadeOut({node:this.titleNode, duration:200 }).play(25); |
this.inherited("hide", arguments); |
this.inGroup = null; |
this._positionIndex = null; |
}, |
|
addImage: function(/* object */child,/* String? */group){ |
// summary: add an image to this master dialog |
// |
// child.href: String - link to image (required) |
// child.title: String - title to display |
// |
// group: String - attach to group of similar tag |
// or null for individual image instance |
|
var g = group; |
if(!child.href){ return; } |
if(g){ |
if(this._groups[(g)]){ |
this._groups[(g)].push(child); |
}else{ |
this._groups[(g)] = [(child)]; |
} |
}else{ this._groups["XnoGroupX"].push(child); } |
}, |
|
_handleKey: function(/* Event */e){ |
// summary: handle keyboard navigation |
if(!this.open){ return; } |
var key = (e.charCode == dojo.keys.SPACE ? dojo.keys.SPACE : e.keyCode); |
switch(key){ |
case dojo.keys.ESCAPE: this.hide(); break; |
|
case dojo.keys.DOWN_ARROW: |
case dojo.keys.RIGHT_ARROW: |
case 78: // key "n" |
this._nextImage(); break; |
|
case dojo.keys.UP_ARROW: |
case dojo.keys.LEFT_ARROW: |
case 80: // key "p" |
this._prevImage(); break; |
} |
} |
}); |
|
} |