/**
 * Search Engine Keyword Highlight (http://fucoder.com/code/se-hilite/)
 *
 * This module can be imported by any HTML page, and it would analyse the
 * referrer for search engine keywords, and then highlight those keywords on
 * the page, by wrapping them around <span class="hilite">...</span> tags.
 * Document can then define styles else where to provide visual feedbacks.
 *
 * Usage:
 *
 *   In HTML. Add the following line towards the end of the document.
 *
 *     <script type="text/javascript" src="se_hilite.js"></script>
 *
 *   In CSS, define the following style:
 *
 *     .hilite { background-color: #ff0; }
 *
 *   If Hilite.style_name_suffix is true, then define the follow styles:
 *
 *     .hilite1 { background-color: #ff0; }
 *     .hilite2 { background-color: #f0f; }
 *     .hilite3 { background-color: #0ff; }
 *     .hilite4 ...
 *
 * @author Scott Yang <http://scott.yang.id.au/>
 * @version 1.5
 */

////////////////////////////////////////////////////////////////
function hilite(strFrameId, strKeyword, strColor, strBackgroundColor) {
   try {
      var elem;
      if (navigator.appName != 'Netscape') {
      	elem = document.frames[strFrameId].document;
      } else {
      	elem = document.getElementById(strFrameId).contentDocument;
      }

      if ((strKeyword != null) && (strKeyword.length > 0)) {
      	Hilite.hiliteElement(elem, strKeyword, strColor, strBackgroundColor);
		}
   } catch (e) {
      window.status = e.message;
   }
}

function hiliteRenderer(nDocId, strKeyword) {
   if ((nDocId < 0) || (strKeyword == null) || (strKeyword.length == 0))
      return;
      
   var elem;
   var nLinkNum = 0;
   
   do {
      elem = document.getElementById("rendererTabLink_" + nLinkNum);
      if (elem != null) {
         Hilite.elementid = "rendererTabLink_" + nLinkNum;
         Hilite.hiliteElement(document, strKeyword);
         Hilite.elementid = 'content';
         nLinkNum++;
      }
   } while (elem != null);
   
   elem = document.getElementById("rendererAbstract");
   if (elem != null) {
      Hilite.elementid = "rendererAbstract";
      Hilite.hiliteElement(document, strKeyword);
      Hilite.elementid = 'content';
   }
}
//////////////////////////////////////////////////////////////// 
 
 
 
 
// Configuration:
Hilite = {
    /**
     * Element ID to be highlighted. If set, then only content inside this DOM
     * element will be highlighted, otherwise everything inside document.body
     * will be searched.
     */
    elementid: 'content',

    /**
     * Whether we are matching an exact word. For example, searching for
     * "highlight" will only match "highlight" but not "highlighting" if exact
     * is set to true.
     */
    exact: true,

    /**
     * Maximum number of DOM nodes to test, before handing the control back to
     * the GUI thread. This prevents locking up the UI when parsing and
     * replacing inside a large document.
     */
    max_nodes: 1000,

    /**
     * Whether to automatically hilite a section of the HTML document, by
     * binding the "Hilite.hilite()" to window.onload() event. If this
     * attribute is set to false, you can still manually trigger the hilite by
     * calling Hilite.hilite() in Javascript after document has been fully
     * loaded.
     */
    onload: false,

    /**
     * Name of the style to be used. Default to 'hilite'.
     */
    style_name: 'hilite',

    /**
     * Whether to use different style names for different search keywords by
     * appending a number starting from 1, i.e. hilite1, hilite2, etc.
     */
    style_name_suffix: false,

    /**
     * Set it to override the document.referrer string. Used for debugging
     * only.
     */
    debug_referrer: ''
};


/**
 * Decode the referrer string and return a list of search keywords.
 */

/**
 * Highlight a DOM element with a list of keywords.
 */
Hilite.hiliteElement = function(myDoc, strKeyword, strColor, strBackgroundColor) {
   var elm;
   if (myDoc == null) {
      alert("Element content to highlight is null");
      return;
   }

   var query = strKeyword.split(/[\s,\+\.]+/);

   if (!query || myDoc.childNodes.length == 0)
	return;

   if ((Hilite.elementid && (e = myDoc.getElementById(Hilite.elementid))) || (e = myDoc.body)) {
      elm = e;
   }


    var qre = new Array();
    for (var i = 0; i < query.length; i ++) {
        query[i] = query[i].toLowerCase();

        if (Hilite.exact)
            qre.push('\\b'+query[i]+'\\b');
        else
            qre.push(query[i]);
    }

    qre = new RegExp(qre.join("|"), "i");

    var stylemapper = {};
    for (var i = 0; i < query.length; i ++) {
        if (Hilite.style_name_suffix)
            stylemapper[query[i]] = Hilite.style_name+(i+1);
        else
            stylemapper[query[i]] = Hilite.style_name;
    }

    var textproc = function(node) {
        var match = qre.exec(node.data);
        if (match) {
            var val = match[0];
            var k = '';
            var node2 = node.splitText(match.index);
            var node3 = node2.splitText(val.length);
            var span = node.ownerDocument.createElement('SPAN');
            node.parentNode.replaceChild(span, node2);
            span.style.color=strColor;
            span.style.backgroundColor=strBackgroundColor;            
            //span.className = stylemapper[val.toLowerCase()];
            span.appendChild(node2);
            return span;
        } else {
            return node;
        }
    };

    Hilite.walkElements(elm.childNodes[0], 1, textproc);
};

Hilite.walkElements = function(node, depth, textproc) {
    var skipre = /^(script|style|textarea)/i;
    var count = 0;
    while (node && depth > 0) {
        count ++;
        if (count >= Hilite.max_nodes) {
            var handler = function() {
                Hilite.walkElements(node, depth, textproc);
            };
            setTimeout(handler, 50);
            return;
        }

        if (node.nodeType == 1) { // ELEMENT_NODE
            if (!skipre.test(node.tagName) && node.childNodes.length > 0) {
                node = node.childNodes[0];
                depth ++;
                continue;
            }
        } else if (node.nodeType == 3) { // TEXT_NODE
            node = textproc(node);
        }

        if (node.nextSibling) {
            node = node.nextSibling;
        } else {
            while (depth > 0) {
                node = node.parentNode;
                depth --;
                if (node.nextSibling) {
                    node = node.nextSibling;
                    break;
                }
            }
        }
    }
};


