Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojox.image.Lightbox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojox.image.Lightbox"] = true;
3
dojo.provide("dojox.image.Lightbox");
4
dojo.experimental("dojox.image.Lightbox");
5
 
6
dojo.require("dijit.Dialog");
7
dojo.require("dojox.fx");
8
 
9
dojo.declare("dojox.image.Lightbox",
10
	dijit._Widget,{
11
	// summary:
12
	//	a dojo-based Lightbox implementation.
13
	//
14
	// description:
15
	//	an Elegant, keyboard accessible, markup and store capable Lightbox widget to show images
16
	//	in a modal dialog-esque format. Can show individual images as Modal dialog, or can group
17
	//	images with multiple entry points, all using a single "master" Dialog for visualization
18
	//
19
	// examples:
20
	//
21
	//	<a href="image1.jpg" dojoType="dojox.image.Lightbox">show lightbox</a>
22
	//	<a href="image2.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
23
	//	<a href="image3.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
24
	//
25
	//	FIXME: not implemented fully yet, though works with basic datastore access. need to manually call
26
	//	widget._attachedDialog.addImage(item,"fromStore") for each item in a store result set.
27
	//	<div dojoType="dojox.image.Lightbox" group="fromStore" store="storeName"></div>
28
 
29
	// group: String
30
	//	grouping images in a page with similar tags will provide a 'slideshow' like grouping of images
31
	group: "",
32
 
33
	// title: String
34
	//	A string of text to be shown in the Lightbox beneath the image (empty if using a store)
35
	title: "",
36
 
37
	// href; String
38
	//	link to image to use for this Lightbox node (empty if using a store).
39
	href: "",
40
 
41
	// duration: Integer
42
	//	generic time in MS to adjust the feel of widget. could possibly add various
43
	//	durations for the various actions (dialog fadein, sizeing, img fadein ...)
44
	duration: 500,
45
 
46
	// _allowPassthru: Boolean
47
	//	privately set this to disable/enable natural link of anchor tags
48
	_allowPassthru: false,
49
	_attachedDialog: null, // try to share a single underlay per page?
50
 
51
	startup: function(){
52
		this.inherited("startup", arguments);
53
		// setup an attachment to the masterDialog (or create the masterDialog)
54
		var tmp = dijit.byId('dojoxLightboxDialog');
55
		if(tmp){
56
			this._attachedDialog = tmp;
57
		}else{
58
			// this is the first instance to start, so we make the masterDialog
59
			this._attachedDialog = new dojox.image._LightboxDialog({ id: "dojoxLightboxDialog" });
60
			this._attachedDialog.startup();
61
		}
62
		if(!this.store){
63
			// FIXME: full store support lacking, have to manually call this._attachedDialog.addImage(imgage,group) as it stands
64
			this._addSelf();
65
			this.connect(this.domNode, "onclick", "_handleClick");
66
		}
67
	},
68
 
69
	_addSelf: function(){
70
		this._attachedDialog.addImage({
71
			href: this.href,
72
			title: this.title
73
		},this.group||null);
74
	},
75
 
76
	_handleClick: function(/* Event */e){
77
		// summary: handle the click on the link
78
		if(!this._allowPassthru){ e.preventDefault(); }
79
		else{ return; }
80
		this.show();
81
	},
82
 
83
	show: function(){
84
		this._attachedDialog.show(this);
85
	},
86
 
87
	disable: function(){
88
		// summary, disables event clobbering and dialog, and follows natural link
89
		this._allowPassthru = true;
90
	},
91
 
92
	enable: function(){
93
		// summary: enables the dialog (prevents default link)
94
		this._allowPassthru = false;
95
	}
96
 
97
});
98
 
