jQuery in XPages – prettyPhoto – How does it work?

This article is written in support of the original jQuery in XPages #4 – prettyPhoto

Demonstration

To see the prettyPhoto plugin demonstrated in an XPage click on this link

Download

The sample database (as always from now on) is available from the link above and (here)

How does it work?

The plugin “.prettyPhoto()” acts on all elements which match the selector $(“a[rel^=’prettyPhoto’]”)

	$("a[rel^='prettyPhoto']").prettyPhoto();

The $(“a[rel^=’prettyPhoto’]”) selector translates to

  • For all the a tags (a)
  • get all those with the “rel” attribute
  • which starts with the word (^=) ‘prettyPhoto’

The following DOM elements would be selected

	<a href="/xomino/jQinX.nsf/1.jpg" rel="prettyPhoto[pp_gal]" title="Mark"></a>
	<a href="/xomino/jQinX.nsf/demos/xhr_response.html?open&amp;ajax=true" title="Ajax" rel="prettyPhoto[ajax]">Ajax</a>

but the following would not

<a href="1.jpg" rel="marky_prettyPhoto"></a>
<div rel="prettyPhoto" title="You can add caption to pictures.">Hi Mum</div>
  • in the first case prettyPhoto is not the start of the rel attribute,
  • in the second case it is not an anchor (A) tag but a div (div)

Adding prettyPhoto elements to the XPage

We need to add the “rel” attribute to an anchor tag (a link control) in our XPage and there are a number of ways we can achieve this. We can either:

1. Add the images to the database and reference them directly with HTML Directly in the XPage source

	<a title="You can add caption to pictures." href="images/fullscreen/1.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_1.jpg" alt="Red round shape" width="60" height="60" />
 </a>
	<a href="images/fullscreen/2.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_2.jpg" alt="Nice building" width="60" height="60" />
 </a>
	<a href="images/fullscreen/3.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_3.jpg" alt="Fire!" width="60" height="60" />
 </a>
	<a href="images/fullscreen/4.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_4.jpg" alt="Rock climbing" width="60" height="60" />
 </a>
	<a href="images/fullscreen/5.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_5.jpg" alt="Fly kite, fly!" width="60" height="60" />
 </a>

2. Add the images to the database and reference them using link controls in our XPage

	<xp:link escape="true" id="link4" value="images/fullscreen/3.jpg"
		title="Fire!">
		<xp:this.attrs>
			<xp:attr name="rel" value="prettyPhoto[pp_gal]"></xp:attr>
		</xp:this.attrs>
		<xp:image url="images/thumbnails/t_3.jpg" width="60" height="60"
			alt="Fire" id="image4">
		</xp:image>
	</xp:link>

Be aware that custom attributes cannot be added to the XPage Link control prior to 8.5.3

3. Add the images to documents within the database and reference them through a data source in a data table – and that is what we are going to show below…

Database Elements

The demonstration is made up of the following elements

  • XPages
    • The xPrettyPhoto container
  • CustomControls
    • The formPrettyPhoto (where the code lies)
  • JavaScript libraries
    • The jQuery library
    • The prettyPhoto Library
  • Form
    • The images form (data holder)
  • View
    • Images (data source)

The demonstration – Adding the images to a data source in the database

First of all we need to create a form which is going to hold the images

Creating the image upload form
Creating the image upload form

On the form we are going to create an image name, a RTF field to hold the attachment and a description field

Fields on the image form
Fields on the image form

Then we make our XPage and create a data source based on the imageHolder form

XPage data source
XPage data source

Dragging and dropping our data source onto the XPage creates out fields and add a File Upload control (which must be associated with the imageHolder field in the database source)

Fields on our XPage
Fields on our XPage

We add a submit button and reformatting the page a little creates out basic XPage

Basic Image Upload XPage
Basic Image Upload XPage

We need to create a view which shows our image name, description and the attachment name so that we can use them for reference.

Simple view

We will then create a repeat control on the page to display the thumbnail images

Adding a repeat control to the XPages
Adding a repeat control to the XPages

Inside the repeat control we are going to build our Anchor tags and Images.

To create the following HTML

	<a title="You can add caption to pictures." href="images/fullscreen/1.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_1.jpg" alt="Red round shape" width="60" height="60" />
 </a>

