views:

277

answers:

4

I'm building an application that is an image gallery but with lots of images (it's for browsing archives of documents); basically the application does this:

  1. display an image
  2. display "previous" and "next" links left and right of the first image

The previous and next links are retrieved from an XML file that lists all images in sequence; there are around 1000-2000 images in each set (one XML file per set). In order to avoid having to look for preceding and following sibling elements, I included the names of each previous and next images as attributes of each image.

So the XML file is basically:

<list>
   ...
   <image previous="ww.jpg" next="yy.jpg">xx.jpg</image>
   <image previous="xx.jpg" next="zz.jpg">yy.jpg</image>
   <image previous="yy.jpg" next="aa.jpg">zz.jpg</image>
   ...
   </list>

What I'm doing is this:

function display(img) {
  var lookingfor = 'image:contains('+img+')';
  $.ajax({
    type: "GET",
    url: "pns.xml",
    dataType: "xml",
    success: function(xml) {
      $(xml).find(lookingfor).each(function(){
        // display the actual image and the links from @previous and @next attributes
        });
      }
    });
  }

$(document).ready(function(){ 
  var image = $.query.get('img');
  display(image);
  });

The first time the page loads, the script:

  1. gets the name of the image to be displayed from the url parameter 'img'
  2. loads the xml file containing the name of all images
  3. gets previous and next image names from this same file
  4. displays the image
  5. displays links to the previous and next images

So far so good. My problem is with the other images.

The link to the previous or next image is:

 display('image_id');

I was hoping that without reloading the page and simply calling again the 'display' function I would not have to get the XML file again, and not have to parse it again. However, it seems to not be the case: the XML file is apparently loaded again with every new call of the 'display' function.

A significant delay the first time the page is loaded is acceptable; but the same delay for each image seems sluggish and very unpleasant.

I have full control over the application; if there is a more efficient solution than an XML file to hold the parameters that would be fine. However the application has to work offline, so I cannot query a server to get the names of preceding / following images.

Also, using the :contains() selector is probably not the fastest approach: what would be better?

Edit: using XML and loading it externally was clearly far from optimal; a much better and simpler approach is to have a big object containing one array per image and to load this object just once (when the script is first loaded). Another approach would be to use some local storage / SQL facility; I may try this with Google Gears which provide such tools.

+1  A: 

Perhaps Ajax the image XML into a global JS variable the first time and then just query the JS variable on subsequent calls. So:

<script type="text/javascript">
  var imgXML = null;

  // document ready
  $(function() { 
    $.ajax({
      type: "GET",
      url: "pns.xml",
      dataType: "xml",
      success: function(xml) {
        imgXML = xml;
        var image = $.query.get('img');
        display(image);
      }
    });
  }      

  // subsequent display goes straight to the XML data in memory
  function display(img) {
    if(imgXML != null) {
      var lookingfor = 'image:contains('+img+')';
      $(imgXML).find(lookingfor).each(function(){
        // display image and links
      }
    }   
  }
</script>

I'm sure there's other optimizations to be made but this should solve your re-loading the XML problem.

patrickmcgraw
That did work, thanks.I added 'async:false' to the ajax call so that the first call waits for the xml to be ready before doing any display stuff; if not, imgXML is always null when display() is called the first time (because the xml is not finished loading) and so no images and no links are ever displayed...
A: 

How about setting cache to true?

$.ajaxSetup({
  cache: true
});
Mark Ursino
Isn't it true by defualt? http://docs.jquery.com/Ajax/jQuery.ajax#optionsI think the problem is that he is going through xml file on each request.
TheVillageIdiot
Yes, it's true by default and it doesn't seem to do anything anyway.
A: 

One way is to fetch xml file before getting first image separately (from image fetching function) and read all image names in an array (though it will be a big array).

//pseduo code
<script type="text/javascript">
    var currentImage=-1;
    var imageName=new Array();

    loadXML(){
        GETXML;
        var i=0;
        for(image in images_in_xml){
            imageName.push(image);
            if(image == CURRENT_IMAGE_NAME)
               currentImage = i;
            i++;
        }            
    }
</script>

Now you have index of current image and you can easily get name of next and previous image by simply using currentImage-1 and currentImage+1

TheVillageIdiot
A: 

Looks like you're making a request for the full xml each time, which is in many cases not the best idea. Depending on your situation you might want to use an optimized database, a smaller/optimised dynamic xml solution or start looking for an expert...

From the brief description you give, I would suggest a jquery lightbox plugin - but of course you might have a reason not to use that option.

By the way, I noticed you wrote "A significant delay the first time the page is loaded is acceptable" and am trying to understand the logic... The first time a visitor comes to your site is the first impression, and everybody knows that first impressions last (especially online, where 3 seconds feels like an eternity)'

Emil Hunefalk
From what I understand ("the lightbox plugin is used to overlay images on the current page"), I don't think it has much to do with my problem?
About the delay: the "site" is a special offline application targeted at professionals who need access to the documents; they can handle a small warmup delay. However if the delay is repeated for every page it's not the same thing of course.