views:

368

answers:

4

I want to solve duplicate objects in dynamic loading content. Please look at the following source code for easier understand.

Base Page HTML With 1 Dynamic Loading Content

<body>
     <div id="general-div"></div>>
     <div id="div1"></div>
     <div id="placeholder1">
          Dynamic Content will be placed inside this.

          <div class="inner-div"></div>
          <div class="div1"></div>
     </div>
</body>

For script in header of this page, it's very easy to select "general-div" object like the following code.

 $('#general-div')

It's quite easy for select "inner-div" object inside placeholder1. So I can select by using the below code.

 $('.inner-div')

The above code could works perfectly. However, I can't use the above code when there is more than 1 duplicated object in the same document like the following HTML. The above code will return 2 objects that don’t what I want.

Base Page HTML - After load another dynamic loading content

<body>
     <div id="general-div"></div>>
     <div id="div1"></div>
     <div id="placeholder1">
          Dynamic Content will be placed inside this.

          <div class="inner-div"></div>
          <div class="div1"></div>
     </div>
     <div id="placeholder2">
          Dynamic Content will be placed inside this.

          <div class="inner-div"></div>
          <div class="div1"></div>
     </div>
</body>

Possible Solution 1

I must create specified jQuery object foreach script in dynamic loading content like the following code.

 // Deep copy for jQuery object.
 var specfiedjQueryObj = $.extend(true, {}, jQuery);

 // modify find function in jQuery object.
 specfiedjQueryObj.fn.find = function(selector)
 {
      // by adding placeholder selector before eval result.
      return new specfiedjQueryObj.fn.old_find('#placeholder1 ' + selector);
 };

 // So, I can select any object in dynamic loading content.
 (function($)
 {
      // This result must be 1 object.
      $('.div1'); 
 })(temp);

Even though, this solution should be work great. But I found that jQuery is a very complex object. I found a lot of errors when I try to use it.

Do you have any idea for solving this problem?

PS.PlaceHolder Id is not a fixed Id. So, It's impossible to fixed it in selector rule. Moreover, I do not know exactly amount of element and position (first, last or middle) of it in document. Because of dynamic loading content will be displayed on a lot of page.

+1  A: 

How about $('div[id^=placeholder]:last') ?

Selectors / attrubuteStartsWith

Alexander Gyoshev
I do not know what exactly number of it. Therefore, it is impossible to specify number of order in every selector in dynamic loading script. Moreover, it makes my script much complicate.
Soul_Master
can you elaborate which exactly elements do you want to get? how are they appended? the :last will get always the last of the elements - it does not require the index of the element.
Alexander Gyoshev
I do not know exactly amount of element and position (first, last or middle) of it in document. Because of dynamic loading content will be displayed on a lot of page.
Soul_Master
+1  A: 

You could simply use $('.innerdiv:first') to get the first one or $('.inner-div:last') to get the last one. Or if you have multiples and want to select a particular one $('.inner-div:nth(x)') where x is the index of the item.

Jose Basilio
I do not know what exactly number of it. Therefore, it is impossible to specify number of order in every selector in dynamic loading script. Moreover, it makes my script much complicate.
Soul_Master
Please explain what is your final objective or expected solution. Do you want hide all the duplicated elements and display only one. Do you want to change some css attributes. What is your criteria to determine which one should be selected?
Jose Basilio
Please see my possible solution 1. It's very generic solution for this question. It does not require position of dynamic loading content. Do you have any idea like this?
Soul_Master
A: 

The following function will process data from partial loading view page and add specified context for each jQuery selector in script. This answer works well. However, it does not support external script file.

function renderPartialView(control, data)
{
    // For detecting all script tag in loaded data.
    var reExtractScript = /(<script type="text\/javascript">)([\s\S]+?)(<\/script>)/gi;

    // For detecting all "$" sign (must be jQuery object) in loaded data.
    var reFindDollarSign = /\$\(([\S]+?)\)/gi;

    // Find all matched string in loaded data.
    var result = reExtractScript.exec(data);
    var allScript = '';

    if (result)
    {
        for (i = 0; i < result.length; i += 4)
        {   
            // Remove current script from loaded script.        
            data = data.replace(result[i], '');

            // Replace all "$" function by adding context parameter that is control.
            allScript += result[i+2].replace(reFindDollarSign, '$($1, "' + control + '")');
        }
    }

    // Load non-script html to control.
    $(control).html(data);

    // Evaluate all script that is found in loaded data.
    eval(allScript);
}

// This script will partially download view page from server in the same domain
$(function()
{
    $.get(getUrl('~/Profile/Section/ViewEducation'), null, function(data)
    {
        // When partial loading is complete, all loaded data will be sent to “renderPartialView” function
        renderPartialView('#education-view', data);
    });
});
Soul_Master
A: 

Okay, so let's talk about your example HTML. I added a class of placeholder, and added a dash in the id for convenience later.

<div id="placeholder-1" class="placeholder">
     Dynamic Content will be placed inside this.

     <div class="inner-div">baz</div>
     <div class="div1">zip</div>
     <a href="#" class="action">action</a>
</div>
<div id="placeholder-2" class="placeholder">
     Dynamic Content will be placed inside this.

     <div class="inner-div">foo</div>
     <div class="div1">bar</div>
     <a href="#" class="action">action</a>
</div>

Now I can bind an event to each of these links with $('.placeholder a.action').bind('click', ... ); If I want this event to all future chunks of html like this on the page, I do $('.placeholder a.action').live('click', ... );

This code will attach an event to those links and the var statements can capture the id, or the inner text of the <div>s. In this way you don't have colliding id attribute values, but you can traverse actions inside divs with class placeholder.

$('.placeholder a.action').live('click', function(){
    // get the id
    var id = $(this).parents('div.placeholder').attr('id').split('-')[1];
    // get the text inside the div with class inner-div
    var inner_div = $(this).parents('div.placeholder').children('.inner-div').text();
    // get the text inside the div with class div1
    var div1 = $(this).parents('div.placeholder').children('.div1').text();
    return false;
});
artlung
I think your answer should work with my example. However, for your script is very complicate. I think your script must be placed in parent document only that I do not like it. Because of I cannot reuse it in another page. Please look at my answer. Do you have any idea or any suggestion?
Soul_Master
For clarify my question, you can imagine dynamic loading page as some complex control like calendar or Grid View. You can have more than one control on the same page. Moreover, all of this control will be loaded and showed data depend on user action like click. Therefore, your idea should not be the best way to solve my question that focus on the following three points like easy to use, easy to reuse, easy to modify. Thanks for suggest your answer.
Soul_Master
I don't understand your objection to my script.
artlung
ASP.NET MVC causes the original problem when I try to load two partial view pages in the same web page via AJAX. I have script in each partial view page. Therefore, jQuery selector will work incorrectly. In specified ID of object case, jQuery will return the first matched object. In the other hand, without specified ID of object, jQuery will return all matched object from both duplicated partial view page. As I comment before, your answer could work fine for my example. Nevertheless, your script is designed to be contained in parent page not in partial view page as I except.
Soul_Master
I've added asp.net related tags to your question so perhaps an asp.net maven will be able to help. But it sounds like what you want is to NOT have the code which would handle these partial views be included by default. Maybe what you need is dependency injection and when these partial views are loaded to call whatever JS is necessary to process them with `$.getScript`.
artlung
I do not agree with for adding asp.net related tag to my question. This problem may happen in when someone use other language like PHP or ruby. Thanks for suggest me to use $.getScript function. This function works like require script function (that will be added into jQuery 1.4 features).
Soul_Master