Code snippets

From GreaseSpot Wiki
Revision as of 10:47, 4 February 2010 by Arantius (talk | contribs)
Jump to navigationJump to search

Note: Contents in the process of being migrated to separate pages within Category:Coding Tips.

Hijacking browser properties

Sometimes you want to cook your own browser constants, for instance change the value of navigator.userAgent. Getters are good for that:

var real = window.navigator.userAgent;
var lie = function() { return real + " Macintosh"; };
unsafeWindow.navigator.__defineGetter__("userAgent", lie);

Extending the DOM with missing functions

Other times you might want to emulate proprietary functionality of another browser, for instance when a site uses such features:

var getter = function() { return this.textContent; };
var setter = function(t) { return this.textContent = t; };
unsafeWindow.HTMLElement.prototype.__defineGetter__("innerText", getter);
unsafeWindow.HTMLElement.prototype.__defineSetter__("innerText", setter);

Here is a function to get outerHTML without using unsafeWindow (note: the above isn't working with FF3 and GM 0.8, anyway).

function outerHTML(el){
  // create range of element
  var rng=document.createRange();
  rng.selectNode(el);
  // create temp span around element
  var tempSpan=document.createElement("span");
  rng.surroundContents(tempSpan);
  // what we came for
  var oHTML=tempSpan.innerHTML;
  // remove temp span
  rng.selectNodeContents(tempSpan);
  var frag = rng.cloneContents();
  tempSpan.parentNode.replaceChild(frag, tempSpan);
  // remove range
  rng.detach();
  // output
  return oHTML;
}

Make script accessible to Firebug

Firebug's console is very useful but can't access functions in a script this can make debugging them tiresome. The following code will run the entire script in the page so you can mess about with it from Firebug.

function a() {return a.caller.toString().replace(/([\s\S]*?return;){2}([\s\S]*)}/,'$2')}
document.body.appendChild(document.createElement('script')).innerHTML=a();
return;

Embed a function in the current page

function embedFunction(s) {
document.body.appendChild(document.createElement('script')).innerHTML=s.toString().replace(/([\s\S]*?return;){2}([\s\S]*)}/,'$2');
}

Example:

function helloWorld() { alert("hello world"); }
...
embedFunction(helloWorld);
varBody = document.getElementsByTagName("body")[0];
varBody.innerHTML = varBody.innerHTML+ '<a title="Click me" href="javascript:helloWorld();">Click for hello world</a>';

Dump the properties of an object

This function will allow you to easily dump the properties of an object and their values to the firebug console, or anywhere else you like. I know it is long, but it also does nice formatting on the output, helping it to be readable

 /* dumpObj courtesy of Scott Van Vliet
 *
 *  http://weblogs.asp.net/skillet/archive/2006/03/23/440940.aspx
 *  
 *  usage:
 *  params: all are optional except obj
 *    
 *  obj        -> OBJECT    your object to dump
 *  name       -> STRING    the name of your object if you want it printed
 *  maxDepth   -> NUMBER    the maximum nested objects that will be dumped. Defaults to 0, because 
 *                          it grows exponentially, so most of the time, it will be better and
 *                          easier to read if you just call dump on the child object manually.
 *  format     -> BOOLEAN   whether to format the output (default=1). Turn this of if you have to
 *                          HTML content from it, to keep the indent low.
 *  indent     ↓
 *  tabsize    ↓
 *  depth      ↓
 *  tabs       -> these are for internal communication when recursing.., if you plan on touching
 *                them, you shouldn't need documentation...lol
 *  
 *  The formatting works well only if viewed in a monospaced font. This means good in the firebug
 *  console, and probably bad in alert boxes, unless you set your chrome to use a monospace font...
 *  
 *  modifications by Naja Melan ( najamelan<AT>gmail )
 *  
 **/
 
 function dump( obj, name, maxDepth, format, indent, tabsize, depth, tabs ) 
 {
   if( typeof obj      == "undefined" ) return "dumpObj: No object was passed in!\n";
   if( typeof maxDepth == "undefined" ) maxDepth = 0;
   if( typeof name     == "undefined" ) name     = "<root object>";
   if( typeof format   == "undefined" ) format   = 1;
   if( typeof indent   == "undefined" ) indent   = "";
   if( typeof tabSize  == "undefined" ) tabSize  = 8;
   if( typeof depth    == "undefined" ) depth    = 0;
   if( typeof tabs     == "undefined" ) tabs     = "";
     
   if( typeof obj != "object" ) return obj;
 
   var child = null,
       output = [];
       
   output.push( indent + name + "\n" );
 
   if( format )
   {
     indent += "  ";
     
     var maxLength = 0;
     for( var item in obj )
       if( item.toString().length > maxLength ) maxLength = item.toString().length;
   }
   
   for( var item in obj )
   {
     try
     {
      child = obj[item];
     } 
 
     catch (e) 
     {
      child = "<Unable to Evaluate>";
     }
     
     if( format )
     {
       var numSp   = maxLength - item.toString().length + 1,
           tabs    = "";
 
       while( --numSp > 0 ) tabs += " ";
     }
     
     if( typeof child == "object" ) 
     {
       if( depth >= maxDepth ) 
         output.push(  indent + item + tabs + ": <object, max depth reached>\n" );
 
       else
       {
         try
         {
           var temp = dump( child, item, maxDepth, format, indent, tabsize, depth + 1, tabs );
         }
         catch( e )
         {
           output.push( indent + item + tabs + ": <object could not be iterated, Error name: '" +
                        e.name + "'. Error message: '" + e.message + "'>\n" );
           temp = null;
         }
       
         if( temp == indent + item + "\n" )
           output.push( indent + item + tabs + ": <object, only has built-in properties>\n" );
         
         else if( temp )
         {
           output.push( " \n" );
           output.push( temp );
           output.push( "\n------------------------------------------------------------------------<end of " +
                        item + ">---------------------------------------------- \n \n" );
         }
       }
       continue;
     } 
 
     else 
     {
       if( format )
       {
         var intro   = indent + item,
             length  = intro.length + numSp + 1,
             indent2 = "  ";
             
         while( --length > 0 ) indent2 += " ";
       }
       
       else
       {
         var intro   = indent + item,
             tabs    = indent2 = "";
       }
 
       output.push( intro + tabs + ": " + 
         ( ( !format )? child : child.toString().replace( /({)\n   ( \[native code\])\n(})/,
           "$1$2 $3"  ).replace( /(\r\n|[\r\n]+|<br ?\/?>)/gm, "$1" + indent2 + tabs ) ) + "\n" );
     }
   }
   return output.join( "" );
 }

Force Links to Open in Another Window

Useful when you have altered the page in a custom way (i.e. via user input) and need to preserve the customized page without repainting form fields or customized nodes. This assumes only anchor links, not button or JavaScript induced links:

 var anchorTags=document.links;
 for (var i=anchorTags.length - 1; i >= 0;--i)
         anchorTags[i].target="_blank";

nextSibling function that skips whitespace

function nextSibling(startSib){
    var nextSib;
    if (!(nextSib=startSib.nextSibling)) 
        return false;
    while (nextSib.nodeType!=1) 
        if (!(nextSib=nextSib.nextSibling)) 
            return false;
    return nextSib;
}

Example Usage

if (nextSib=nexSibling(element)) 
    alert(nextSib.textContent);