We need to need to get the href, title, alt and src tags from each document in the view.

So we add a data source to our repeat control

Assigning a data source to our repeat control
Assigning a data source to our repeat control

We then move to the XPage source to build our gallery HTML.

					<xp:repeat id="repeat1" rows="30"
						value="#{imagesView}" var="imageRepeat">

					<a href="??" rel="prettyPhoto[pp_gal]"
						title="??.">
						<img alt="??" height="60" src="??"
							width="60" style="padding: 5px"></img>
					</a>
					</xp:repeat>

and when we attach this to the repeat control data source (imagesRepeat) the code becomes:

					<xp:repeat id="repeat1" rows="30"
						value="#{imagesView}" var="imageRepeat">

					<a href="#{imageRepeat.imagePath}" rel="prettyPhoto[pp_gal]"
						title="#{imageRepeat.imageName}">
						<img alt="#{imageRepeat.imageDescription}" height="60" src="#{imageRepeat.imagePath}"
							width="60"  style="padding: 5px"></img>
					</a>

					 </xp:repeat>

and we have our gallery.

Image gallery
Image gallery

So now we have a basic functioning XPage which allows for the addition of images into a display gallery. To take it from here to the final product we need to add the prettyPhoto images/css and javascript libraries. The original prettyPhoto files are available here. I added the files to the WebContent by dragging and dropping them from my desktop.

I have added them to the WebContent folder which is accessible through the eclipse package explorer (Window/Show Eclipse Views/Package Explorer)

Adding prettyPhoto files to the WebContent folder int he database
Adding prettyPhoto files to the WebContent folder int he database

We then add the prettyPhoto.css,  jQuery and prettyPhoto javascript libraries to the XPage as a resource (I am referencing them here in the XPage source code)

	<xp:this.resources>
		<xp:script src="js/jquery-1.7.1.min.js" clientSide="true"></xp:script>
		<xp:script src="js/jquery.prettyPhoto.js" clientSide="true"></xp:script>
		<xp:styleSheet href="css/prettyPhoto.css"></xp:styleSheet>
	</xp:this.resources>

The final touch is to prettyPhoto-ify them by adding the activation code to a ScriptBlock at the end of the XPage

	$(document).ready(function(){
		  $("a[rel^='prettyPhoto']").prettyPhoto();
	});

And there we have it

The final prettyPhoto gallery
The final prettyPhoto gallery

There are more examples on the xomino demo website including prettyPhoto galleries containing:

  • iFrame content
  • youTube content
  • and even ajax content

Extra

The prettyPhoto library can also handle youtube/other videos by just making the a href link to a video link the prettyPhoto plugin is smart enough to pick it up and run with it.

Extra Extra

