jQuery(function( $ ) {
	var methods =  {
		start:function(args)
		{
			methods.pattern = args.pattern;
			if($.trim(methods.pattern))
			{
				var id = $(this).attr("id");
				methods.hiliteElement(this.get(0), methods.pattern);
			}
		},
		hiliteElement: function(elm, query) {
			if (!$.trim(query) || elm.childNodes.length == 0)
				return;

			qre = new RegExp(query.toLowerCase(),"i");
			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.className =  methods.style_name;
					span.appendChild(node2);
					return span;
				} else {
					return node;
				}
			};
			methods.walkElements(elm.childNodes[0], 1, textproc);
		},
		walkElements:function(node, depth, textproc) {
			var skipre = /^(script|style|textarea|input)/i;
			var count = 0;
			while (node && depth > 0) {
				count ++;
				if (count >= methods.max_nodes) {
					var handler = function() {
						methods.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;
						}
					}
				}
			}
		},
		max_nodes: 1000,
		style_name: 'hilite',
		pattern:''
	};
	
	$.fn.hilite = function( method )	{
		// Method calling logic
		if ( methods[method] ) {
		  return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
		  return methods.start.apply( this, arguments );
		}
	}
});
