3 * Copyright(c) 2006-2010 Sencha Inc.
5 * http://www.sencha.com/license
9 Ext.ux.Lightbox = (function(){
25 this.resizeDuration = this.animate ? ((11 - this.resizeSpeed) * 0.15) : 0;
26 this.overlayDuration = this.animate ? 0.2 : 0;
29 Ext.apply(this, Ext.util.Observable.prototype);
30 Ext.util.Observable.constructor.call(this);
31 this.addEvents('open', 'close');
38 initMarkup: function() {
39 els.shim = Ext.DomHelper.append(document.body, {
41 id: 'ux-lightbox-shim'
43 els.overlay = Ext.DomHelper.append(document.body, {
44 id: 'ux-lightbox-overlay'
47 var lightboxTpl = new Ext.Template(this.getTemplate());
48 els.lightbox = lightboxTpl.append(document.body, {}, true);
51 ['outerImageContainer', 'imageContainer', 'image', 'hoverNav', 'navPrev', 'navNext', 'loading', 'loadingLink',
52 'outerDataContainer', 'dataContainer', 'data', 'details', 'caption', 'imageNumber', 'bottomNav', 'navClose'];
54 Ext.each(ids, function(id){
55 els[id] = Ext.get('ux-lightbox-' + id);
58 Ext.each([els.overlay, els.lightbox, els.shim], function(el){
59 el.setVisibilityMode(Ext.Element.DISPLAY)
63 var size = (this.animate ? 250 : 1) + 'px';
64 els.outerImageContainer.setStyle({
70 getTemplate : function() {
72 '<div id="ux-lightbox">',
73 '<div id="ux-lightbox-outerImageContainer">',
74 '<div id="ux-lightbox-imageContainer">',
75 '<img id="ux-lightbox-image">',
76 '<div id="ux-lightbox-hoverNav">',
77 '<a href="#" id="ux-lightbox-navPrev"></a>',
78 '<a href="#" id="ux-lightbox-navNext"></a>',
80 '<div id="ux-lightbox-loading">',
81 '<a id="ux-lightbox-loadingLink"></a>',
85 '<div id="ux-lightbox-outerDataContainer">',
86 '<div id="ux-lightbox-dataContainer">',
87 '<div id="ux-lightbox-data">',
88 '<div id="ux-lightbox-details">',
89 '<span id="ux-lightbox-caption"></span>',
90 '<span id="ux-lightbox-imageNumber"></span>',
92 '<div id="ux-lightbox-bottomNav">',
93 '<a href="#" id="ux-lightbox-navClose"></a>',
102 initEvents: function() {
103 var close = function(ev) {
108 els.overlay.on('click', close, this);
109 els.loadingLink.on('click', close, this);
110 els.navClose.on('click', close, this);
112 els.lightbox.on('click', function(ev) {
113 if(ev.getTarget().id == 'ux-lightbox') {
118 els.navPrev.on('click', function(ev) {
120 this.setImage(activeImage - 1);
123 els.navNext.on('click', function(ev) {
125 this.setImage(activeImage + 1);
129 register: function(sel, group) {
130 if(selectors.indexOf(sel) === -1) {
133 Ext.fly(document).on('click', function(ev){
134 var target = ev.getTarget(sel);
138 this.open(target, sel, group);
144 open: function(image, sel, group) {
145 group = group || false;
148 duration: this.overlayDuration,
149 endOpacity: this.overlayOpacity,
150 callback: function() {
155 images.push([image.href, image.title]);
158 var setItems = Ext.query(sel);
159 Ext.each(setItems, function(item) {
161 images.push([item.href, item.title]);
165 while (images[index][0] != image.href) {
170 // calculate top and left offset for the lightbox
171 var pageScroll = Ext.fly(document).getScroll();
173 var lightboxTop = pageScroll.top + (Ext.lib.Dom.getViewportHeight() / 10);
174 var lightboxLeft = pageScroll.left;
175 els.lightbox.setStyle({
176 top: lightboxTop + 'px',
177 left: lightboxLeft + 'px'
180 this.setImage(index);
182 this.fireEvent('open', images[index]);
188 setViewSize: function(){
189 var viewSize = this.getViewSize();
190 els.overlay.setStyle({
191 width: viewSize[0] + 'px',
192 height: viewSize[1] + 'px'
195 width: viewSize[0] + 'px',
196 height: viewSize[1] + 'px'
200 setImage: function(index){
203 this.disableKeyNav();
212 els.dataContainer.setOpacity(0.0001);
213 els.imageNumber.hide();
215 var preload = new Image();
216 preload.onload = (function(){
217 els.image.dom.src = images[activeImage][0];
218 this.resizeImage(preload.width, preload.height);
219 }).createDelegate(this);
220 preload.src = images[activeImage][0];
223 resizeImage: function(w, h){
224 var wCur = els.outerImageContainer.getWidth();
225 var hCur = els.outerImageContainer.getHeight();
227 var wNew = (w + this.borderSize * 2);
228 var hNew = (h + this.borderSize * 2);
230 var wDiff = wCur - wNew;
231 var hDiff = hCur - hNew;
233 var afterResize = function(){
234 els.hoverNav.setWidth(els.imageContainer.getWidth() + 'px');
236 els.navPrev.setHeight(h + 'px');
237 els.navNext.setHeight(h + 'px');
239 els.outerDataContainer.setWidth(wNew + 'px');
244 if (hDiff != 0 || wDiff != 0) {
245 els.outerImageContainer.shift({
248 duration: this.resizeDuration,
250 callback: afterResize,
255 afterResize.call(this);
259 showImage: function(){
262 duration: this.resizeDuration,
264 callback: function(){
265 this.updateDetails();
268 this.preloadImages();
271 updateDetails: function(){
272 var detailsWidth = els.data.getWidth(true) - els.navClose.getWidth() - 10;
273 els.details.setWidth((detailsWidth > 0 ? detailsWidth : 0) + 'px');
275 els.caption.update(images[activeImage][1]);
278 if (images.length > 1) {
279 els.imageNumber.update(this.labelImage + ' ' + (activeImage + 1) + ' ' + this.labelOf + ' ' + images.length);
280 els.imageNumber.show();
283 els.dataContainer.fadeIn({
284 duration: this.resizeDuration/2,
286 callback: function() {
287 var viewSize = this.getViewSize();
288 els.overlay.setHeight(viewSize[1] + 'px');
294 updateNav: function(){
299 // if not first image in set, display prev image button
303 // if not last image in set, display next image button
304 if (activeImage < (images.length - 1))
308 enableKeyNav: function() {
309 Ext.fly(document).on('keydown', this.keyNavAction, this);
312 disableKeyNav: function() {
313 Ext.fly(document).un('keydown', this.keyNavAction, this);
316 keyNavAction: function(ev) {
317 var keyCode = ev.getKey();
320 keyCode == 88 || // x
321 keyCode == 67 || // c
326 else if (keyCode == 80 || keyCode == 37){ // display previous image
327 if (activeImage != 0){
328 this.setImage(activeImage - 1);
331 else if (keyCode == 78 || keyCode == 39){ // display next image
332 if (activeImage != (images.length - 1)){
333 this.setImage(activeImage + 1);
338 preloadImages: function(){
340 if (images.length > activeImage + 1) {
342 next.src = images[activeImage + 1][0];
344 if (activeImage > 0) {
346 prev.src = images[activeImage - 1][0];
351 this.disableKeyNav();
353 els.overlay.fadeOut({
354 duration: this.overlayDuration
357 this.fireEvent('close', activeImage);
360 getViewSize: function() {
361 return [Ext.lib.Dom.getViewWidth(), Ext.lib.Dom.getViewHeight()];
366 Ext.onReady(Ext.ux.Lightbox.init, Ext.ux.Lightbox);