Any external JavaScript or CSS file, whether added manually or
dynamically, can be removed from the page. The end result may not be fully
what you had in mind, however. I'll talk about this a little later.
Dynamically removing an external JavaScript or CSS file
To remove an external JavaScript or CSS file from a page, the key is to
hunt them down first by traversing the DOM, then call DOM's
removeChild()
method to do the hit job. A generic approach is to
identify an external file to remove based on its file name, though there are
certainly other approaches, such as by CSS class name. With that in mind, the
below function removes any external JavaScript or CSS file based on the file
name entered:
function removejscssfile(filename, filetype){
var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none"
//determine element type to create nodelist from
var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none"
//determine corresponding attribute to test for
var allsuspects=document.getElementsByTagName(targetelement)
for (var i=allsuspects.length; i>=0; i--){
//search backwards within nodelist for matching elements to remove
if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null
&& allsuspects[i].getAttribute(targetattr).indexOf(filename)!=-1)
allsuspects[i].parentNode.removeChild(allsuspects[i])
//remove element by calling parentNode.removeChild()
}
}
removejscssfile("somescript.js", "js")
//remove all occurences of "somescript.js" on page
removejscssfile("somestyle.css", "css")
//remove all occurences "somestyle.css" on page
The function starts out by creating a collection out of either all
"
SCRIPT
" or "
LINK
" elements on the page depending
on the desired file type to remove.
The corresponding attribute to look at also changes accordingly ("
src
" or
"
href
" attribute). Then, the function sets out to loop through the gathered elements
backwards to see if any of them match the name of the file that should be
removed. There's a reason for the reversed direction- if/whenever an
identified element is deleted, the collection collapses by one element each
time, and to continue to cycle through the new collection correctly,
reversing the direction does the trick (it may encounter undefined
elements, hence the first check for
allsuspects[i]
in the
if
statement). Now, to delete the identified element, the DOM method
parentNode.removeChild()
is called on it.
So what actually happens when you remove an external JavaScript or CSS
file? Perhaps not entirely what you would expect actually. In the case of
JavaScript, while the element is removed from the document tree, any code
loaded as part of the external JavaScript file remains in the browser's
memory. That is to say, you can still access variables, functions etc that
were added when the external file first loaded (at least in IE7 and
Firefox 2.x). If you're looking to reclaim browser memory by removing an
external JavaScript, don't rely on this operation to do all your work. With external CSS files, when you remove a file, the
document does reflow to take into account the removed CSS rules, but unfortunately,
not in IE7 (Firefox 2.x and Opera 9 do).
Demo:
|
"myscript.js" source:var petname="Spotty"
alert("Pet Name: " + petname)
|
"mystyle.css" source:#demotable td{
background-color: lightyellow;
}
#demotable b{
color: blue;
}
|
Dynamically replacing an external JavaScript or CSS file
Replacing an external JavaScript or CSS file isn't much different than
removing one as far as the process goes. Instead of calling
parentNode.removeChild()
, you'll be using
parentNode.replaceChild()
to do the bidding instead:
function createjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
return fileref
}
function replacejscssfile(oldfilename, newfilename, filetype){
var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none"
//determine element type to create nodelist using
var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none"
//determine corresponding attribute to test for
var allsuspects=document.getElementsByTagName(targetelement)
for (var i=allsuspects.length; i>=0; i--){
//search backwards within nodelist for matching elements to remove
if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null
&& allsuspects[i].getAttribute(targetattr).indexOf(oldfilename)!=-1)
{
var newelement=createjscssfile(newfilename, filetype)
allsuspects[i].parentNode.replaceChild(newelement, allsuspects[i])
}
}
}
replacejscssfile("oldscript.js", "newscript.js", "js")
//Replace all occurences of "oldscript.js" with "newscript.js"
replacejscssfile("oldstyle.css", "newstyle", "css")
//Replace all occurences "oldstyle.css" with "newstyle.css"
Notice the helper function
createjscssfile()
, which is
essentially just a duplicate of
loadjscssfile()
as seen on the previous
page, but modified to return the newly created element instead of actually
adding it to the page. It comes in handy when
parentNode.replaceChild()
is called in
replacejscssfile()
to replace the old element with the new. Some good news here- when you
replace one external CSS file with another, all browsers, including IE7,
will reflow the document automatically to take into account the new file's
CSS rules.
Demo:
|
"oldscript.js" source:var petname="Spotty"
alert("Pet Name: " + petname)
"newscript.js" source:
var petname="Beauty"
alert("Pet Name: " + petname)
|
"oldstyle.css" source:#demotable2 td{
background-color: lightyellow;
}
#demotable2 b{
color: blue;
}
"newstyle.css" source:
#demotable2 td{
background-color: lightblue;
}
#demotable2 b{
color: red;
}
|
Conclusion
So when is all this useful? Well, in today's world of Ajax and ever
larger web applications, being able to load accompanying JavaScript/ CSS
files asynchronously and on demand is not only handy, but in some cases,
necessary. Have fun finding out what they are, or implementing the
technique. :)
No comments :
Post a Comment