99
dojo.declare("dojox.image._LightboxDialog",
100
	dijit.Dialog,{
101
	//
102
	// Description:
103
	//
104
	//	a widget that intercepts anchor links (typically around images)
105
	//	and displays a modal Dialog. this is the actual Popup, and should
106
	//	not be created directly.
107
	//
108
	//	there will only be one of these on a page, so all dojox.image.Lightbox's will us it
109
	//	(the first instance of a Lightbox to be show()'n will create me If i do not exist)
110
	//
111
	//	note: the could be the ImagePane i was talking about?
112
 
113
	// title: String
114
	// 	the current title
115
	title: "",
116
 
117
	// FIXME: implement titleTemplate
118
 
119
	// inGroup: Array
120
	//	Array of objects. this is populated by from the JSON object _groups, and
121
	//	should not be populate manually. it is a placeholder for the currently
122
	//	showing group of images in this master dialog
123
	inGroup: null,
124
 
125
	// imgUrl: String
126
	//	the src="" attrib of our imageNode (can be null at statup)
127
	imgUrl: "",
128
 
129
	// an array of objects, each object being a unique 'group'
130
	_groups: { XnoGroupX: [] },
131
	_imageReady: false,
132
 
133
	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",
134
 
135
	startup: function(){
136
		// summary: add some extra event handlers, and startup our superclass.
137
		this.inherited("startup", arguments);
138
 
139
		// FIXME: these are supposed to be available in dijit.Dialog already,
140
		// but aren't making it over.
141
		dojo.connect(document.documentElement,"onkeypress",this,"_handleKey");
142
		this.connect(window,"onresize","_position");
143
 
144
		this.connect(this.nextNode, "onclick", "_nextImage");
145
		this.connect(this.prevNode, "onclick", "_prevImage");
146
		this.connect(this.closeNode, "onclick", "hide");
147
 
148
	},
149
 
150
	show: function(/* Object */groupData){
151
		// summary: starts the chain of events to show an image in the dialog, including showing the dialog
152
		//	if it is not already visible
153
 
154
		dojo.style(this.imgNode,"opacity","0");
155
		dojo.style(this.titleNode,"opacity","0");
156
 
157
		// we only need to call dijit.Dialog.show() if we're not already open.
158
		if(!this.open){ this.inherited("show", arguments); }
159
 
160
		this._imageReady = false;
161
 
162
		this.imgNode.src = groupData.href;
163
		if((groupData.group && !(groupData == "XnoGroupX")) || this.inGroup){
164
			if(!this.inGroup){
165
				this.inGroup = this._groups[(groupData.group)];
166
				var i = 0;
167
				// determine where we were or are in the show
168
				dojo.forEach(this.inGroup,function(g){
169
					if (g.href == groupData.href){
170
						this._positionIndex = i;
171
					}
172
					i++;
173
				},this);
174
			}
175
			if(!this._positionIndex){ this._positionIndex=0; this.imgNode.src = this.inGroup[this._positionIndex].href; }
176
			this.groupCount.innerHTML = " (" +(this._positionIndex+1) +" of "+this.inGroup.length+")";
177
			this.prevNode.style.visibility = "visible";
178
			this.nextNode.style.visibility = "visible";
179
		}else{
180
			this.groupCount.innerHTML = "";
181
			this.prevNode.style.visibility = "hidden";
182
			this.nextNode.style.visibility = "hidden";
183
		}
184
		this.textNode.innerHTML = groupData.title;
185
 
186
		if(!this._imageReady || this.imgNode.complete === true){
187
			this._imgConnect = dojo.connect(this.imgNode,"onload", this, function(){
188
				this._imageReady = true;
189
				this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:this.duration });
190
				dojo.disconnect(this._imgConnect);
191
			});
192
			// onload doesn't fire in IE if you connect before you set the src.
193
			// hack to re-set the src after onload connection made:
194
			if(dojo.isIE){ this.imgNode.src = this.imgNode.src; }
195
		}else{
196
			// do it quickly. kind of a hack, but image is ready now
197
			this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:1 });
198
		}
199
	},
200
 
