tl;dr summary: jQuery's load()
method called like:
$('#foo').load('similar.html #foo')
results in DOM structure of:
<div id="foo">
<div id="foo">…</div>
</div>
What's the Right way to swap out a portion of a page with the equivalent part in a similar page using jQuery that does not double up the wrapper?
I want to create a site that:
I don't want to use frames due to #3, and also because I want the persistent content to overlap the dynamic content (note the persistent search results in pink overlaying the content).
So, every page in the site will have structure similar to the following abbreviated shell:
<html><head><title>NAME</title>…</head><body>
<div id="chrome">…</div>
<div id="content">…</div>
</body></html>
Using jQuery I can intercept the navigation and search links and use AJAX to load the page and replace just the content. And I can use history.pushState()
to make the address bar update in a navigable and bookmarkable way:
$('#nav a').click(function(e){
var url = this.href;
$('#content').load(url+" #content",function(html){
var title = /<title>(.+?)<\/title>/i.exec(html)[1];
history.pushState({},title,url);
$('title').html(title);
});
e.preventDefault();
});
Additional code is needed to properly handle moving forward and backward through the history; these are irrelevant to the question.
However, the above code results in the DOM having:
<div id="content">
<div id="content">contents from other page</div>
</div>
Is there a better way to prevent this illegal doubling of id
other than changing all my markup to…
<div id="content-wrap"><div id="content">…</div></div>
and the JS to…
$('#content-wrap').load(url+" #content",…);
Instead of using .load()
which automatically loads the server response into the selected element (using .html()
), you can use a $.get()
request and filter the server response to only include the innerHTML
of the response:
$.get('similar.html', function (serverResponse) {
var filter = $(serverResponse).filter('#foo').html();
$('#foo').html(filter);
});
Here is a demo: http://jsfiddle.net/QRBaw/
You can also use .children().parent()
to select the #foo
element rather than using .filter()
(in-case you want to do this dynamically).
UN-TESTED
Have you tried to change the selector in your .load()
function call to select the children of the #foo
element?
$('#foo').load('similar.html #foo>*');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With