Francesca
Francesca

Reputation: 28148

Reload AJAX from an inline link already within an AJAX page

http://fh80.student.eda.kent.ac.uk/fyp/ Live example

If you see this page, click sports/venues/athletes etc it lets you browse around but it is all called in via AJAX.

This works fine but I'm having problems with inline links. For example:

Go to sports

Go to athletics

Go to "Hampden Park" link in red

This link doesn't reload within the AJAX window, it loads it in a new window...

This is the code that should set anything with the class ajaxLink as possible to load the AJAX page into the div #grid (same as the way it's done for all the other pages)

var newLink = $('.ajaxLink');
            newLink.click(function (e) {
                $.ajax({
                    url: newLink.attr('href'),
                    type: 'POST',
                    success: function (data) {
                        $('#grid').remove();
                        successHandler(data)
                    }
                });
                e.preventDefault();
            });

Here is the code for the AJAX I am using (it's long):

//on document ready
$(function () {

    var ajaxElement = $('#browserMenu a, .ajaxLink');
    ajaxElement.on('click', function (e) {
        var src = $(this).attr('href');
        console.log(src);
        //this element clicked
        var thisEl = $(this);
        var runAJAX = (src && src != '#') ? true : false;
        if (runAJAX) {
            var targetElement = $('#grid');
            var parentElement = $('#ajaxParent');
            if (src === 'index.html') {
                $('#content').load('index.html #inner-content', function () {
                    $('.selected-menu').each(function () {
                        $(this).removeClass('selected-menu');
                    });
                    thisEl.addClass('selected-menu');
                    $('#jsCode code pre').load('js/nocomments.js');
                });
            } else {
                $.ajax({
                    url: src,
                    dataType: 'html',
                    statusCode: {
                        404: function () {

                            console.log(src + ' - not found');
                        }
                    },
                    cache: false,
                    error: function (jqXHR, textStatus, errorThrown) {

                        console.log(errorThrown);
                    },
                    success: successHandler
                });
            }

            e.preventDefault();
        }

        function successHandler(data) {
            targetElement.remove();
            //remove any selected classed
            $('.selected-menu').each(function () {
                $(this).removeClass('selected-menu');
            });
            thisEl.addClass('selected-menu');
            var newContent = $('<div id="grid" />');
            newContent
                .html(data) //grab the HTML from AJAX and place it in to <div id="content"> </div>                  
            .css("opacity", "0"); //hide the div until were ready to animate it in.
            parentElement.append(newContent);
            newContent.animate({
                opacity: 1
            }, 500);
            var newLink = $('.ajaxLink');
            newLink.click(function (e) {
                $.ajax({
                    url: newLink.attr('href'),
                    type: 'POST',
                    success: function (data) {
                        $('#grid').remove();
                        successHandler(data)
                    }
                });
                e.preventDefault();
            });
        }

    });

    $('#jsCode code pre').load('js/nocomments.js');
});

Upvotes: 4

Views: 1393

Answers (4)

doydoy44
doydoy44

Reputation: 5772

In response to my comment and since there was no validation , I propose another way to recover your data avoiding ajax calls that can be resource intensive .

The principle is to call once the static data and concerver .

For example, you have your grid div .

The first time you click on "Sports", verify that there is no div grid-sport, you create a div grid-sport in the grid with a div class grid-class , you made ​​the call to ajax to fill the grid-sports div.

Clicking "Athletics" , you hide the class grid-class, verify that there is no div grid-athletics, you create a div grid-athletics with grid-class (after the grid-sports div in the grid div), and you made ​​the call to ajax to fill the grid-athletics.

And so on for all the links ...

If you click again on "Athletics" for example, you hide the div that the grid-class class and there, verify that there is div grid-athletics, if your content is static (for the user session), show you the tag grid-athletics, otherwise, if the content should be dynamic you delete its contents and remade an ajax call.

With this method, you call once your static content.

I hope I have understood (translated by Google:))

Upvotes: 0

Jeffery To
Jeffery To

Reputation: 11936

Why your code doesn't work

Let's step through what happens from when the user loads the page to when the user clicks on the "Hampden Park" link:

  1. User loads the page:

    The document ready event handler is called. It adds a click event handler to $('#browserMenu a, .ajaxLink'), which matches the "Sports" link inside <div id="browserMenu">. There are no elements with the "ajaxLink" class in the document at this point, so only the four menu links get this click event handler.

  2. User clicks on the "Sports" menu link:

    The click event handler from 1. is called. It loads content from the Sports page using Ajax, then passes that data to successHandler(). successHandler() removes the old <div id="grid"> and adds a new <div id="grid"> with the new content, which is a jQuery UI Tabs widget and content for the first tab (content for the other tabs are loaded using Ajax).

    At this point, successHandler() tries to add a click event handler to $('.ajaxLink'), but there are still no elements with the "ajaxLink" class in the document, so no click handlers are added.

  3. User clicks on the "Athletics" tab:

    The jQuery UI Tabs widget loads the content for the Athletics page with Ajax and displays it.

  4. User clicks on the "Hampden Park" link:

    This link has the "ajaxLink" class, but as noted in 2., it has no click event handler, so the browser opens this link normally.


A better approach

For cases where content is loaded dynamically, it is easier to use event delegation rather than trying to bind new event handlers every time the content changes.

Basically, every* event "bubbles up" from the original element where the event occurred, to its parent element, its parent's parent, all the way up to the document element. You can attach handlers to a parent element to respond to events that originate from its children.

From jQuery's documentation, you will notice that on() takes an optional selector parameter. For example, with this:

$('body').on('click', handler);

handler() will be called whenever the user clicks on the page, no matter if the user clicked on a link, an image or a blank space. When a selector is present:

$('body').on('click', 'a', handler);

handler() will only be called when the user clicks on a link (inside the body element). Any click events from elements that do not match the selector will be ignored (including any clicks that occur directly on the body element).

*As with many other cases, jQuery works around any browser inconsistencies so that event delegation works for all events.


In your case

Assuming you want one event handler to handle clicks to both menu links and content links, you can attach a click event handler to either <div class="slideWrapper"> or <body>, as they are parents / ancestors of both <div id="browserMenu"> and <div id="grid">:

$('body').on('click', '#browserMenu a, .ajaxLink', function (e) {
    // load content using Ajax
    // on success, replace old content with new
});

Upvotes: 8

nijel
nijel

Reputation: 61

It doesn't work because you need to attach the function to an element which is not loaded by ajax.

$('#grid').on('click', '.ajaxlink', function() {
    // do stuff
});

Since #grid is not modified by the ajax call, the event handler will stay in place.

Upvotes: 2

Mike Thomsen
Mike Thomsen

Reputation: 37506

You need to use the on function of jQuery to do this. Start here. click will not work with dynamic content, but the newish event API will catch dynamic content generated from an AJAX response and inserted into the DOM. This is a google example from that page:

$( "#dataTable tbody" ).on( "click", "tr", function() {
    alert( $( this ).text() );
});

What that does is catches all incoming tr elements into dataTable's tbody and give them a click event.

Upvotes: 2

Related Questions