9

When I submit a form using Ajax I want to reload the section of the page that has changed, rather than the whole page, and for this I'm using:

$('#body_container').load(a_href);

where a_href is the location of the source file. After this command has run and #body_container is updated, the new content of the div doesn't seem to be able to access the script files included in the header of the original page, even though it is encompassed by this original page. It only works if I put <script type="text/javascript" src="files.js"></script> at the start of the a_href file.

However, I actually have little divs inside #body_container that I'm also changing, so doing it this way I have files.js being included lots of times at different levels. It seems to be causing conflicts.

Is there a way to include files.js once in the document header, then have all divs, regardless of when their content was created, always recognise that this file is there, waiting to be used?

5
  • 2
    When adding a bounty, you should at least let people who have answered what was wrong with their answer, and/or provide more info. If you have had vague answers, it may be because your question was vague to start with. Commented May 31, 2013 at 0:11
  • can you give a real example? a fiddle maybe? Commented May 31, 2013 at 0:18
  • Hi @OnurYILDIRIM. Here is a fiddle: jsfiddle.net/FcqbD Since I can't include the PHP, please just assume that each file returns an arbitrary and irrelevant template (that also needs to access the javascript (and so contains a <script> to do this) and updates #manage with this. The problem arises if I were to rapidly click between manage 1 and manage 2, it then seems to flicker indefinitely between the two. Commented May 31, 2013 at 0:32
  • You don't need to include the scripts in the loaded files. Pls see my answer. Commented May 31, 2013 at 13:08
  • 1
    @dplanet Both answers here are accurate, is it still not what you are looking for? As i can read your question, i don't see any reason why it should not fit your needs. Commented Jun 1, 2013 at 7:59

3 Answers 3

6
+50

Including the same JS file in every load is a bit much. My suggestion would be to include the file in the main head the first time. Then make use of "delegation" for "dynamic" elements.

For example, say I'm loading a view partial that will have link buttons similar to the initially loaded ones. thus I want them to maintain the same click function. Instead of typical assignment, such as:

$("a.bob").click(function(e) { e.preventDefault(); alert($(this).prop("href")); });

I will use "delegation". jQuery gives us an easy way to do this that will assign the SAME EVENT|METHOD TO ALL ITEMS (PRESENT AND FUTURE[DYNAMIC]) HAVING MATCHING SELECTOR. The way to do this is like:

$(document).on("click", "a.bob", function(e) {
    e.preventDefault();
    alert($(this).prop("href"));
});

The previous will tell ALL a tags having the class bob to not go any where and alert me of their link. This is regardless of when the a tag was added to the DOM.

Example

One thing to keep in mind, .on is new as of jQuery version 1.72 (i think). Prior to that you would use .live or even .delegate instead.


On a Side-Note

Of course, delegation is only going to work with "events". If you need to use JavaScript for something like "layout" movement, then you're best to make a "callback" function to be used with the success of an ajax request. Again, you can place these callback methods in your one head file, but you will need to "call" them as needed in either $.ajax[success or complete].

See success and complete http://api.jquery.com/jQuery.ajax/ to learn more about the basic callbacks of an ajax call. Also, as of version 1.7, you can maintain a list or jQuery Object of callbacks to be fired as needed. To get more information about callback lists, see http://api.jquery.com/category/callbacks-object/

If this is not enough information, please comment and I'll try to make anything you have a question on more clear.

Sign up to request clarification or add additional context in comments.

Comments

1

Is the actual problem that the event handlers in your script don't work in the dynamically loaded content?

If that's the case, change those event handlers to use event delegation. For example:

$("#body_container").on( 'click', '#my-div', function() {...});

Or:

$("#body_container").delegate( '#my-div', 'click', function() {...});

where #my-div is some element in the dynamic content.

Now the event handler will work even though you only load the script once when the page is first loaded.

8 Comments

Hi, this works at the highest level (and is definitely less glitchy), but the script files at the highest level aren't accessible by the children when they load. If I manually include the script file at the top of the child's HTML it works, but again is very glitchy.
What you need to do at this point is describe the problem in very specific terms that JavaScript developers will understand, and give a working (non-working) example where we can see the problem in action. The fiddle you posted doesn't really help; it's not possible to duplicate the problem there, is it? And terminology like "the script files at the highest level aren't accessible by the children when they load" doesn't make sense. I've been doing this for many years and I have no idea what that means. That's why I took a wild guess as to what the problem might be.
Continuing my previous comment... Usually we don't think in terms of child elements "accessing script files". It's the other way around. We write script files that access DOM elements. That's why I and the other responders are just taking wild guesses; we don't know what actual specific problem you are trying to fix.
Uhm ... I already gave these exact answers, and yet you've goten the only questionaire feedback. lol
@MichaelGeary BTW, d$%^ good points in your comments. My answer was a guess as well. Although, I've been where he is (been years ago, but i was there, lol) so I think you and I are spot on for his problem. But I'm not sure he quite understands the solution.
|
1

If I understand the question right, the problem is that you don't initialize the elements in the external files when they are dynamically loaded.

You should use the complete (callback) parameter of the jQuery .load() method; which executes when the corresponding request is complete. Here is the documentation.

Main PHP/HTML file that loads external content:

<html>
<head>
    <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){

            // This is the function to be called from the externally 
            // loaded content.
            function functionToBeCalled() {
                alert("Called function in the main (loader) page!");
            }

            // This is the handler method that executes when the AJAX request
            // is complete. You can initialize the DOM elements in the external
            // content files here.
            function initOnLoad(responseText, textStatus, XMLHttpRequest) {
                // attach event listeners when the load is complete:
                $('#external-div').on('click', '#external-btn', functionToBeCalled);
            }

            $(".manage_link").click(function(e){
                e.preventDefault();
                var a_href = $(this).attr('href');
                // passing the initOnLoad callback as param here:
                $('#ajax_manage').load(a_href, initOnLoad);
            });
        });
    </script>
</head>
<body>
    <ul>
        <li><a class="manage_link" href="ajax_1.php">Manage 1</a></li>
        <li><a class="manage_link" href="ajax_2.php">Manage 2</a></li>
    </ul>
    <div id="ajax_manage"></div>
</body>
</html>

External Content 1 (ajax_1.php):

<div id="external-div">
    External Content <b>1</b><br />
    <button id="external-btn" type="button">Call Function (from ajax 1)</button>
</div>

External Content 2 (ajax_2.php):

<div id="external-div">
    External Content <b>2</b><br />
    <button id="external-btn" type="button">Call Function (from ajax 2)</button>
</div>

3 Comments

This is similar to what I need, but I need everything in the script to be accessible from the external content, not just a single function.
This is just a demonstration. What I show here is; because the content is dynamically loaded, you should bind each element to the proper event/function you want "after" the request/load is complete. The DOM elements must be present when you bind an event to them.
You're already using event delegation in this example, so why not let it do the work for you? Instead of $('#external-div').on('click', '#external-btn', functionToBeCalled); use $('#ajax_manage').on('click', '#external-btn', functionToBeCalled);. Now you only need to do this once when the page is first loaded, instead of having to re-apply this event handler every time you load content.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.