﻿

/*
* jSuggest
* from Kean Loong Tan, http://www.gimiti.com/kltan
*/
(function(jQuery) {

    jQuery.fn.jSuggest = function(options) {
        // merge users option with default options
        var opts = jQuery.extend({}, jQuery.fn.jSuggest.defaults, options);
        var jH = ".jSuggestHover";
        var jsH = "jSuggestHover";
        var iniVal = this.value;
        var textBox = this;
        var textVal = this.value;
        var jC = "#" + opts.objID;



        jQuery(this).attr("autocomplete", "off");
        jQuery("body").append('<div id="' + opts.objID + '" class="jSuggestContainer"></div>');
        jQuery(jC).hide();
        jQuery(this).bind("keyup click", function(e) {

            textBox = this;
            textVal = this.value;
            if (this.value.length >= opts.minchar && jQuery.trim(this.value) != "Search Terms") {
                var offSet = jQuery(this).offset();

                jQuery(jC).css({
                    position: "absolute",
                    top: offSet.top + jQuery(this).outerHeight() + "px",
                    left: offSet.left,
                    width: jQuery(this).outerWidth() - 2 + "px",
                    opacity: opts.opacity,
                    zIndex: opts.zindex
                }).show();



                // if escape key
                if (e.keyCode == 27) {
                    jQuery(jC).hide();
                }

                // if enter key or tab key
                else if (e.keyCode == 13 || e.keyCode == 9) {
                    if (jQuery(jH).length == 1)
                        opts.changeFun(textBox, opts, jH, true);
                    jQuery(jC).hide();
                    iniVal = textBox.value;
                }
                // if down arrow
                else if (e.keyCode == 40) {
                    // if any suggestion is highlighted
                    if (jQuery(jH).length == 1) {
                        if (!jQuery(jH).next().length == 0) {
                            jQuery(jH).next().addClass(jsH);
                            jQuery(".jSuggestHover:eq(0)").removeClass(jsH);
                            if (opts.autoChange)
                                opts.changeFun(textBox, opts, jH, false);
                        }
                    }
                    else {
                        jQuery("#" + opts.objID + " ul li:first-child").addClass(jsH);
                        if (opts.autoChange)
                            opts.changeFun(textBox, opts, jH, false);
                    }

                }

                // if up arrow
                else if (e.keyCode == 38) {
                    // if any suggestion is highlighted
                    if (jQuery(jH).length == 1) {
                        if (!jQuery(jH).prev().length == 0) {
                            jQuery(jH).prev().addClass(jsH);
                            jQuery(".jSuggestHover:eq(1)").removeClass(jsH);
                            if (opts.autoChange)
                                opts.changeFun(textBox, opts, jH, false);
                        }
                        // if is first child
                        else {
                            jQuery(jH).removeClass(jsH);
                            jQuery(textBox).val(iniVal);
                        }
                    }
                }
                // new query detected
                else if (textBox.value != iniVal) {
                    iniVal = textBox.value;
                    if (jQuery(".jSuggestLoading").length == 0)
                        jQuery('<div class="jSuggestLoading"><img src="' + opts.loadingImg + '" align="bottom" /> ' + opts.loadingText + '</div>').prependTo("#" + opts.objID);

                    jQuery(".jSuggestLoading").show();
                    jQuery(jC).find('ul').remove();

                    opts.data = jQuery(this).serialize(); //序列化键值对
                    // optimize server performance by loading at intervals
                    setTimeout(function() {
                        jQuery.getJSON(
                            opts.url,
                            opts.data,
                            function(json) {
                                jQuery(jC).find('ul').remove();

                                var ulObj = jQuery("<ul></ul>");

                                //modify by zimo 2010.5.27.
                                //jQuery(json.data).each(function(i) { ulObj.append(jQuery.sp.format(opts.dataFormat, this.id, this.text)); });
                                jQuery.each(json, function(i) { ulObj.append(jQuery.sp.format(opts.dataFormat, json[i].id, json[i].text, json[i].value)); });

                                jQuery(jC).append(ulObj);


                                jQuery("#" + opts.objID + " ul li").bind("mouseover", function() {
                                    jQuery(jH).removeClass(jsH);
                                    jQuery(this).addClass(jsH);
                                    if (opts.autoChange)
                                        opts.changeFun(textBox, opts, jH, false);
                                });
                                jQuery("#" + opts.objID + " ul li").click(function() {
                                    jQuery(this).addClass(jsH);
                                    //opts.changeFun(textBox, opts, jH, false);
                                });
                                jQuery(".jSuggestLoading").hide();
                            }
                        );
                    }, opts.delay);
                }
            }
            // if text is too short do nothing and hide everything
            else {
                jQuery(jH).removeClass(jsH);
                jQuery(jC).hide();
            }

            // no bubbling, click is binded to textBox to prevent document bind from firing
            return false;
        });

        // why no use jQuery(this).blur ?, because jSuggest box is hidden before click fires so this is the only way to do it
        // alternate way is to say that text blur will fire beforejQuery("#jSuggestContainer ul li") click.
        jQuery(document).bind("click", function() {
            jQuery(jC).hide();
            iniVal = textBox.value;
        });
        //取消全局事件的注册，这样才会触发后面的keyup中的回车事件
        jQuery(document).bind("keydown", function(e) {
            if (e.keyCode == 13) {
                return false;
            }
        });


    };

    jQuery.fn.jSuggest.defaults = {
        minchar: 1,
        opacity: 1,
        zindex: 20000,
        delay: 100,
        loadingImg: '/images/loading.gif',
        loadingText: 'Loading...',
        autoChange: true,
        changeFun: function(obj, opts, jH, isAdd) { jQuery(obj).val(opts.dataName == "" ? jQuery(jH).text() : jQuery(jH).attr(opts.dataName)); },
        //        url: "",
        type: "GET",
        //data: "", //未使用
        objID: "jSuggestContainer",
        dataName: "", //保存数据的key
        dataFormat: "<li>{1}</li>"
    };


})(jQuery);