201
	_nextImage: function(){
202
		// summary: load next image in group
203
		if(this._positionIndex+1<this.inGroup.length){
204
			this._positionIndex++;
205
		}else{
206
			this._positionIndex = 0;
207
		}
208
		this._loadImage();
209
	},
210
 
211
	_prevImage: function(){
212
		// summary: load previous image in group
213
		if(this._positionIndex==0){
214
			this._positionIndex = this.inGroup.length-1;
215
		}else{
216
			this._positionIndex--;
217
		}
218
		this._loadImage();
219
	},
220
 
221
	_loadImage: function(){
222
		// summary: do the prep work before we can show another image
223
		var _loading = dojo.fx.combine([
224
			dojo.fadeOut({ node:this.imgNode, duration:(this.duration/2) }),
225
			dojo.fadeOut({ node:this.titleNode, duration:(this.duration/2) })
226
		]);
227
		this.connect(_loading,"onEnd","_prepNodes");
228
		_loading.play(10);
229
	},
230
 
231
	_prepNodes: function(){
232
		// summary: a localized hook to accompany _loadImage
233
		this._imageReady = false;
234
		this.show({
235
			href: this.inGroup[this._positionIndex].href,
236
			title: this.inGroup[this._positionIndex].title
237
		});
238
	},
239
 
240
	resizeTo: function(/* Object */size){
241
		// summary: resize our dialog container, and fire _showImage
242
		var _sizeAnim = dojox.fx.sizeTo({
243
			node: this.containerNode,
244
			duration:size.duration||this.duration,
245
			width: size.w,
246
			height:size.h+30
247
		});
248
		this.connect(_sizeAnim,"onEnd","_showImage");
249
		_sizeAnim.play(this.duration);
250
	},
251
 
252
	_showImage: function(){
253
		// summary: fade in the image, and fire showNav
254
		dojo.fadeIn({ node: this.imgNode, duration:this.duration,
255
			onEnd: dojo.hitch(this,"_showNav")
256
		}).play(75);
257
	},
258
 
259
	_showNav: function(){
260
		// summary: fade in the footer, and setup our connections.
261
		dojo.fadeIn({ node: this.titleNode, duration:200 }).play(25);
262
	},
263
 
264
	hide: function(){
265
		// summary: close the Lightbox
266
		dojo.fadeOut({node:this.titleNode, duration:200 }).play(25);
267
		this.inherited("hide", arguments);
268
		this.inGroup = null;
269
		this._positionIndex = null;
270
	},
271
 
272
	addImage: function(/* object */child,/* String? */group){
273
		// summary: add an image to this master dialog
274
		//
275
		// child.href: String - link to image (required)
276
		// child.title: String - title to display
277
		//
278
		// group: String - attach to group of similar tag
279
		//	or null for individual image instance
280
 
281
		var g = group;
282
		if(!child.href){ return; }
283
		if(g){
284
			if(this._groups[(g)]){
285
				this._groups[(g)].push(child);
286
			}else{
287
				this._groups[(g)] = [(child)];
288
			}
289
		}else{ this._groups["XnoGroupX"].push(child); }
290
	},
291
 
292
	_handleKey: function(/* Event */e){
293
		// summary: handle keyboard navigation
294
		if(!this.open){ return; }
295
		var key = (e.charCode == dojo.keys.SPACE ? dojo.keys.SPACE : e.keyCode);
296
		switch(key){
297
			case dojo.keys.ESCAPE: this.hide(); break;
298
 
299
			case dojo.keys.DOWN_ARROW:
300
			case dojo.keys.RIGHT_ARROW:
301
			case 78: // key "n"
302
				this._nextImage(); break;
303
 
304
			case dojo.keys.UP_ARROW:
305
			case dojo.keys.LEFT_ARROW:
306
			case 80: // key "p"
307
				this._prevImage(); break;
308
		}
309
	}
310
});
311
 
312
}