Author: echatellier Date: 2010-02-01 18:46:41 +0100 (Mon, 01 Feb 2010) New Revision: 2856 Added: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Image.tml trunk/pollen-ui/src/main/webapp/css/lightbox.css trunk/pollen-ui/src/main/webapp/img/lightbox/ trunk/pollen-ui/src/main/webapp/img/lightbox/closelabel.gif trunk/pollen-ui/src/main/webapp/img/lightbox/loading.gif trunk/pollen-ui/src/main/webapp/img/lightbox/nextlabel.gif trunk/pollen-ui/src/main/webapp/img/lightbox/prevlabel.gif trunk/pollen-ui/src/main/webapp/js/lightbox.js Removed: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Image.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java trunk/pollen-ui/src/main/webapp/poll/ImageDisplay.tml trunk/pollen-ui/src/main/webapp/poll/Results.tml trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml Log: Fix #103 : Pr?\195?\169visualisation des images (based on lightbox scripts) Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Image.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Image.java 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Image.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -27,13 +27,10 @@ import org.apache.commons.lang.StringUtils; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Link; -import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.StreamResponse; import org.apache.tapestry5.annotations.Parameter; -import org.apache.tapestry5.dom.Element; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.services.Response; -import org.chorem.pollen.ui.base.ContextLink; import org.slf4j.Logger; /** @@ -52,55 +49,88 @@ * @author rannou * @version $Id$ */ -public class Image { +public class Image extends ImageContextLink { /** Chemin de l'image */ @Parameter(required = true) - private String _src; + private String src; - @Parameter(required = true) - private ContextLink _context; - /** Texte alternatif */ @Parameter - private String _alt; + private String alt; /** Largeur de l'image */ @Parameter - private int _width; + private int width; /** Hauteur de l'image */ @Parameter - private int _height; + private int height; @Inject private Logger logger; @Inject - private ComponentResources _resources; + private ComponentResources resources; - void beginRender(MarkupWriter writer) { - Link link = _resources.createEventLink("imageLink", _src, _width, - _height); - Element img = writer.element("img", "src", link, "alt", _alt); + /** + * @return the src + */ + public String getSrc() { + return src; + } - _resources.renderInformalParameters(writer); + /** + * @return the alt + */ + public String getAlt() { + return alt; } - void afterRender(MarkupWriter writer) { - writer.end(); + /** + * @return the width + */ + public int getWidth() { + return width; } + /** + * @return the height + */ + public int getHeight() { + return height; + } + + /** + * Create a link to call "thumbLink" event. + * + * @return event link + */ + public Link getThumbLink() { + return resources.createEventLink("imageLink", src, width, + height, true); + } + + /** + * Create a link to call "imageLink" event. + * + * @return event link + */ + public Link getImageLink() { + return resources.createEventLink("imageLink", src, width, + height, false); + } + /** Affichage de l'image */ public StreamResponse onImageLink(final String src, final int width, - final int height) { + final int height, boolean thumb) { // security : src containing .. are filtered, to not access to full system if (StringUtils.isEmpty(src) || src.contains("..")) { return null; } - File file = _context.getFile(src); + File file = getFile(src, thumb); FileInputStream stream = null; try { stream = new FileInputStream(file); @@ -132,7 +162,7 @@ return stream; } - public void prepareResponse(Response arg0) { + public void prepareResponse(Response response) { } } Deleted: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -1,68 +0,0 @@ - -package org.chorem.pollen.ui.components; - -import java.io.File; -import org.apache.tapestry5.annotations.Parameter; -import org.apache.tapestry5.ioc.annotations.Inject; -import org.chorem.pollen.ui.base.ContextLink; -import org.chorem.pollen.ui.services.Configuration; - -/** - * ImageContextLink - * - * Created: 4 nov. 2009 - * - * @author fdesbois - * @version $Revision$ - * - * Mise a jour: $Date$ - * par : $Author$ - */ -public class ImageContextLink implements ContextLink { - - public static final String THUMB_PREFIX = "thumb_"; - - @Inject - private Configuration config; - - /** - * Directory for files getting or saving from this context - * (ie. subdirectory where images are uploaded, main directory is defined by contextPath) - */ - @Parameter - private String dir; - - /** - * true for thumbnails images prefixed by {@link Configuration.IMG_DIR} - */ - @Parameter - private boolean thumb; - - @Override - public String getContextPath() { - return config.getProperty(Configuration.IMG_DIR); - } - - @Override - public File getFile(String filename) { - if (thumb) { - filename = THUMB_PREFIX + filename; - } - return new File(getImageDir(), filename); - } - - /** - * Get the directory where are uploaded the images from the context. - * @return a File corresponding to the image directory - */ - public File getImageDir() { - File result = null; - if (dir != null && !dir.isEmpty()) { - result = new File(getContextPath(), dir); - } else { - result = new File(getContextPath()); - } - return result; - } - -} Added: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java (rev 0) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/ImageContextLink.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -0,0 +1,87 @@ +/* *##% Pollen + * Copyright (C) 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. ##%*/ + +package org.chorem.pollen.ui.components; + +import java.io.File; +import org.apache.tapestry5.annotations.Parameter; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.chorem.pollen.ui.base.ContextLink; +import org.chorem.pollen.ui.services.Configuration; + +/** + * ImageContextLink + * + * Created: 4 nov. 2009 + * + * @author fdesbois + * @version $Revision$ + * + * Mise a jour: $Date$ + * par : $Author$ + */ +public class ImageContextLink implements ContextLink { + + public static final String THUMB_PREFIX = "thumb_"; + + @Inject + private Configuration config; + + /** + * Directory for files getting or saving from this context + * (ie. subdirectory where images are uploaded, main directory is defined by contextPath) + */ + @Parameter + private String dir; + + /** + * true for thumbnails images prefixed by {@link Configuration.IMG_DIR} + */ + @Parameter + private boolean thumb; + + @Override + public String getContextPath() { + return config.getProperty(Configuration.IMG_DIR); + } + + @Override + public File getFile(String filename) { + return getFile(filename, thumb); + } + + public File getFile(String filename, boolean thumb) { + if (thumb) { + filename = THUMB_PREFIX + filename; + } + return new File(getImageDir(), filename); + } + + /** + * Get the directory where are uploaded the images from the context. + * @return a File corresponding to the image directory + */ + public File getImageDir() { + File result = null; + if (dir != null && !dir.isEmpty()) { + result = new File(getContextPath(), dir); + } else { + result = new File(getContextPath()); + } + return result; + } + +} Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -36,6 +36,8 @@ * * @author rannou * @version $Id$ + * + * @deprecated not used anymore (displayed by ligthbox now) */ public class ImageDisplay { Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -30,6 +30,7 @@ import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.annotations.Component; +import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary; import org.apache.tapestry5.annotations.IncludeStylesheet; import org.apache.tapestry5.annotations.InjectComponent; import org.apache.tapestry5.annotations.InjectPage; @@ -64,7 +65,8 @@ * @author rannou * @version $Id$ */ -@IncludeStylesheet("context:css/results.css") +@IncludeStylesheet({"context:css/results.css", "context:css/lightbox.css"}) +@IncludeJavaScriptLibrary({"${tapestry.scriptaculous}/builder.js","context:js/lightbox.js"}) public class Results { @Parameter(defaultPrefix = BindingConstants.MESSAGE, value = "title") @Property Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java 2010-02-01 17:46:41 UTC (rev 2856) @@ -30,9 +30,9 @@ import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.ValidationException; import org.apache.tapestry5.annotations.Component; +import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary; import org.apache.tapestry5.annotations.IncludeStylesheet; import org.apache.tapestry5.annotations.InjectComponent; -import org.apache.tapestry5.annotations.InjectPage; import org.apache.tapestry5.annotations.Log; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Persist; @@ -88,7 +88,8 @@ * @author rannou * @version $Id$ */ -@IncludeStylesheet("context:css/vote.css") +@IncludeStylesheet({"context:css/vote.css", "context:css/lightbox.css"}) +@IncludeJavaScriptLibrary({"${tapestry.scriptaculous}/builder.js","context:js/lightbox.js"}) public class VoteForPoll { @Inject @@ -188,8 +189,8 @@ @Retain private BeanModel voteModel; - @InjectPage - private ImageDisplay imageDisplay; + /*@InjectPage + private ImageDisplay imageDisplay;*/ @InjectComponent private Zone pollZone; @@ -843,6 +844,7 @@ newImageChoice.setName(newImageChoice.getImg().getFileName() .replace(' ', '_')); poll.getChoiceDTOs().add(newImageChoice); + //File imgFile = getImgContext().getImageDir(); // dir set in getImgContext() File imgFile = getImgContext().getImageDir(); // dir set in getImgContext() ImageUtil.saveImage(newImageChoice, imgFile); choiceName = newImageChoice.getName(); @@ -1019,20 +1021,20 @@ } /** Action réalisée lorsqu'on clique sur l'image */ - Object onDisplayImage(String choiceId) { + /*Object onDisplayImage(String choiceId) { imageDisplay.setPoll(poll); imageDisplay.setChoiceId(choiceId); imageDisplay.setPageStyle("Vote"); return imageDisplay; - } + }*/ /** Affichage de "" plutôt que 0 pour le Condorcet */ - String onToClientFromCondorcetInput() { + /*String onToClientFromCondorcetInput() { if (choiceOfVote.getValue() == 0) { return ""; } return null; - } + }*/ /** Récupération d'un entier plutôt que "" pour le Condorcet */ /*Object onParseClientFromCondorcetInput(String input) { Added: trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Image.tml =================================================================== --- trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Image.tml (rev 0) +++ trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Image.tml 2010-02-01 17:46:41 UTC (rev 2856) @@ -0,0 +1,3 @@ +<a xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" rel="lightbox[pollChoiceImages]" href="${imageLink}" title="${alt}"> + <img src="${thumbLink}" alt="${alt}" /> +</a> \ No newline at end of file Added: trunk/pollen-ui/src/main/webapp/css/lightbox.css =================================================================== --- trunk/pollen-ui/src/main/webapp/css/lightbox.css (rev 0) +++ trunk/pollen-ui/src/main/webapp/css/lightbox.css 2010-02-01 17:46:41 UTC (rev 2856) @@ -0,0 +1,27 @@ +#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;} +#lightbox img{ width: auto; height: auto;} +#lightbox a img{ border: none; } + +#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; } +#imageContainer{ padding: 10px; } + +#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; } +#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; } +#imageContainer>#hoverNav{ left: 0;} +#hoverNav a{ outline: none;} + +#prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; } +#prevLink { left: 0; float: left;} +#nextLink { right: 0; float: right;} +#prevLink:hover, #prevLink:visited:hover { background: url(../img/lightbox/prevlabel.gif) left 15% no-repeat; } +#nextLink:hover, #nextLink:visited:hover { background: url(../img/lightbox/nextlabel.gif) right 15% no-repeat; } + +#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; } + +#imageData{ padding:0 10px; color: #666; } +#imageData #imageDetails{ width: 70%; float: left; text-align: left; } +#imageData #caption{ font-weight: bold; } +#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; } +#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;} + +#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; } Property changes on: trunk/pollen-ui/src/main/webapp/css/lightbox.css ___________________________________________________________________ Added: svn:executable + * Added: trunk/pollen-ui/src/main/webapp/img/lightbox/closelabel.gif =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/lightbox/closelabel.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/lightbox/loading.gif =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/lightbox/loading.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/lightbox/nextlabel.gif =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/lightbox/nextlabel.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/lightbox/prevlabel.gif =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/lightbox/prevlabel.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/js/lightbox.js =================================================================== --- trunk/pollen-ui/src/main/webapp/js/lightbox.js (rev 0) +++ trunk/pollen-ui/src/main/webapp/js/lightbox.js 2010-02-01 17:46:41 UTC (rev 2856) @@ -0,0 +1,554 @@ + + +// ----------------------------------------------------------------------------------- +// +// Lightbox v2.04 +// by Lokesh Dhakar - http://www.lokeshdhakar.com +// Last Modification: 2/9/08 +// +// For more information, visit: +// http://lokeshdhakar.com/projects/lightbox2/ +// +// Modification by Fabian Lange - blog.hma-info.de +// - Integration of automatic resize from Michael R. Bagnall - elusivemind.net & Sebastien Grosjean - ZenCocoon.com +// - do not display caption of previous image if new image has none +// - moved opera hack to resolve disortion in FireFox +// - readded window sizes to getPageSize() +// +// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ +// - Free for use in both personal and commercial projects +// - Attribution requires leaving author name, author link, and the license info intact. +// +// Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets. +// Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous. +// +// ----------------------------------------------------------------------------------- +/* + + Table of Contents + ----------------- + Configuration + + Lightbox Class Declaration + - initialize() + - updateImageList() + - start() + - changeImage() + - adjustImageSize() + - resizeImageContainer() + - showImage() + - updateDetails() + - updateNav() + - enableKeyboardNav() + - disableKeyboardNav() + - keyboardAction() + - preloadNeighborImages() + - getPageSize() + - end() + + Function Calls + - document.observe() + +*/ +// ----------------------------------------------------------------------------------- + +// +// Configurationl +// + +var IsResized = false; + +LightboxOptions = Object.extend({ + fileLoadingImage: '../../img/lightbox/loading.gif', + fileBottomNavCloseImage: '../../img/lightbox/closelabel.gif', + + overlayOpacity: 0.7, // controls transparency of shadow overlay + + animate: true, // toggles resizing animations + resizeSpeed: 9, // controls the speed of the image resizing animations (1=slowest and 10=fastest) + + borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable + + featBrowser: true, // set it to true or false to choose to auto-adjust the maximum size to the browser + breathingSize: 50, // control the minimum space around the image box + + // When grouping images this is used to write: Image # of #. + // Change it for non-english localization + labelImage: "Images", + labelOf: "of" +}, window.LightboxOptions || {}); + +// ----------------------------------------------------------------------------------- + +var Lightbox = Class.create(); + +Lightbox.prototype = { + imageArray: [], + activeImage: undefined, + + // initialize() + // Constructor runs on completion of the DOM loading. Calls updateImageList and then + // the function inserts html at the bottom of the page which is used to display the shadow + // overlay and the image container. + // + initialize: function() { + + this.updateImageList(); + + this.keyboardAction = this.keyboardAction.bindAsEventListener(this); + + if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10; + if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1; + + this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0; + this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration + + // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension. + // If animations are turned off, it will be hidden as to prevent a flicker of a + // white 250 by 250 box. + var size = (LightboxOptions.animate ? 250 : 1) + 'px'; + + + // Code inserts html at the bottom of the page that looks similar to this: + // + // <div id="overlay"></div> + // <div id="lightbox"> + // <div id="outerImageContainer"> + // <div id="imageContainer"> + // <img id="lightboxImage"> + // <div style="" id="hoverNav"> + // <a href="#" id="prevLink"></a> + // <a href="#" id="nextLink"></a> + // </div> + // <div id="loading"> + // <a href="#" id="loadingLink"> + // <img src="images/loading.gif"> + // </a> + // </div> + // </div> + // </div> + // <div id="imageDataContainer"> + // <div id="imageData"> + // <div id="imageDetails"> + // <span id="caption"></span> + // <span id="numberDisplay"></span> + // </div> + // <div id="bottomNav"> + // <a href="#" id="bottomNavClose"> + // <img src="images/close.gif"> + // </a> + // </div> + // </div> + // </div> + // </div> + + + var objBody = $$('body')[0]; + + objBody.appendChild(Builder.node('div',{id:'overlay'})); + objBody.appendChild(Builder.node('div',{id:'lightbox'}, [ + Builder.node('div',{id:'outerImageContainer'}, + Builder.node('div',{id:'imageContainer'}, [ + Builder.node('img',{id:'lightboxImage'}), + Builder.node('div',{id:'hoverNav'}, [ + Builder.node('a',{id:'prevLink', href: '#' }), + Builder.node('a',{id:'nextLink', href: '#' }) + ]), + Builder.node('div',{id:'loading'}, + Builder.node('a',{id:'loadingLink', href: '#' }, + Builder.node('img', {src: LightboxOptions.fileLoadingImage}) + ) + ) + ]) + ), + Builder.node('div', {id:'imageDataContainer'}, + Builder.node('div',{id:'imageData'}, [ + Builder.node('div',{id:'imageDetails'}, [ + Builder.node('span',{id:'caption'}), + Builder.node('span',{id:'numberDisplay'}) + ]), + Builder.node('div',{id:'bottomNav'}, + Builder.node('a',{id:'bottomNavClose', href: '#' }, + Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage }) + ) + ) + ]) + ) + ])); + + + $('overlay').hide().observe('click', (function() { this.end(); }).bind(this)); + $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this)); + $('outerImageContainer').setStyle({ width: size, height: size }); + $('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this)); + $('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this)); + $('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this)); + $('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this)); + + var th = this; + (function(){ + var ids = + 'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' + + 'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose'; + $w(ids).each(function(id){ th[id] = $(id); }); + }).defer(); + }, + + // + // updateImageList() + // Loops through anchor tags looking for 'lightbox' references and applies onclick + // events to appropriate links. You can rerun after dynamically adding images w/ajax. + // + updateImageList: function() { + this.updateImageList = Prototype.emptyFunction; + + document.observe('click', (function(event){ + var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]'); + if (target) { + event.stop(); + this.start(target); + } + }).bind(this)); + }, + + // + // start() + // Display overlay and lightbox. If image is part of a set, add siblings to imageArray. + // + start: function(imageLink) { + + $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' }); + + // stretch overlay to fill page and fade in + var arrayPageSize = this.getPageSize(); + $('overlay').setStyle({height: arrayPageSize[1] + 'px' }); + + new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity }); + + this.imageArray = []; + var imageNum = 0; + + if ((imageLink.rel == 'lightbox')){ + // if image is NOT part of a set, add single image to imageArray + this.imageArray.push([imageLink.href, imageLink.title]); + } else { + // if image is part of a set.. + this.imageArray = + $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]'). + collect(function(anchor){ return [anchor.href, anchor.title]; }). + uniq(); + + while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; } + } + + // calculate top and left offset for the lightbox + var arrayPageScroll = document.viewport.getScrollOffsets(); + var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10); + var lightboxLeft = arrayPageScroll[0]; + this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show(); + if (LightboxOptions.featBrowser == true) { Event.observe(window, 'resize', (function(e) {this.adjustImageSize(true); }).bind(this)); } + this.changeImage(imageNum); + }, + + // + // changeImage() + // Hide most elements and preload image in preparation for resizing image container. + // + changeImage: function(imageNum) { + + this.activeImage = imageNum; // update global var + + // hide elements during transition + if (LightboxOptions.animate) this.loading.show(); + this.lightboxImage.hide(); + this.hoverNav.hide(); + this.prevLink.hide(); + this.nextLink.hide(); + this.imageDataContainer.hide(); + this.numberDisplay.hide(); + + var imgPreloader = new Image(); + + // once image is preloaded, resize image container + imgPreloader.onload = (function(){ + this.lightboxImage.src = this.imageArray[this.activeImage][0]; + this.imageArray[this.activeImage][2] = imgPreloader.width; + this.imageArray[this.activeImage][3] = imgPreloader.height; + this.adjustImageSize(false); + }).bind(this); + imgPreloader.src = this.imageArray[this.activeImage][0]; + }, + + // + // adjustImageSize() + // adjust image size if option featBrowser is set to true + // + adjustImageSize: function( recall ) { + // get image size + imgWidth = this.imageArray[this.activeImage][2]; + imgHeight = this.imageArray[this.activeImage][3]; + var arrayPageSize = this.getPageSize(); + // adjust image size if featBrowser option is set to true + if (LightboxOptions.featBrowser == true) { + // calculate proportions + var imageProportion = imgWidth / imgHeight; + var winProportion = arrayPageSize[2] / arrayPageSize[3]; + + if (imageProportion > winProportion) { + // calculate max width base on page width + var maxWidth = arrayPageSize[2] - (LightboxOptions.borderSize * 4) - (LightboxOptions.breathingSize * 2); + var maxHeight = Math.round(maxWidth / imageProportion); + } else { + // calculate maw height base on page height + var maxHeight = arrayPageSize[3] - (LightboxOptions.borderSize * 5) - (arrayPageSize[3] / 15) - LightboxOptions.breathingSize; + var maxWidth = Math.round(maxHeight * imageProportion); + } + if (imgWidth > maxWidth || imgHeight > maxHeight) { + IsResized = true; + imgWidth = maxWidth; + imgHeight = maxHeight; + } else { + IsResized = false; + } + } + this.overlay.setStyle({ height: arrayPageSize[1] + 'px' }); + this.lightboxImage.setStyle({ height: imgHeight + 'px', width: imgWidth + 'px'}); + + if (recall == true) { + this.outerImageContainer.setStyle({height: (imgHeight + (LightboxOptions.borderSize * 2)) + 'px', width: (imgWidth + (LightboxOptions.borderSize * 2)) + 'px'}); + this.imageDataContainer.setStyle({ width: (imgWidth + (LightboxOptions.borderSize * 2)) + 'px' }); + } else { + this.resizeImageContainer(imgWidth, imgHeight); + } + }, + + // + // resizeImageContainer() + // + resizeImageContainer: function(imgWidth, imgHeight) { + + // get current width and height + var widthCurrent = this.outerImageContainer.getWidth(); + var heightCurrent = this.outerImageContainer.getHeight(); + + // get new width and height + var widthNew = (imgWidth + LightboxOptions.borderSize * 2); + var heightNew = (imgHeight + LightboxOptions.borderSize * 2); + + // scalars based on change from old to new + var xScale = (widthNew / widthCurrent) * 100; + var yScale = (heightNew / heightCurrent) * 100; + + // calculate size difference between new and old image, and resize if necessary + var wDiff = widthCurrent - widthNew; + var hDiff = heightCurrent - heightNew; + + if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'}); + if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration}); + + // if new and old image are same size and no scaling transition is necessary, + // do a quick pause to prevent image flicker. + var timeout = 0; + if ((hDiff == 0) && (wDiff == 0)){ + timeout = 100; + if (Prototype.Browser.IE) timeout = 250; + } + + (function(){ + this.prevLink.setStyle({ height: imgHeight + 'px' }); + this.nextLink.setStyle({ height: imgHeight + 'px' }); + this.imageDataContainer.setStyle({ width: widthNew + 'px' }); + + this.showImage(); + }).bind(this).delay(timeout / 1000); + }, + + // + // showImage() + // Display image and begin preloading neighbors. + // + showImage: function(){ + this.loading.hide(); + new Effect.Appear(this.lightboxImage, { + duration: this.resizeDuration, + queue: 'end', + afterFinish: (function(){ this.updateDetails(); }).bind(this) + }); + this.preloadNeighborImages(); + }, + + // + // updateDetails() + // Display caption, image number, and bottom nav. + // + updateDetails: function() { + this.caption.update(this.imageArray[this.activeImage][1] ? this.imageArray[this.activeImage][1] : "").show(); + + // if image is part of set display 'Image x of x' + if (this.imageArray.length > 1){ + if(IsResized) { + this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length + ' <a href="' + this.imageArray[this.activeImage][0] + '" rel="nofollow">Original Size</a>').show(); + } else { + this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show(); + } + } + //opera 9 hack moved here + this.imageDataContainer.setStyle({opacity: .0001}); + this.imageDataContainer.show(); + new Effect.Parallel( + [ + new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }), + new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration }) + ], + { + duration: this.resizeDuration, + afterFinish: (function() { + this.updateNav(); + }).bind(this) + } + ); + }, + + // + // updateNav() + // Display appropriate previous and next hover navigation. + // + updateNav: function() { + + this.hoverNav.show(); + + // if not first image in set, display prev image button + if (this.activeImage > 0) this.prevLink.show(); + + // if not last image in set, display next image button + if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show(); + + this.enableKeyboardNav(); + }, + + // + // enableKeyboardNav() + // + enableKeyboardNav: function() { + document.observe('keydown', this.keyboardAction); + }, + + // + // disableKeyboardNav() + // + disableKeyboardNav: function() { + document.stopObserving('keydown', this.keyboardAction); + }, + + // + // keyboardAction() + // + keyboardAction: function(event) { + var keycode = event.keyCode; + + var escapeKey; + if (event.DOM_VK_ESCAPE) { // mozilla + escapeKey = event.DOM_VK_ESCAPE; + } else { // ie + escapeKey = 27; + } + + var key = String.fromCharCode(keycode).toLowerCase(); + + if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox + this.end(); + } else if ((key == 'p') || (keycode == 37)){ // display previous image + if (this.activeImage != 0){ + this.disableKeyboardNav(); + this.changeImage(this.activeImage - 1); + } + } else if ((key == 'n') || (keycode == 39)){ // display next image + if (this.activeImage != (this.imageArray.length - 1)){ + this.disableKeyboardNav(); + this.changeImage(this.activeImage + 1); + } + } + }, + + // + // preloadNeighborImages() + // Preload previous and next images. + // + preloadNeighborImages: function(){ + var preloadNextImage, preloadPrevImage; + if (this.imageArray.length > this.activeImage + 1){ + preloadNextImage = new Image(); + preloadNextImage.src = this.imageArray[this.activeImage + 1][0]; + } + if (this.activeImage > 0){ + preloadPrevImage = new Image(); + preloadPrevImage.src = this.imageArray[this.activeImage - 1][0]; + } + + }, + + // + // end() + // + end: function() { + this.disableKeyboardNav(); + this.lightbox.hide(); + new Effect.Fade(this.overlay, { duration: this.overlayDuration }); + $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' }); + }, + + // + // getPageSize() + // + getPageSize: function() { + + var xScroll, yScroll; + + if (window.innerHeight && window.scrollMaxY) { + xScroll = window.innerWidth + window.scrollMaxX; + yScroll = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac + xScroll = document.body.scrollWidth; + yScroll = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + xScroll = document.body.offsetWidth; + yScroll = document.body.offsetHeight; + } + + var windowWidth, windowHeight; + + if (self.innerHeight) { // all except Explorer + if(document.documentElement.clientWidth){ + windowWidth = document.documentElement.clientWidth; + } else { + windowWidth = self.innerWidth; + } + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowWidth = document.documentElement.clientWidth; + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowWidth = document.body.clientWidth; + windowHeight = document.body.clientHeight; + } + + // for small pages with total height less then height of the viewport + if(yScroll < windowHeight){ + pageHeight = windowHeight; + } else { + pageHeight = yScroll; + } + + // for small pages with total width less then width of the viewport + if(xScroll < windowWidth){ + pageWidth = xScroll; + } else { + pageWidth = windowWidth; + } + + return [pageWidth,pageHeight,windowWidth,windowHeight]; + } +} + +document.observe('dom:loaded', function () { new Lightbox(); }); + Property changes on: trunk/pollen-ui/src/main/webapp/js/lightbox.js ___________________________________________________________________ Added: svn:executable + * Modified: trunk/pollen-ui/src/main/webapp/poll/ImageDisplay.tml =================================================================== --- trunk/pollen-ui/src/main/webapp/poll/ImageDisplay.tml 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/webapp/poll/ImageDisplay.tml 2010-02-01 17:46:41 UTC (rev 2856) @@ -1,4 +1,4 @@ - +<!-- Not used anymore, images are displayed by lightbox --> <t:border t:address="address" t:pageLogo="${pageStyle}" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter"> Modified: trunk/pollen-ui/src/main/webapp/poll/Results.tml =================================================================== --- trunk/pollen-ui/src/main/webapp/poll/Results.tml 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/webapp/poll/Results.tml 2010-02-01 17:46:41 UTC (rev 2856) @@ -47,9 +47,10 @@ <t:if test="imageType"> <t:ImageContextLink t:id="imgContext" t:thumb="true" t:dir="poll.pollId" /> <span t:type="ck/Tooltip" value="${result.name}" effect="appear"> - <t:eventlink event="displayImage" context="${result.name}"> + <!-- <t:eventlink event="displayImage" context="${result.name}"> <t:image src="${result.name}" alt="${result.name}" t:context="imgContext" /> - </t:eventlink> + </t:eventlink> --> + <t:image src="${result.name}" t:imageid="result.id" alt="${result.name}" t:dir="poll.pollId"/> </span> </t:if> <br/> Modified: trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml =================================================================== --- trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml 2010-02-01 14:30:01 UTC (rev 2855) +++ trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml 2010-02-01 17:46:41 UTC (rev 2856) @@ -98,22 +98,24 @@ </t:loop> </t:if> <t:if test="imageType"> - <t:ImageContextLink t:id="imgContext" t:thumb="true" t:dir="poll.pollId"/> + <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> <t:if test="!isChoiceHidden()"> <t:unless test="isDescNull()"> <th class="desc"> <span t:type="ck/Tooltip" title="${message:description}" value="${choiceOfPoll.description}" effect="blind"> - <t:eventlink event="displayImage" context="${choiceOfPoll.id}"> + <!-- <t:eventlink event="displayImage" context="${choiceOfPoll.id}"> <t:image src="${choiceOfPoll.name}" alt="${choiceOfPoll.name}" t:context="imgContext"/> - </t:eventlink> + </t:eventlink> --> + <t:image t:src="choiceOfPoll.name" alt="choiceOfPoll.description" t:dir="poll.pollId"/> </span> </th> <p:else> <th> - <t:eventlink event="displayImage" context="${choiceOfPoll.id}"> + <!--<t:eventlink event="displayImage" context="${choiceOfPoll.id}"> <t:image src="${choiceOfPoll.name}" alt="${choiceOfPoll.name}" t:context="imgContext"/> - </t:eventlink> + </t:eventlink> --> + <t:image t:src="choiceOfPoll.name" alt="choiceOfPoll.name" t:dir="poll.pollId"/> </th> </p:else> </t:unless> @@ -255,7 +257,7 @@ <!-- Ajout de choix --> - + <t:ImageContextLink t:id="imgContext" t:thumb="true" t:dir="poll.pollId"/> <t:if test="${pollChoiceRunning}"> <h4>${message:addChoice}</h4> <div id="choiceFormDiv">