BookMarklets are short pieces of javascript that run code on the current web page. Unfortunately many of them are not compatible with pages that use frames. Normally this is to keep the length of the script down (Internet Explorer in particular can have some very restrictive limits). But since this is a page for Opera users, and since Opera has the longest limit of any browser (AFAIK), this is an an attempt to impart my wisdom on the world.
BookMarklets will remain compatible with pages that don't use frames.
Pretty much all the code here has been figured out from looking at other people's BookMarklets (see that page for more links)
It's quite possible there are some things I do that I don't fully understand... And which may cause problems later, feel free to correct me.
For this simple example I will use the following Bookmarklet that 'fixes' any marquees on a page
javascript:var m=document.getElementsByTagName("marquee");for(var i=0;i<m.length;i++) m[i].style.display="table-row";return false;
Now that you have your script, it's time to format it... Trust me, this will help lots with the longer scripts.
I have also added comments, mostly for tracking benefit, they will be removed again before the end.
javascript:
var m=document.getElementsByTagName("marquee"); // make m an array of all marquees
for(var i=0;i<m.length;i++) // loop through the marquees
m[i].style.display="table-row"; // edit the style so that opera kills the animation
return false; // standard bookmarklet closer
As a bonus I will enclose the code in an anonymous function... this gives the benefit of allowing any variable name to be used without interfering with page variables. You can also drop the "return false;" line.
javascript:(
function(){
var m=document.getElementsByTagName("marquee");
for(var i=0;i<m.length;i++)
m[i].style.display="table-row";
})();
You shouldn't need to read this bit after a while, but here is the fully commented template code that your existing script will be wedged into.
javascript:(
function(){ // Note again, anonymous function
// *************************************
// Insert the main code of the script here in a function
// The function name can be whatever you choose
// The script must also accept at least one parameter
// This will represent a document object
// *************************************
// declare any script wide variables
var f=window.frames; // get the frames
if(f.length==0){ // If the page has no frames
// run the function on the "document" object
}
else{ // page uses frames
// You may still want to run the code on the top level page here
// I.E. the page with <Frame set> etc....
for(var i=0;i<f.length;i++){ //loop through each frame
// run the function on the "document" object of the current frame
}
}
// place here any code to be done
// If, for example the script was counting links.. here would be the place to put the alert()
}
)()
If we look at the last version of the current code.
javascript:(
function(){
var m=document.getElementsByTagName("marquee");
for(var i=0;i<m.length;i++)
m[i].style.display="table-row";
})();
We can see that in this simple example all the code should be run on each page in the frame set.
So lets make a function out of that code
function killM(d){
var m=d.getElementsByTagName("marquee"); // notice we are now referring to the passed document
for(var i=0;i<m.length;i++)
m[i].style.display="table-row";
// no need for a return value here.. but they can be used
}
Now we place that into the template... and add the code to run our now named function.
(Remember, because of the surrounding anonymous function we can use sensible names :) )
javascript:(
function(){
function killM(d){
var m=d.getElementsByTagName("marquee");
for(var i=0;i<m.length;i++)
m[i].style.display="table-row";
}
var f=window.frames;
if(f.length==0){
killM(document);
}
else{
for(var i=0;i<f.length;i++){
killM(f[i].document);
}
}
}
)()
Now that we have our code it's simply a matter of removing any unnecessary whitespace so that it looks more like a real bookmarklet.
javascript:(function(){function killM(d){var m=d.getElementsByTagName("marquee");for(var i=0;i<m.length;i++)m[i].style.display="table-row";}var f=window.frames;if(f.length==0){killM(document);}else{for(var i=0;i<f.length;i++){killM(f[i].document);}}})()
And now we have code that should work on a page with frames.