views:

825

answers:

2

I'm trying to create a jQuery plugin, inside I need to do an AJAX call to load an xml.

jQuery.fn.imagetags = function(options) {

  s = jQuery.extend({
     height:null,
     width:null,
     url:false,
     callback:null,
     title:null,
  }, options);

  return this.each(function(){
    obj = $(this);

    //Initialising the placeholder  
    $holder = $('<div />')
    .width(s.width).height(s.height)
    .addClass('jimageholder')
    .css({
        position: 'relative',
    });
    obj.wrap($holder);

    $.ajax({
      type: "GET",
      url: s.url,
      dataType: "xml",
      success:function(data){ initGrids(obj,data,s.callback,s.title); } ,
      error: function(data) { alert("Error loading Grid data."); },
    });

    function initGrids(obj, data,callback,gridtitle){
    if (!data) {
      alert("Error loading Grid data");
    }

    $("gridlist gridset",data).each(function(){
      var gridsetname = $(this).children("setname").text();
      var gridsetcolor = "";
      if ($(this).children("color").text() != "") {
        gridsetcolor = $(this).children("color").text();
      }
      $(this).children("grid").each(function(){     
        var gridcolor = gridsetcolor;
        //This colour will override colour set for the grid set
        if ($(this).children("color").text() != "") {
          gridcolor = $(this).children("color").text();
        }

        //addGrid(gridsetname,id,x,y,height,width)
        addGrid(
            obj,
            gridsetname,
            $(this).children("id").text(),
            $(this).children("x").text(),
            $(this).children("y").text(),
            $(this).children("height").text(),
            $(this).children("width").text(),
            gridcolor,
            gridtitle
        );

      });
    });

    }

    function addGrid(obj,gridsetname,id,x,y,height,width,color,gridtitle){
      //To compensate for the 2px border
      height-=4;
      width-=4;

      $grid = $('<div />')
        .addClass(gridsetname)
        .attr("id",id)
        .addClass('gridtag')
        .imagetagsResetHighlight()
        .css({
        "bottom":y+"px",
        "left":x+"px",
        "height":height+"px",
        "width":width+"px",
         });
       if(gridtitle != null){
         $grid.attr("title",gridtitle);
       }

      if(color != ""){
        $grid.css({
        "border-color":color,
        });
      }
      obj.after($grid);
    }
  });
}

The above plugin I bind with 2 DOM objects and loads two seperate XML files but the callback function is run only on the last DOM object using both loaded XML files.

How can I fix this, so that the callback is applied on the corresponding DOMs. Is the above ajax call is correct?

Sample usage:

<script type="text/javascript">
        $(function(){
            $(".romeo img").imagetags({
              height:500,
              width:497,
              url: "sample-data.xml",
              title: "Testing...",
              callback:function(id){
                console.log(id);
              },
            });
        });
       </script>
       <div class="padding-10 min-item background-color-black">
         <div class="romeo"><img src="images/samplecontent/test_500x497.gif" alt="Image"> </div>
       </div>

<script type="text/javascript">
        $(function(){
            $(".romeo2 img").imagetags({
              height:500,
              width:497,
              url: "sample-data2.xml",
              title: "Testing...",
              callback:function(id){
                console.log(id);
              },
            });
        });
       </script>
       <div class="padding-10 min-item background-color-black">
         <div class="romeo2"><img src="images/samplecontent/test2_500x497.gif" alt="Image"> </div>
       </div>

Here is the sample XML data:

<?xml version="1.0" encoding="utf-8"?>
<gridlist>
    <gridset>
      <setname>gridset4</setname>
      <color>#00FF00</color>
      <grid>
        <color>#FF77FF</color>
        <id>grid2-324</id>
        <x>300</x>
        <y>300</y>
        <height>60</height>
        <width>60</width>
     </grid>
    </gridset>
    <gridset>
      <setname>gridset3</setname>
      <color>#00FF00</color>
      <grid>
        <color>#FF77FF</color>
        <id>grid2-212</id>
        <x>300</x>
        <y>300</y>
        <height>100</height>
        <width>100</width>
     </grid>
     <grid>
        <color>#FF77FF</color>
        <id>grid2-1212</id>
        <x>200</x>
        <y>10</y>
        <height>200</height>
        <width>10</width>
     </grid>
   </gridset>
</gridlist>
A: 

You might be experiencing issues because your calling the ajax load on same url, thus the second call cancels the first call.

If you reading in the same url for each div, why don't you call the ajax once then loop the elements when it returns.

jQuery.fn.imagetags = function(options) {

  s = jQuery.extend({
     height:null,
     width:null,
     url:false,
     callback:null,
     title:null,
  }, options);

  var elems = $(this);

  $.ajax({
      type: "GET",
      url: s.url,
      dataType: "xml",
      success:function(data){ 
        elems.each(function() {     
          obj = $(this);

          //Initialising the placeholder  
          $holder = $('&lt;div /&gt;')
          .width(s.width).height(s.height)
          .addClass('jimageholder')
          .css({
              position: 'relative',
          });
          obj.wrap($holder); 
          initGrids(obj,data,s.callback,s.title); 
        });
      },
      error: function(data) { alert("Error loading Grid data."); }
    });

  return $(this);
}

Basically, what your doing here is calling the ajax function then instantly return the set. then, when the ajax callback gets fired, your looping the elements and appending the data.

bendewey
I tried using variable. Result is the same :(
Saneef
i'm calling the AJAX on 2 different urls.
Saneef
from the code i'm seeing it looks like your calling ajax on the same s.url for each object.
bendewey
I'm able the data from 2 different xmls using above code. So I think calling with same url is not case here.
Saneef
Can you provide a sample of your usage code?
bendewey
I have provied the sample usage also.
Saneef
this usage still appears to only call one url... Can you provide a usage that calls two urls?
bendewey
Similar call only the class name changes. I have updated the sample usage for the second call also.
Saneef
I'm trying to test it, but I'm getting parseerrors on my XML. I'm just guessing your schema, Hate to do this to you but, can you also supply your XML?
bendewey
I have updated the sample XML also.
Saneef
A: 

this might be a scoping issue. you should use the 'var' statement when declaring variables inside functions. otherwise the variables go into the global scope.

var s = jQuery.extend({
     height:null,
     width:null,
     url:false,
     callback:null,
     title:null,
  }, options);

elems.each(function() {     
      var obj = $(this);

      ....
}

since the variables are living in the global scope, they get overwritten by each iteration through the loop, and ultimately resulting in the the last DOM element.

jonnyheadphones