When you are working in jQuery with generated HTML fragments that are
returned from AJAX, It is interesting to note these cases..
1) Creating New elements on The Fly
When passing HTML string to jQuery( html ) it will look for HTML tags (ex: <tag ... >) somewhere within the string. Then, it attempts to create new DOM elements as described by the HTML string.But, be ware of that: in complex HTML strings, some browsers may not generate a DOM that replicates the HTML you provided especially for not well-formed snippets.
Solution, is really simple. First, create a new container div and set its inner HTML with the snippet string then append it to the target element.
$(document).ready(function(){
// not-well-formed HTML string
var str = '1<br>2<br>3';
// Bad: creating new elements
$(str).appendTo('#output1');
// Good: using inner HTML
$('<div/>').html(str).appendTo('#output2');
});
2) Having Images or Iframes in fragments
When you intend to filter out some parts of the HTML snippet before appending it to the DOM, you should note that the web browser will immediately request any images or iframes or scripts it finds in that snippet and certainly slowing down your page loading.* you can inspect what resources are loaded on web pages using Firebug for FireFox or built-in developer tools in Chrome.
Solution, is to rename the [src] attribute of the img or iframe tags as [tempsrc] using regular-expressions to prevent browser from loading them. Then, when you are finished with filtering out unneeded parts, you can revert it back as it was..
To revert [src] attributes back, you have 2 options:
- Using regular expressions again.
- After appending the fragment string to a container, you can loop each image/iframe tag using jQuery selectors to revert its [src] attribute as is.
$(document).ready(function(){
// not-well-formed HTML string
var str = '1<br>2<br>3<br>'+
'<img src
= [url]>';
// replace src attributes to tempsrc
str =
str.replace( /\ssrc\s*=/gi , ' tempsrc=' );
// some manipulations here..
// **************************** Option 1
// revert src attributes as is with regex
str = str.replace( /\stempsrc=/gi , ' src=' );
// append fragment
$('<div/>').html(str).appendTo('#output1');
// **************************** Option 2
// revert src with jquery after appending the fragment
var div = $('<div/>').html(str).appendTo('#output2');
// loop any image, iframe tags to revert src
$('img,iframe' , div).each(function(){
var tag = $(this);
tag.attr('src' , tag.attr('tempsrc'));
});
});
Nice article...very easy to understand..Keep up the good work.
In your second example, the word boundary special character '\b' is a zero-width match, so there's no need to capture it and prepend it to your replacement string.
@Rod,
Thanks alot for heads-up, I corrected the code now.
Officially, You are the first one who had actually read the post :)
Be aware that if the snippet ever legitimately contains the string " tempsrc=", such as a snippet containing the body of this article itself, then you're in an unhappy place. Never say never.
To ensure we're only operating on tag attributes named src/tempsrc, I'd rewrite the regexes thus:
str = str.replace( /(<\w+[^>]*?)(\ssrc\s*=)/gi , '$1 tempsrc=' );
...and...
str = str.replace( /(<\w+[^>]*?)(\stempsrc=)/gi , '$1 src=' );
@Spacebat,
That would not work with working HTML like this
<img alt="a > b" src="">
I guess I could change attribute ' tempsrc=' to ' one_in_a_million_src=' to have a chance of 1 in a million of it occurring :)
Surely, Regular expressions are not for irregular languages like HTML in all situations. But, it should do just fine in that case..
Interesting! My approach is different and unique.
I do set for jQuery to create elements dramatically with its own id but these string are in a .js file as var; and is apart from the document. When calling back these strings via ajax, I then set the DIV to nest the new content. When it's time to load 'new content', it'll have go to the nesting strings(that is already called back).
Since I made new content as dependent on the nesting string. Remove() if I want to remove nesting string.
With this approach, I saw that it does prevent jQuery to preload everything, and it'd fire specifically at my click.
But with this discussion above, I saw that it'll be good idea if I made the practice by using .text('') to the nesting DIV right before remove() so that way any var would be replaced if they are being cached as flushed.