If you look into the prettyPhoto.js file you will see that there are LOTS of configurations which you can play with yourself to change the behavior of the plugin. Because of the following from the website “prettyPhoto is totally free to use, it is licensed under Creative Commons Attribution 2.5. So you can use it in all you projects even commercial ones.” you can make any alterations you like.

	$.fn.prettyPhoto = function(pp_settings) {
		pp_settings = jQuery.extend({
			hook: 'rel', /* the attribute tag to use for prettyPhoto hooks. default: 'rel'. For HTML5, use "data-rel" or similar. */
			animation_speed: 'fast', /* fast/slow/normal */
			ajaxcallback: function() {},
			slideshow: 5000, /* false OR interval time in ms */
			autoplay_slideshow: false, /* true/false */
			opacity: 0.80, /* Value between 0 and 1 */
			show_title: true, /* true/false */
			allow_resize: true, /* Resize the photos bigger than viewport. true/false */
			allow_expand: true, /* Allow the user to expand a resized image. true/false */
			default_width: 500,
			default_height: 344,
			counter_separator_label: '/', /* The separator for the gallery counter 1 "of" 2 */
			theme: 'pp_default', /* light_rounded / dark_rounded / light_square / dark_square / facebook */
			horizontal_padding: 20, /* The padding on each side of the picture */
			hideflash: false, /* Hides all the flash object on a page, set to TRUE if flash appears over prettyPhoto */
			wmode: 'opaque', /* Set the flash wmode attribute */
			autoplay: true, /* Automatically start videos: True/False */
			modal: false, /* If set to true, only the close button will close the window */
			deeplinking: true, /* Allow prettyPhoto to update the url to enable deeplinking. */
			overlay_gallery: true, /* If set to true, a gallery will overlay the fullscreen image on mouse over */
			overlay_gallery_max: 30, /* Maximum number of pictures in the overlay gallery */
			keyboard_shortcuts: true, /* Set to false if you open forms inside prettyPhoto */
			changepicturecallback: function(){}, /* Called everytime an item is shown/changed */
			callback: function(){}, /* Called when prettyPhoto is closed */
			ie6_fallback: true,
			markup: '<div class="pp_pic_holder"> \
						<div class="ppt">&nbsp;</div> \
						<div class="pp_top"> \
							<div class="pp_left"></div> \
							<div class="pp_middle"></div> \
							<div class="pp_right"></div> \
						</div> \
						<div class="pp_content_container"> \
							<div class="pp_left"> \
							<div class="pp_right"> \
								<div class="pp_content"> \
									<div class="pp_loaderIcon"></div> \
									<div class="pp_fade"> \
										<a href="#" class="pp_expand" title="Expand the image">Expand</a> \
										<div class="pp_hoverContainer"> \
											<a class="pp_next" href="#">next</a> \
											<a class="pp_previous" href="#">previous</a> \
										</div> \
										<div id="pp_full_res"></div> \
										<div class="pp_details"> \
											<div class="pp_nav"> \
												<a href="#" class="pp_arrow_previous">Previous</a> \
												<p class="currentTextHolder">0/0</p> \
												<a href="#" class="pp_arrow_next">Next</a> \
											</div> \
											<p class="pp_description"></p> \
											<div class="pp_social">{pp_social}</div> \
											<a class="pp_close" href="#">Close</a> \
										</div> \
									</div> \
								</div> \
							</div> \
							</div> \
						</div> \
						<div class="pp_bottom"> \
							<div class="pp_left"></div> \
							<div class="pp_middle"></div> \
							<div class="pp_right"></div> \
						</div> \
					</div> \
					<div class="pp_overlay"></div>',
			gallery_markup: '<div class="pp_gallery"> \
								<a href="#" class="pp_arrow_previous">Previous</a> \
								<div> \
									<ul> \
										{gallery} \
									</ul> \
								</div> \
								<a href="#" class="pp_arrow_next">Next</a> \
							</div>',
			image_markup: '<img id="fullResImage" src="{path}" />',
			flash_markup: '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{width}" height="{height}"><param name="wmode" value="{wmode}" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{path}" /><embed src="{path}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="{width}" height="{height}" wmode="{wmode}"></embed></object>',
			quicktime_markup: '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" height="{height}" width="{width}"><param name="src" value="{path}"><param name="autoplay" value="{autoplay}"><param name="type" value="video/quicktime"><embed src="{path}" height="{height}" width="{width}" autoplay="{autoplay}" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>',
			iframe_markup: '<iframe src ="{path}" width="{width}" height="{height}" frameborder="no"></iframe>',
			inline_markup: '<div class="pp_inline">{content}</div>',
			custom_markup: '',
			social_tools: '<div class="twitter"><a href="http://twitter.com/share" class="twitter-share-button" data-count="none">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>' /* html or false to disable */
		}, pp_settings);

I hope that these examples are helpful and in general that the jQuery in XPages article series is enlightening and inspiring. There are so many different things we can easily incorporate into our XPages, the possibilities are endless 🙂

Demonstration

To see the prettyPhoto plugin demonstrated in an XPage click on this link

Advertisement

41 thoughts on “jQuery in XPages – prettyPhoto – How does it work?

    • That is very kind of you Roy but I didn’t write the plugin, I just integrated it.

      One day maybe I can create $.xpagify but I have no idea what that would do (yet). I am still waiting for inspiration

      🙂

  1. Ok this is nice and interesting, but when you open a gallery and go through few images notice the url is changing. So when you try and click ‘back’ on the browser, you aren’t going anywhere until you get to the stage before you clicked on the gallery images. Which is pretty much lame. If you have a solution for this will you please share it!?
    Thank you…

    • thanks for the feedback.

      I am not entirely sure though why you would want to use the back button. What is the use case? If you want to use the back button to cycle back through the images then I would try and find another lightbox. There is a back arrow and a close icon. Why do you need to use the back button?

      • You come in to the front page of a website: http://www.example.com. Than you open a document and now the url looks like this http://www.example.com/Dox_page.xsp/2039820985982343. In this document you have a gallery with 5 images, you open the first one and the url looks like this ../823759827394782/#prettyPhoto[pp_gal]/0/
        opening the second image ../#prettyPhoto[pp_gal]/1/
        the third #prettyPhoto[pp_gal]/2/
        and so on…
        So when you’ve read the document and seen all the pictures you want to go back to the frontpage, than you click back. Which goes through all of the url changes you’ve made by cycling in the gallery.
        So if you have 5 images in the gallery and open all of them, than you’ll have to click Back 7 times to actually go back.

        I’m not trying to make you look like an idiot here, I’m just trying to really explain the user experience 🙂

      • I wrote a very detailed comment but when I click Post I was logged in, and the comment got deleted.
        Anyways, the use case scenario goes like this on my app.
        User comes on the frontpage, opens a document that contains a gallery, now when he cycles through the images this is added at the end of the url:
        Opening first image: #prettyPhoto[pp_gal]/0/
        Second #prettyPhoto[pp_gal]/1/
        Third #prettyPhoto[pp_gal]/2/
        and so on…
        Now he closes the gallery and tries to go back to the front page, when he clicks the back button he cycles through all of the url changes made by cycling through the gallery.
        The page doesn’t change until he clears the url out of all the url changes made by the gallery.

        You can try this scenario on your demo app too.

      • The post actually got flagged for approval for some reason – I approved it.

        I get it now and I can repeat it – thanks for the explanation.

        I think you have found a limitation of this plugin. I took a brief google look around and found this alternate lightbox

        http://leandrovieira.com/projects/jquery/lightbox/

        Which does not use the URL and does not have the issues you describe – my only suggestion for right now would be to use another plugin if you are looking for a lightbox. Maybe I will take this under advisement and do a subsequent article on a different lightbox.

        sorry this doesn’t fix your problem but I really appreciate you taking the time to explain and provide the feedback.

        thank you!

      • I’m just trying to find a solution for this, so everyone will benefit from it…
        Also I like the jQuery posts you’ve written about and the demo database is rocking! 😀

      • Now that was a quickie 🙂
        I gave it a shot using FancyBox http://fancybox.net/home
        The implementation is pretty much the same, except all the files are stored in folder called “fancybox” which annoys me a little bit 🙂
        It all works perfect now 🙂

  2. I love this, its very nice. I am able to use your PrettyPhoto integration from your db, but when I copy the components to another db, the lightbox javascript does not load for browsing the photos. I copied the entire /WebContent folder and all I get is a view of the image, with no border, buttons, etc. What am I missing?

    I notice that when I go to the page and try to add the resources via the gui, it says the path is invalid. Oddly, it says the same thing when I look at the PrettyPhoto custom control in your JQinX.nsf. If I try to edit the Resources, I cannot Edit and save the resources, the OK button stays greyed out. I I try to add an identical resource, I get the same issue, the OK button will not activate.

    Any suggestions?

    • John – my first suggestion is to use Firefox and the HTTPFox plugin to examine all the traffic coming to the page. That will tell you where the XPage “thinks” the images should be and should help point you in the right direction.

      That said, this sounds like a css problem. Make sure that css/prettyPhoto.css is in the WebContent and loaded on the page (view source and search for it)

      When the resources are added to the WebContent folder they will not appear as selectable in the XPage GUI resource selector – that control is looking in the script libraries and image libraries within the database and your files are not there. That doesn’t stop you referencing it int he source code panel though. The root of the WebContents folder is equivalent to the root of your database in the browser.

      I use the WebContent folder because it is much easier to manage where all your files are in one place rather than having to go to different areas of the database to get the elements. You can also “see” a folder structure rather than having to rename the files to mimic one.

      Hope that helps 🙂

      If it is still not working for you let me know.

      • OK, I made a new css file, and copied the contents of prettyPhoto.css into it, and added it to the page. I do not see any files fail to load in the FireBug Net console.

        FireBug does show a console error on the page that is almost a copy of the demo.

        JQuery is not defined

        the line is 913 of jquery.PrettyPhoto.js:

        })(jQuery);

        And also

        $ is not defined

        from

        $(document).ready(function(){

        So now I have re-copied the WebContent folder, xPrettyPhoto.xsp, formPretttyPhoto, commonContainer to a new db. I still see the exact same issue, same problem in FireBug, same lack of light box. What else am I missing?

      • Ahhhhh – you need to have jQuery added to the page as well – in the database I add jQuery through the theme. Either copy it from my theme into your own or add the following at the top of your source page – you must have jQuery call above the prettyPhoto call – sorry for the comment edits – rushed and not thinking

        <xp:this.resources>
        <xp:script src=”js/jquery-1.7.1.min.js” clientSide=”true”>
        <xp:script src=”js/jquery.prettyPhoto.js” clientSide=”true”>
        <xp:styleSheet href=”css/prettyPhoto.css”>
        </xp:this.resources>

    • Forgive me if I understood you wrong, but do you add in the source of the xpage?
      You need to copy all the files to the Web Content folder, but you also have to actually tell the js and css files to be loaded.

      Also, the web content is used for this kind of files because it’s a public folder, you might have access issues if you put your files in other folders in the database.

      I hope that helped you…

  3. Well I think I have, but as I said I cannot do so through the GUI, it will not let me click OK.

    Here is what I have at the top of the Custom Control:

    As I said I copied the WebContent folder just as it was in the demo db JQinX.nsf

    • Dwain,

      if you look in the demo database you will be able to see the order of everything. The script block to prettyPhoto everything comes at the end of the page.

      Marky 🙂

      • Not sure if I am doing something wrong or if this is not really useful when trying to display images in a column of a viewPanel, but I kept getting a HTTP 500 error. I did get it working as I wanted by simply making the column a specific width and matching that width in the image resource tag.

  4. Excellent article. I tried it out. All works fine except for the images in the WEB-INF/images folder. I was able to copy/paste the images but – when browsing to the xpage- the server returns an error for all images.
    I tried placing images in another folder below WEB-INF but same problem. Css files and javascript files are loaded correctly.
    Do you know of a setting that blocks loading images from WEB-INF

    Regards

    Wim Stevens

      • You are right. I placed the content below webcontent/WEB-INF. It should have been below webcontent.
        I was not aware that WEB-INF is protected from being accessed via the web
        I will continue may tests

        Thanks

  5. Q: Can the Prettyphotos being displayed (when they pop up), go back to the beginning? Let me explain. I have 9 photos, when the user browses through all 9, when he gets to the last photo ( ” 9 of 9″) there is no repeating back to 1. (photo 1). My client wants to be able to view all over again after they reach the last photos, instead of using the tiny “back” arrow. Thanks in advance for ANY help.

  6. I got this website from my buddy who shared with me on the
    topic of this site and now this time I am browsing this web page
    and reading very informative articles at this place.

    I’m confident all of you here play Crew Fortress 2, or else you wouldn’t be below!
    I also perform TF2, and one particular issue that I couldn’t
    get my head about was accumulating all the items!!
    I’v discovered some players cant even collect most of the items, by no means mind ALL of them!!

    I was dedicated to getting all the objects, but it seemed impossible, so getting an knowledgeable programmer, I got to function!

    Following hrs of hard function I designed, what I say a single of the
    ideal hacks out there! (biased a lot?!) The
    device that I have designed permits you to unlock
    any of the items you would like in TF2!
    I’ts straightforward really…
    I was planning to sell this device and enable some funds start off rolling in, but i know the experience of
    not becoming able to pay for it, or currently being a ‘poor’ guy on TF2, so I have made the decision
    to give this out for totally free to see what individuals believe of
    it! Just read the tutorial below detailing how to get and use the tool!

  7. Hello! I could have sworn I’ve been to this website
    before but after going through a few of the articles I realized it’s new to
    me. Anyhow, I’m certainly pleased I stumbled
    upon it and I’ll be book-marking it and checking back frequently!

  8. whoah this blog is excellent i like reading your posts.
    Stay up the good work! You realize, lots of individuals are looking round for this information,
    you could help them greatly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s