(function($)
{
    $.fn.autocomplete = function (sSearchAjaxUrl, data)
    {
        objKeyUp = function(e, obj)
        {
            // init
            var self = obj;
            var srch = $(self).val();
            var oStoredResultDiv = $(self).data("resultDiv");
            $(self).blur(function(){oStoredResultDiv.fadeOut()})
            if (!srch || srch.length < 2 || e.keyCode == 27)
            {
              oStoredResultDiv.fadeOut();
              return;
            }
            
            // cache ?
            if($(self).data("result_" + encodeURIComponent($(self).val())))
            {
                // show records
                oPos = $(self).offset();   
                oStoredResultDiv.css({left: oPos.left, top: oPos.top + $(self).height() + 7}).html($(self).data("result_" + encodeURIComponent($(self).val()))).fadeIn();
                
                // pngfix
                if ($.fn.pngFix) $(oStoredResultDiv).pngFix();

                return;
            }   
            
            // record latest_keypress_time
            var keypress_time = new Date();
            $(self).data("latest_keypress_time", keypress_time);
                      
            // ajax
            if (typeof data === 'undefined') { data = {}; }
            data.q = $(self).val();
            $(self).addClass('busy');
            $.get(sSearchAjaxUrl, data, function(response)
            {
                $(self).removeClass('busy');
                
                // compare keypress_time with latest_keypress_time
                var latest_keypress_time = $(self).data("latest_keypress_time");
                if (keypress_time < latest_keypress_time)  { return; }
                
                // into cache
                $(self).data("result_" + encodeURIComponent($(self).val()), response.html);
                
                // show records
                oPos = $(self).offset(); 
                oStoredResultDiv.html(response.html).css({left: oPos.left, top: oPos.top + $(self).height() + 7}).fadeIn();

                // pngfix
                if ($.fn.pngFix) $(oStoredResultDiv).pngFix();
                
            }, 'json');
        }
        $(this).each(function()
        {
            var oResultDiv = document.createElement("div");
            $(oResultDiv).attr('id', 'searchresult');            
            $('#contentwrapper').append($(oResultDiv));
            $(this).data("resultDiv", $(oResultDiv));
            $(this).attr("autocomplete", "off");
            
            // onkeyup
            //$(this).keyup(objKeyUp);
            $(this).delay({delay: 300, event: 'keyup', fn: objKeyUp});
        });
        return $(this);
    };
})(jQuery);
            
//jQuery delayed event execution.
(function($)
{
    $.fn.delay = function(options)
    {
        var timer;
        var delayImpl = function(eventObj, obj)
        {
            if (timer != null)
            {
                clearTimeout(timer);
            }
            var newFn = function()
            {
                options.fn(eventObj, obj);
            }
            timer = setTimeout(newFn, options.delay);
        }
            
        return this.each(function()
        {
            var obj = $(this);
            obj.bind(options.event, function(eventObj, obj)
            {
                 delayImpl(eventObj, this);  
            });
        });
    };
})(jQuery);