#5513 closed defect (fixed)
dojox.image.Lightbox infinite loading when image not found
Reported by: | guest | Owned by: | Adam Peller |
---|---|---|---|
Priority: | high | Milestone: | |
Component: | Dojox | Version: | 1.0 |
Keywords: | Lightbox onerror | Cc: | [email protected]… |
Blocked By: | Blocking: |
Description
This patch should fix it:
check juniorjazzcollege.nl and click on one of the images to see the patched version.. Or mail me [email protected]… :)
CSS:
.dojoxLightboxError {
height:50px; position:relative; bottom:0; left:0; margin-top:8px; color:#990000; z-index:1000; font-size:10pt; background-color: #fff; text-align: center;
}
JS Lightbox.js:
if(!dojo._hasResourcedojox.image.Lightbox?){ _hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResourcedojox.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"> <div style="position:relative">
<div dojoAttachPoint="imageContainer" class="dojoxLightboxContainer">
<div class="dojoxLightboxError" style="display: none;" dojoAttachPoint="errNode"></div> <img dojoAttachPoint="imgNode" src="${imgUrl}" class="dojoxLightboxImage" alt="${title}"> <div class="dojoxLightboxFooter" dojoAttachPoint="titleNode">
<div class="dijitInline LightboxClose?" dojoAttachPoint="closeNode"></div> <div class="dijitInline LightboxNext?" dojoAttachPoint="nextNode"></div> <div class="dijitInline LightboxPrev?" dojoAttachPoint="prevNode"></div>
<div class="dojoxLightboxText"><span dojoAttachPoint="textNode">${title}</span><span dojoAttachPoint="groupCount" class="dojoxLightboxGroupText"></span></div>
</div>
</div>
</div>
</div> ",
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);
}); this._imgErrorConnect = dojo.connect(this.imgNode,"onerror", this, function(){
this._imageReady = true; this._showError("Image not found"); dojo.disconnect(this._imgErrorConnect);
}); 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 });
}
},
_showError: function(/*String*/err) {
this.errNode.innerHTML = err; this.errNode.style.display = ; this.groupCount.innerHTML = ; this.textNode.innerHTML = ; do this to prevend too large text descriptions var _sizeAnim = dojox.fx.sizeTo({
node: this.containerNode, duration:this.duration, width: 200, height:80
}); _sizeAnim.play(this.duration);
summary: fade in the image, and fire showNav this.connect(_sizeAnim,"onEnd",dojo.hitch(this, function() {
this.errNode.style.display = ; dojo.fadeIn({ node: this.errNode, duration:this.duration,
onEnd: dojo.hitch(this,"_showNav")
}).play(75);
}));
},
_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) }), dojo.fadeOut({ node: this.errNode, duration:(this.duration/2) })
]); this.connect(_loading,"onEnd",dojo.hitch(this, function() {
this.errNode.style.display = 'none'; this.errNode.innerHTML = ; this._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._groupsXnoGroupX?.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;
}
}
});
}
(In [12200]) Bogus checkin to make corrupt ticket disappear. Fixes #5513