-
1. Re: RichFaces & Slideshow
rhasselbaum Dec 23, 2007 4:49 PM (in response to cstefkivoila)I'm also looking for a way to implement a slideshow with RichFaces. I have it mostly working: I use <a4j:poll> to rerender an IMG element at periodic intervals. But I'd like to be able to do a smooth fade between images, and so far I've had no luck with <rich:effect>. Any suggestions?
-
2. Re: RichFaces & Slideshow
rhasselbaum Jan 2, 2008 11:17 AM (in response to cstefkivoila)FWIW, I did get this working. I created a page-scoped controller component in Seam that supplies two overlapping <h:graphicImage> elements with new images on a rotating basis each time an action method is called. I use <a4j:pll> to call the action periodically and rerender the new "active" image. And finally, a little bit of JavaScript kicks off a Fade effect and switches the z-index of the two images in response to the <a4j:poll>'s oncomplete event.
One nice thing is that it degrades gracefully if the user has JavaScript disabled. They just see a random image when the page loads. -
3. Re: RichFaces & Slideshow
cstefkivoila Jan 31, 2008 6:26 AM (in response to cstefkivoila)Could you please provide us an example of your code?
Thanks. -
4. Re: RichFaces & Slideshow
rhasselbaum Jan 31, 2008 10:22 AM (in response to cstefkivoila)I could do that, although I'm planning to revisit this code when I get some time. It works fine most of the time, but I'm also using Seam, and I've noticed that on occasion, the polling request redirects the user to the no-conversation-view page. This seems to happen when the polling request overlaps another request that is beginning or ending a Seam conversation. Need to investigate how to prevent this.
-
5. Re: RichFaces & Slideshow
techieexchange Feb 1, 2008 4:25 AM (in response to cstefkivoila)Hi,
@rhasselbaum
Would be great if you could share your work here or in wiki.
Thanks -
6. Re: RichFaces & Slideshow
rhasselbaum Feb 1, 2008 10:39 AM (in response to cstefkivoila)Sure. It would probably have been better to implement this as a JSF component, but I haven't learned how to do that. Anyway, here's the controller class (a Seam component).
/** * Controller for a simple slideshow UI element. The controller selects images * randomly from a resource folder for display. The UI is expected to consist of * two overlapping image elements (called "frames", but not in the HTML sense). * These are updated with new images on an alternating basis every time the * {@link #transition()} method is called. The reason for having two frames * instead of one is that it enables the implementation of smooth transitions * such as fading on the client side. Each frame is assigned an ID that * corresponds to the element (e.g. HTML) ID. The controller exposes properties * that allow the view to determine which frame should be active and visible at * any given time. Initially, the second frame is active, since it would be the * topmost element in z-order by default. */ @Name("slideShowController") @Scope(ScopeType.PAGE) public class SlideShowController implements Serializable { /** * The path relative to the web root containing random images to be chosen. * The path should begin and end with a forward slash and contain only * eligible images. At least two images MUST be present in the path. */ private static final String IMAGES_PATH = "/images/houses/"; /** * The first frame component ID. */ private String m_firstFrameComponentId; /** * The second frame component ID. */ private String m_secondFrameComponentId; /** * Resource paths to image files. */ private List<String> m_imageFiles; /** * Path to the image contained in the first frame. */ private String m_firstFrameImage; /** * Path to the image contained in the second frame. */ private String m_secondFrameImage; /** * True if the first frame is showing. False if the second frame is showing. */ private boolean m_showingFirstFrame = false; /** * The Seam context. */ @In(value = "facesContext") private FacesContext m_facesContext; /** * Create new instance. */ public SlideShowController() { // No op. } /** * Set up initial controller state. */ @Create public void init() { ExternalContext externalContext = m_facesContext.getExternalContext(); Set<String> resourcePaths = externalContext.getResourcePaths(IMAGES_PATH); if (resourcePaths.size() < 2) { // We can get into an infinite loop if there are less than two // unique images. throw new IllegalStateException("Image list must have at least two images."); } String uuid = UUID.randomUUID().toString(); if (m_firstFrameComponentId == null) m_firstFrameComponentId = "frame1-" + uuid; if (m_secondFrameComponentId == null) m_secondFrameComponentId = "frame2-" + uuid; m_imageFiles = Collections.unmodifiableList(new ArrayList<String>(resourcePaths)); m_firstFrameImage = getRandomImageFile(); m_secondFrameImage = m_firstFrameImage; } /** * Choose and return a random image file from the images folder. */ private String getRandomImageFile() { return m_imageFiles.get((int) (Math.random() * (double) m_imageFiles.size())); } /** * Path to the image contained in the first frame. */ public String getFirstFrameImage() { return m_firstFrameImage; } /** * Path to the image contained in the second frame. */ public String getSecondFrameImage() { return m_secondFrameImage; } /** * Get component ID of the currently active frame. */ public String getActiveFrameComponentId() { if (m_showingFirstFrame) { return m_firstFrameComponentId; } else { return m_secondFrameComponentId; } } /** * Get component ID of the currently active frame. */ public String getInactiveFrameComponentId() { if (m_showingFirstFrame) { return m_secondFrameComponentId; } else { return m_firstFrameComponentId; } } /** * True if the first frame is showing. False if the second frame is showing. */ public boolean isShowingFirstFrame() { return m_showingFirstFrame; } /** * The first frame component ID. */ public String getFirstFrameComponentId() { return m_firstFrameComponentId; } /** * The first frame component ID. */ public void setFirstFrameComponentId(String firstFrameComponentId) { m_firstFrameComponentId = firstFrameComponentId; } /** * The second frame component ID. */ public String getSecondFrameComponentId() { return m_secondFrameComponentId; } /** * The second frame component ID. */ public void setSecondFrameComponentId(String secondFrameComponentId) { m_secondFrameComponentId = secondFrameComponentId; } /** * The Faces context. */ public FacesContext getFacesContext() { return m_facesContext; } /** * The Faces context. */ public void setFacesContext(FacesContext facesContext) { m_facesContext = facesContext; } /** * Transition from one frame to the other. A new, random image is selected * for the next frame, which is guaranteed to be different from the prior * frame. At least two images MUST be present in the image path. */ public void transition() { if (m_showingFirstFrame) { // Fetch new (unique!) image for the second frame. do { m_secondFrameImage = getRandomImageFile(); } while (m_secondFrameImage.equals(m_firstFrameImage)); } else { // Fetch new (unique!) image for the first frame. do { m_firstFrameImage = getRandomImageFile(); } while (m_firstFrameImage.equals(m_secondFrameImage)); } // Switch active frames. m_showingFirstFrame = !m_showingFirstFrame; } }
Next. here is the fragment of XHTML that contains the images.<div id="slideshow-container"> <rich:effect name="hideSlide" type="Fade" /> <a4j:poll action="#{slideShowController.transition()}" interval="10000" timeout="10000" reRender="#{slideShowController.activeFrameComponentId}" oncomplete="BHA_SlideShow.switchFrame('#{slideShowController.inactiveFrameComponentId}', '#{slideShowController.activeFrameComponentId}', hideSlide)" /> <h:graphicImage value="#{slideShowController.firstFrameImage}" id="#{slideShowController.firstFrameComponentId}" /> <h:graphicImage value="#{slideShowController.secondFrameImage}" id="#{slideShowController.secondFrameComponentId}" /> </div>
Here are the CSS styles for the relevant bits:#slideshow-container { border: 1px solid; border-color: #ffff04; margin: 10px; width: 180px; height: 135px; } #slideshow-container img { position: absolute; margin: 0px; width: inherit; height: inherit; }
And finally, the bit of JavaScript that gets called for the oncomplete event./** * Implement simple slideshow transition in concert with RuchFaces/Script.aculo.us. * Clients should call BHA_SlideShow.switchFrame to effect a smooth transition betweenn * two overlapping image (slide) elements. */ var BHA_SlideShow = function() { return { /** * Implement transition between two overlapping slide elements. * fromElementId: The slide element we're transitioning from. Its z-index should be 2 at the * start of this call. It will be moved down to 1. * toElementId: The slide element we're transitioning to. Its z-index should be 1 at the start * of this call. It will be moved up to 2. */ switchFrame : function(fromElementId, toElementId, hideFunction) { var transitionTimeSec = 2.0 hideFunction({targetId:fromElementId,duration:transitionTimeSec}); setTimeout("BHA_SlideShow.reorderFrames('"+ fromElementId + "', '"+ toElementId +"')", transitionTimeSec * 1000); }, /** * Change the z-order of two elements. * newBottomElementId: The element to be moved to the bottom. It is given z-index 2. * newTopElementId: The element to be moved to the top. It is given z-index 1. */ reorderFrames : function(newBottomElementId, newTopElementId) { document.getElementById(newTopElementId).style.zIndex = 2; document.getElementById(newBottomElementId).style.zIndex = 1; } }; }();
Any suggestions for improvement welcome--especially if you know how to prevent the Seam conversation problem I mentioned earlier! -
7. RichFaces & Slideshow
arturfriesen Apr 12, 2011 10:08 AM (in response to rhasselbaum)shouldnt the a4j:poll - tag be inside the h:form-tag?
on my side its only working this way.
-
8. Re: RichFaces & Slideshow
vikymorrone Jun 27, 2011 9:44 AM (in response to cstefkivoila)Hi
Does somebody know how to do a slideshow with a description in each image with RichFaces?.
Thanks.