您的位置:首页 > 博客中心 > 数据库 >

jquery autocomplete实现读取sql数据库自动补全TextBox

时间:2022-03-13 22:33

项目需要这样子一个功能,其他部门提的意见,只好去实现了哦,搞了好久才弄出来,分享一下。

1.前台页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script src="jquery-1.4.1-vsdoc.js" type="text/javascript"></script>
    <script src="jquery.autocomplete.js" type="text/javascript"></script>
    <link href="jquery.autocomplete.css" type="text/css" rel="stylesheet" />
    <script language="javascript" type="text/javascript">
        $(document).ready((function ()
        {
            $("#txtUser").autocomplete("GetCode.aspx");
        }
));
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            用户名:
            <asp:TextBox ID="txtUser" runat="server"></asp:TextBox>
        </div>
    </form>
</body>
</html>

2.GetCode.aspx

前台为空

后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;

public partial class GetCode : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.QueryString["q"] != null)
        {
            string key = Request.Params["q"].ToString();
            string result = "";
            SqlHelp sql = new SqlHelp();
            string str = "select top 15 CustomCode from tCustomList where CustomCode like '" + key + "%'";
            SqlDataReader dr = sql.ExecuteReader(str);
            while (dr.Read())
            {
                result += dr["CustomCode"].ToString() + "\n";
            }
            dr.Dispose();
            sql.SqlClose();
            if (result == "")
                result = "not exists";
            Response.Write(result);
        } 
    }
}

3jquery.autocomplete.js

jQuery.autocomplete = function (input, options)
{
    // Create a link to self
    var me = this;

    // Create jQuery object for input element
    var $input = $(input).attr("autocomplete", "off");

    // Apply inputClass if necessary
    if (options.inputClass) $input.addClass(options.inputClass);

    // Create results
    var results = document.createElement("div");
    // Create jQuery object for results
    var $results = $(results);
    $results.hide().addClass(options.resultsClass).css("position", "absolute");
    if (options.width > 0) $results.css("width", options.width);

    // Add to body element
    $("body").append(results);

    input.autocompleter = me;

    var timeout = null;
    var prev = "";
    var active = -1;
    var cache = {};
    var keyb = false;
    var hasFocus = false;
    var lastKeyPressCode = null;

    // flush cache
    function flushCache()
    {
        cache = {};
        cache.data = {};
        cache.length = 0;
    };

    // flush cache
    flushCache();

    // if there is a data array supplied
    if (options.data != null) {
        var sFirstChar = "", stMatchSets = {}, row = [];

        // no url was specified, we need to adjust the cache length to make sure it fits the local data store
        if (typeof options.url != "string") options.cacheLength = 1;

        // loop through the array and create a lookup structure
        for (var i = 0; i < options.data.length; i++) {
            // if row is a string, make an array otherwise just reference the array
            row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);

            // if the length is zero, don't add to list
            if (row[0].length > 0) {
                // get the first character
                sFirstChar = row[0].substring(0, 1).toLowerCase();
                // if no lookup array for this character exists, look it up now
                if (!stMatchSets[sFirstChar]) stMatchSets[sFirstChar] = [];
                // if the match is a string
                stMatchSets[sFirstChar].push(row);
            }
        }

        // add the data items to the cache
        for (var k in stMatchSets) {
            // increase the cache size
            options.cacheLength++;
            // add to the cache
            addToCache(k, stMatchSets[k]);
        }
    }

    $input
	.keydown(function (e)
	{
	    // track last key pressed
	    lastKeyPressCode = e.keyCode;
	    switch (e.keyCode) {
	        case 38: // up
	            e.preventDefault();
	            moveSelect(-1);
	            break;
	        case 40: // down
	            e.preventDefault();
	            moveSelect(1);
	            break;
	        case 9:  // tab
	        case 13: // return
	            if (selectCurrent()) {
	                // make sure to blur off the current field
	                $input.get(0).blur();
	                e.preventDefault();
	            }
	            break;
	        default:
	            active = -1;
	            if (timeout) clearTimeout(timeout);
	            timeout = setTimeout(function () { onChange(); }, options.delay);
	            break;
	    }
	})
	.focus(function ()
	{
	    // track whether the field has focus, we shouldn't process any results if the field no longer has focus
	    hasFocus = true;
	})
	.blur(function ()
	{
	    // track whether the field has focus
	    hasFocus = false;
	    hideResults();
	});

    hideResultsNow();

    function onChange()
    {
        // ignore if the following keys are pressed: [del] [shift] [capslock]
        if (lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32)) return $results.hide();
        var v = $input.val();
        if (v == prev) return;
        prev = v;
        if (v.length >= options.minChars) {
            $input.addClass(options.loadingClass);
            requestData(v);
        } else {
            $input.removeClass(options.loadingClass);
            $results.hide();
        }
    };

    function moveSelect(step)
    {

        var lis = $("li", results);
        if (!lis) return;

        active += step;

        if (active < 0) {
            active = 0;
        } else if (active >= lis.size()) {
            active = lis.size() - 1;
        }

        lis.removeClass("ac_over");

        $(lis[active]).addClass("ac_over");

        // Weird behaviour in IE
        // if (lis[active] && lis[active].scrollIntoView) {
        // 	lis[active].scrollIntoView(false);
        // }

    };

    function selectCurrent()
    {
        var li = $("li.ac_over", results)[0];
        if (!li) {
            var $li = $("li", results);
            if (options.selectOnly) {
                if ($li.length == 1) li = $li[0];
            } else if (options.selectFirst) {
                li = $li[0];
            }
        }
        if (li) {
            selectItem(li);
            return true;
        } else {
            return false;
        }
    };

    function selectItem(li)
    {
        if (!li) {
            li = document.createElement("li");
            li.extra = [];
            li.selectValue = "";
        }
        var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
        input.lastSelected = v;
        prev = v;
        $results.html("");
        $input.val(v);
        hideResultsNow();
        if (options.onItemSelect) setTimeout(function () { options.onItemSelect(li) }, 1);
    };

    // selects a portion of the input string
    function createSelection(start, end)
    {
        // get a reference to the input element
        var field = $input.get(0);
        if (field.createTextRange) {
            var selRange = field.createTextRange();
            selRange.collapse(true);
            selRange.moveStart("character", start);
            selRange.moveEnd("character", end);
            selRange.select();
        } else if (field.setSelectionRange) {
            field.setSelectionRange(start, end);
        } else {
            if (field.selectionStart) {
                field.selectionStart = start;
                field.selectionEnd = end;
            }
        }
        field.focus();
    };

    // fills in the input box w/the first match (assumed to be the best match)
    function autoFill(sValue)
    {
        // if the last user key pressed was backspace, don't autofill
        if (lastKeyPressCode != 8) {
            // fill in the value (keep the case the user has typed)
            $input.val($input.val() + sValue.substring(prev.length));
            // select the portion of the value not typed by the user (so the next character will erase)
            createSelection(prev.length, sValue.length);
        }
    };

    function showResults()
    {
        // get the position of the input field right now (in case the DOM is shifted)
        var pos = findPos(input);
        // either use the specified width, or autocalculate based on form element
        var iWidth = (options.width > 0) ? options.width : $input.width();
        // reposition
        $results.css({
            width: parseInt(iWidth) + "px",
            top: (pos.y + input.offsetHeight) + "px",
            left: pos.x + "px"
        }).show();
    };

    function hideResults()
    {
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(hideResultsNow, 200);
    };

    function hideResultsNow()
    {
        if (timeout) clearTimeout(timeout);
        $input.removeClass(options.loadingClass);
        if ($results.is(":visible")) {
            $results.hide();
        }
        if (options.mustMatch) {
            var v = $input.val();
            if (v != input.lastSelected) {
                selectItem(null);
            }
        }
    };

    function receiveData(q, data)
    {
        if (data) {
            $input.removeClass(options.loadingClass);
            results.innerHTML = "";

            // if the field no longer has focus or if there are no matches, do not display the drop down
            if (!hasFocus || data.length == 0) return hideResultsNow();

            if ($.browser.msie) {
                // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
                $results.append(document.createElement('iframe'));
            }
            results.appendChild(dataToDom(data));
            // autofill in the complete box w/the first match as long as the user hasn't entered in more data
            if (options.autoFill && ($input.val().toLowerCase() == q.toLowerCase())) autoFill(data[0][0]);
            showResults();
        } else {
            hideResultsNow();
        }
    };

    function parseData(data)
    {
        if (!data) return null;
        var parsed = [];
        var rows = data.split(options.lineSeparator);
        for (var i = 0; i < rows.length; i++) {
            var row = $.trim(rows[i]);
            if (row) {
                parsed[parsed.length] = row.split(options.cellSeparator);
            }
        }
        return parsed;
    };

    function dataToDom(data)
    {
        var ul = document.createElement("ul");
        var num = data.length;

        // limited results to a max number
        if ((options.maxItemsToShow > 0) && (options.maxItemsToShow < num)) num = options.maxItemsToShow;

        for (var i = 0; i < num; i++) {
            var row = data[i];
            if (!row) continue;
            var li = document.createElement("li");
            if (options.formatItem) {
                li.innerHTML = options.formatItem(row, i, num);
                li.selectValue = row[0];
            } else {
                li.innerHTML = row[0];
                li.selectValue = row[0];
            }
            var extra = null;
            if (row.length > 1) {
                extra = [];
                for (var j = 1; j < row.length; j++) {
                    extra[extra.length] = row[j];
                }
            }
            li.extra = extra;
            ul.appendChild(li);
            $(li).hover(
				function () { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },
				function () { $(this).removeClass("ac_over"); }
			).click(function (e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
        }
        return ul;
    };

    function requestData(q)
    {
        if (!options.matchCase) q = q.toLowerCase();
        var data = options.cacheLength ? loadFromCache(q) : null;
        // recieve the cached data
        if (data) {
            receiveData(q, data);
            // if an AJAX url has been supplied, try loading the data now
        } else if ((typeof options.url == "string") && (options.url.length > 0)) {
            $.get(makeUrl(q), function (data)
            {
                data = parseData(data);
                addToCache(q, data);
                receiveData(q, data);
            });
            // if there's been no data found, remove the loading class
        } else {
            $input.removeClass(options.loadingClass);
        }
    };

    function makeUrl(q)
    {
        var url = options.url + "?q=" + encodeURI(q);
        for (var i in options.extraParams) {
            url += "&" + i + "=" + encodeURI(options.extraParams[i]);
        }
        return url;
    };

    function loadFromCache(q)
    {
        if (!q) return null;
        if (cache.data[q]) return cache.data[q];
        if (options.matchSubset) {
            for (var i = q.length - 1; i >= options.minChars; i--) {
                var qs = q.substr(0, i);
                var c = cache.data[qs];
                if (c) {
                    var csub = [];
                    for (var j = 0; j < c.length; j++) {
                        var x = c[j];
                        var x0 = x[0];
                        if (matchSubset(x0, q)) {
                            csub[csub.length] = x;
                        }
                    }
                    return csub;
                }
            }
        }
        return null;
    };

    function matchSubset(s, sub)
    {
        if (!options.matchCase) s = s.toLowerCase();
        var i = s.indexOf(sub);
        if (i == -1) return false;
        return i == 0 || options.matchContains;
    };

    this.flushCache = function ()
    {
        flushCache();
    };

    this.setExtraParams = function (p)
    {
        options.extraParams = p;
    };

    this.findValue = function ()
    {
        var q = $input.val();

        if (!options.matchCase) q = q.toLowerCase();
        var data = options.cacheLength ? loadFromCache(q) : null;
        if (data) {
            findValueCallback(q, data);
        } else if ((typeof options.url == "string") && (options.url.length > 0)) {
            $.get(makeUrl(q), function (data)
            {
                data = parseData(data)
                addToCache(q, data);
                findValueCallback(q, data);
            });
        } else {
            // no matches
            findValueCallback(q, null);
        }
    }

    function findValueCallback(q, data)
    {
        if (data) $input.removeClass(options.loadingClass);

        var num = (data) ? data.length : 0;
        var li = null;

        for (var i = 0; i < num; i++) {
            var row = data[i];

            if (row[0].toLowerCase() == q.toLowerCase()) {
                li = document.createElement("li");
                if (options.formatItem) {
                    li.innerHTML = options.formatItem(row, i, num);
                    li.selectValue = row[0];
                } else {
                    li.innerHTML = row[0];
                    li.selectValue = row[0];
                }
                var extra = null;
                if (row.length > 1) {
                    extra = [];
                    for (var j = 1; j < row.length; j++) {
                        extra[extra.length] = row[j];
                    }
                }
                li.extra = extra;
            }
        }

        if (options.onFindValue) setTimeout(function () { options.onFindValue(li) }, 1);
    }

    function addToCache(q, data)
    {
        if (!data || !q || !options.cacheLength) return;
        if (!cache.length || cache.length > options.cacheLength) {
            flushCache();
            cache.length++;
        } else if (!cache[q]) {
            cache.length++;
        }
        cache.data[q] = data;
    };

    function findPos(obj)
    {
        var curleft = obj.offsetLeft || 0;
        var curtop = obj.offsetTop || 0;
        while (obj = obj.offsetParent) {
            curleft += obj.offsetLeft
            curtop += obj.offsetTop
        }
        return { x: curleft, y: curtop };
    }
}

jQuery.fn.autocomplete = function (url, options, data)
{
    // Make sure options exists
    options = options || {};
    // Set url as option
    options.url = url;
    // set some bulk local data
    options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;

    // Set default values for required options
    options.inputClass = options.inputClass || "ac_input";
    options.resultsClass = options.resultsClass || "ac_results";
    options.lineSeparator = options.lineSeparator || "\n";
    options.cellSeparator = options.cellSeparator || "|";
    options.minChars = options.minChars || 1;
    options.delay = options.delay || 400;
    options.matchCase = options.matchCase || 0;
    options.matchSubset = options.matchSubset || 1;
    options.matchContains = options.matchContains || 0;
    options.cacheLength = options.cacheLength || 1;
    options.mustMatch = options.mustMatch || 0;
    options.extraParams = options.extraParams || {};
    options.loadingClass = options.loadingClass || "ac_loading";
    options.selectFirst = options.selectFirst || false;
    options.selectOnly = options.selectOnly || false;
    options.maxItemsToShow = options.maxItemsToShow || -1;
    options.autoFill = options.autoFill || false;
    options.width = parseInt(options.width, 10) || 0;

    this.each(function ()
    {
        var input = this;
        new jQuery.autocomplete(input, options);
    });

    // Don't break the chain
    return this;
}

jQuery.fn.autocompleteArray = function (data, options)
{
    return this.autocomplete(null, options, data);
}

jQuery.fn.indexOf = function (e)
{
    for (var i = 0; i < this.length; i++) {
        if (this[i] == e) return i;
    }
    return -1;
};

4.jquery-1.4.1-vsdoc.js

?/*
 * This file has been commented to support Visual Studio Intellisense.
 * You should not use this file at runtime inside the browser--it is only
 * intended to be used only for design-time IntelliSense.  Please use the
 * standard jQuery library for all production use.
 *
 * Comment version: 1.4.1a
 */
 
/*!
 * jQuery JavaScript Library v1.4.1
 * http://jquery.com/
 *
 * Distributed in whole under the terms of the MIT
 *
 * Copyright 2010, John Resig
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXpreSS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Mon Jan 25 19:43:33 2010 -0500
 */
 
(function( window, undefined ) {
 
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
                ///     <summary>
                ///             1: $(expression, context) - 此函数接受一个包含 CSS 选择器的字符串,随后将使用该选择器匹配一组元素。
                ///             2: $(html) - 基于提供的原始 HTML 字符串动态创建 DOM 元素。
                ///             3: $(elements) - 围绕单个或多个 DOM 元素包装 jQuery 功能。
                ///             4: $(callback) - $(document).ready() 的简写形式。
                ///             5: $() - 从 jQuery 1.4 开始,如果未向 jQuery()方法传递任何参数,则将返回空的 jQuery 集。
                ///     </summary>
                ///     <param name="selector" type="String">
                ///             1: expression - 要用于搜索的表达式。
                ///             2: html - 要动态创建的 HTML 字符串。
                ///             3: elements - 将由 jQuery 对象封装的 DOM 元素。
                ///             4: callback - 当 DOM 就绪时要执行的函数。
                ///     </param>
                ///     <param name="context" type="jQuery">
                ///             1: context - 要用作上下文的 DOM 元素、文档或 jQuery。
                ///     </param>
                ///     <returns type="jQuery" />
 
                // The jQuery object is actually just the init constructor 'enhanced'
                return new jQuery.fn.init( selector, context );
        },
 
        // Map over jQuery in case of overwrite
        _jQuery = window.jQuery,
 
        // Map over the $ in case of overwrite
        _$ = window.$,
 
        // Use the correct document accordingly with window argument (sandbox)
        document = window.document,
 
        // A central reference to the root jQuery(document)
        rootjQuery,
 
        // A simple way to check for HTML strings or ID strings
        // (both of which we optimize for)
        quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
 
        // Is it a simple selector
        isSimple = /^.[^:#\[\.,]*$/,
 
        // Check if a string has a non-whitespace character in it
        rnotwhite = /\S/,
 
        // Used for trimming whitespace
        rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
 
        // Match a standalone tag
        rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
 
        // Keep a UserAgent string for use with jQuery.browser
        userAgent = navigator.userAgent,
 
        // For matching the engine and version of the browser
        browserMatch,
       
        // Has the ready events already been bound?
        readyBound = false,
       
        // The functions to execute on DOM ready
        readyList = [],
 
        // The ready event handler
        DOMContentLoaded,
 
        // Save a reference to some core methods
        toString = Object.prototype.toString,
        hasOwnProperty = Object.prototype.hasOwnProperty,
        push = Array.prototype.push,
        slice = Array.prototype.slice,
        indexOf = Array.prototype.indexOf;
 
jQuery.fn = jQuery.prototype = {
        init: function( selector, context ) {
 
                var match, elem, ret, doc;
 
                // Handle $(""), $(null), or $(undefined)
                if ( !selector ) {
                        return this;
                }
 
                // Handle $(DOMElement)
                if ( selector.nodeType ) {
                        this.context = this[0] = selector;
                        this.length = 1;
                        return this;
                }
 
                // Handle HTML strings
                if ( typeof selector === "string" ) {
                        // Are we dealing with HTML string or an ID?
                        match = quickExpr.exec( selector );
 
                        // Verify a match, and that no context was specified for #id
                        if ( match && (match[1] || !context) ) {
 
                                // HANDLE: $(html) -> $(array)
                                if ( match[1] ) {
                                        doc = (context ? context.ownerDocument || context : document);
 
                                        // If a single string is passed in and it's a single tag
                                        // just do a createElement and skip the rest
                                        ret = rsingleTag.exec( selector );
 
                                        if ( ret ) {
                                                if ( jQuery.isPlainObject( context ) ) {
                                                        selector = [ document.createElement( ret[1] ) ];
                                                        jQuery.fn.attr.call( selector, context, true );
 
                                                } else {
                                                        selector = [ doc.createElement( ret[1] ) ];
                                                }
 
                                        } else {
                                                ret = buildFragment( [ match[1] ], [ doc ] );
                                                selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
                                        }
 
                                // HANDLE: $("#id")
                                } else {
                                        elem = document.getElementById( match[2] );
 
                                        if ( elem ) {
                                                // Handle the case where IE and Opera return items
                                                // by name instead of ID
                                                if ( elem.id !== match[2] ) {
                                                        return rootjQuery.find( selector );
                                                }
 
                                                // Otherwise, we inject the element directly into the jQuery object
                                                this.length = 1;
                                                this[0] = elem;
                                        }
 
                                        this.context = document;
                                        this.selector = selector;
                                        return this;
                                }
 
                        // HANDLE: $("TAG")
                        } else if ( !context && /^\w+$/.test( selector ) ) {
                                this.selector = selector;
                                this.context = document;
                                selector = document.getElementsByTagName( selector );
 
                        // HANDLE: $(expr, $(...))
                        } else if ( !context || context.jquery ) {
                                return (context || rootjQuery).find( selector );
 
                        // HANDLE: $(expr, context)
                        // (which is just equivalent to: $(context).find(expr)
                        } else {
                                return jQuery( context ).find( selector );
                        }
 
                // HANDLE: $(function)
                // Shortcut for document ready
                } else if ( jQuery.isFunction( selector ) ) {
                        return rootjQuery.ready( selector );
                }
 
                if (selector.selector !== undefined) {
                        this.selector = selector.selector;
                        this.context = selector.context;
                }
 
                return jQuery.isArray( selector ) ?
                        this.setArray( selector ) :
                        jQuery.makeArray( selector, this );
        },
 
        // Start with an empty selector
        selector: "",
 
        // The current version of jQuery being used
        jquery: "1.4.1",
 
        // The default length of a jQuery object is 0
        length: 0,
 
        // The number of elements contained in the matched element set
        size: function() {
                ///     <summary>
                ///             当前匹配的元素的数目。
                ///             核心部分
                ///     </summary>
                ///     <returns type="Number" />
 
                return this.length;
        },
 
        toArray: function() {
                ///     <summary>
                ///             以数组的形式检索 jQuery 集中包含的所有 DOM 元素。
                ///     </summary>
                ///     <returns type="Array" />
                return slice.call( this, 0 );
        },
 
        // Get the Nth element in the matched element set OR
        // Get the whole matched element set as a clean array
        get: function( num ) {
                ///     <summary>
                ///             访问单个匹配的元素。num 用于访问
                ///             匹配的第 N 个元素。
                ///             核心部分
                ///     </summary>
                ///     <returns type="Element" />
                ///     <param name="num" type="Number">
                ///             访问处于第 N 个位置的元素。
                ///     </param>
 
                return num == null ?
 
                        // Return a 'clean' array
                        this.toArray() :
 
                        // Return just the object
                        ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
        },
 
        // Take an array of elements and push it onto the stack
        // (returning the new matched element set)
        pushStack: function( elems, name, selector ) {
                ///     <summary>
                ///             将 jQuery 对象设置为一个元素数组,同时对
                ///             堆栈进行维护。
                ///             核心部分
                ///     </summary>
                ///     <returns type="jQuery" />
                ///     <param name="elems" type="Elements">
                ///             元素数组
                ///     </param>
 
                // Build a new jQuery matched element set
                var ret = jQuery( elems || null );
 
                // Add the old object onto the stack (as a reference)
                ret.prevObject = this;
 
                ret.context = this.context;
 
                if ( name === "find" ) {
                        ret.selector = this.selector + (this.selector ? " " : "") + selector;
                } else if ( name ) {
                        ret.selector = this.selector + "." + name + "(" + selector + ")";
                }
 
                // Return the newly-formed element set
                return ret;
        },
 
        // Force the current matched set of elements to become
        // the specified array of elements (destroying the stack in the process)
        // You should use pushStack() in order to do this, but maintain the stack
        setArray: function( elems ) {
                ///     <summary>
                ///             将 jQuery 对象设置为一个元素数组。此操作具有十足的
                ///             破坏性 - 如果您希望维护 jQuery 堆栈,
                ///             请务必使用 .pushStack()。
                ///             核心部分
                ///     </summary>
                ///     <returns type="jQuery" />
                ///     <param name="elems" type="Elements">
                ///             元素数组
                ///     </param>
 
                // Resetting the length to 0, then using the native Array push
                // is a super-fast way to populate an object with array-like properties
                this.length = 0;
                push.apply( this, elems );
 
                return this;
        },
 
        // Execute a callback for every element in the matched set.
        // (You can seed the arguments with an array of args, but this is
        // only used internally.)
        each: function( callback, args ) {
                ///     <summary>
                ///             在每个匹配元素的上下文中执行函数。
                ///             这意味着每次执行传入的函数
                ///             (为每个匹配的元素执行一次)时,“this”关键字
                ///             将指向特定元素。
                ///             此外,在执行该函数时,还会为其传递一个参数,
                ///             用于表示元素在匹配集中的位置
                ///             。
                ///             核心部分
                ///     </summary>
                ///     <returns type="jQuery" />
                ///     <param name="callback" type="Function">
                ///             要执行的函数
                ///     </param>
 
                return jQuery.each( this, callback, args );
        },
       
        ready: function( fn ) {
                ///     <summary>
                ///             绑定一个每当准备好遍历和操作 DOM 时就要执行的函数。
                ///     </summary>
                ///     <param name="fn" type="Function">当 DOM 就绪时要执行的函数。</param>
 
                // Attach the listeners
                jQuery.bindReady();
 
                // If the DOM is already ready
                if ( jQuery.isReady ) {
                        // Execute the function immediately
                        fn.call( document, jQuery );
 
                // Otherwise, remember the function for later
                } else if ( readyList ) {
                        // Add the function to the wait list
                        readyList.push( fn );
                }
 
                return this;
        },
       
        eq: function( i ) {
                ///     <summary>
                ///             将匹配元素集简化为单个元素。
                ///             元素在匹配元素集中的位置
                ///             从 0 开始,直至 length - 1。
                ///             核心部分
                ///     </summary>
                ///     <returns type="jQuery" />
                ///     <param name="num" type="Number">
                ///             pos 希望限制为的元素索引。
                ///     </param>
 
                return i === -1 ?
                        this.slice( i ) :
                        this.slice( i, +i + 1 );
        },
 
        first: function() {
                ///     <summary>
                ///             将匹配元素集精简为集合中的第一个元素。
                ///     </summary>
                ///     <returns type="jQuery" />
 
                return this.eq( 0 );
        },
 
        last: function() {
                ///     <summary>
                ///             将匹配元素集精简为集合中的最后一个元素。
                ///     </summary>
                ///     <returns type="jQuery" />
 
                return this.eq( -1 );
        },
 
        slice: function() {
                ///     <summary>
                ///             选择匹配元素的子集。行为方式与内置的 Array 切片方法完全一样。
                ///     </summary>
                ///     <param name="start" type="Number" integer="true">开始子集的位置(从 0 开始)。</param>
                ///     <param name="end" optional="true" type="Number" integer="true">结束子集的位置(不包括结束元素本身)。
                ///             如果省略,则在选择结束时结束</param>
                ///     <returns type="jQuery">切片元素</returns>
 
                return this.pushStack( slice.apply( this, arguments ),
                        "slice", slice.call(arguments).join(",") );
        },
 
        map: function( callback ) {
                ///     <summary>
                ///             此成员为内部成员。
                ///     </summary>
                ///     <private />
                ///     <returns type="jQuery" />
 
                return this.pushStack( jQuery.map(this, function( elem, i ) {
                        return callback.call( elem, i, elem );
                }));
        },
       
        end: function() {
                ///     <summary>
                ///             结束最新的“破坏性”操作,并将匹配元素的列表
                ///             还原回以前的状态。执行结束操作之后,匹配元素的列表将还原为
                ///             匹配元素的最后状态。
                ///             如果前面没有出现过破坏性操作,则将返回一个空集。
                ///             DOM/遍历部分
                ///     </summary>
                ///     <returns type="jQuery" />
 
                return this.prevObject || jQuery(null);
        },
 
        // 仅供内部使用。
        // 行为方式与数组的方法类似,而与 jQuery 方法不类似。
        push: push,
        sort: [].sort,
        splice: [].splice
};
 
// 为 init 函数指定 jQuery 原型以用于以后的实例化
jQuery.fn.init.prototype = jQuery.fn;
 
jQuery.extend = jQuery.fn.extend = function() {
        ///     <summary>
        ///             用一个或多个对象扩展另一个对象,并返回已修改的
        ///             原始对象。这对于简单继承是一个非常有用的实用工具。
        ///             jQuery.extend(settings, options);
        ///             var settings = jQuery.extend({}, defaults, options);
        ///             JavaScript 部分
        ///     </summary>
        ///     <param name="target" type="Object">
        ///              要扩展的对象
        ///     </param>
        ///     <param name="prop1" type="Object">
        ///              将合并到第一个对象的对象。
        ///     </param>
        ///     <param name="propN" type="Object" optional="true" parameterArray="true">
        ///              (可选)要合并到第一个对象的多个对象
        ///     </param>
        ///     <returns type="Object" />
 
        // copy reference to target object
        var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
 
        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
        }
 
        // Handle case when target is a string or something (possible in deep copy)
        if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
                target = {};
        }
 
        // extend jQuery itself if only one argument is passed
        if ( length === i ) {
                target = this;
                --i;
        }
 
        for ( ; i < length; i++ ) {
                // Only deal with non-null/undefined values
                if ( (options = arguments[ i ]) != null ) {
                        // Extend the base object
                        for ( name in options ) {
                                src = target[ name ];
                                copy = options[ name ];
 
                                // Prevent never-ending loop
                                if ( target === copy ) {
                                        continue;
                                }
 
                                // Recurse if we're merging object literal values or arrays
                                if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
                                        var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
                                                : jQuery.isArray(copy) ? [] : {};
 
                                        // Never move original objects, clone them
                                        target[ name ] = jQuery.extend( deep, clone, copy );
 
                                // Don't bring in undefined values
                                } else if ( copy !== undefined ) {
                                        target[ name ] = copy;
                                }
                        }
                }
        }
 
        // Return the modified object
        return target;
};
 
jQuery.extend({
        noConflict: function( deep ) {
                ///     <summary>
                ///             运行此函数以将 $ 变量的控制权交还给
                ///             任何首先实现它的库。这可帮助确保
                ///             jQuery 不会与其他库的 $ 对象
                ///             冲突。
                ///             通过使用此函数,您将只能够使用“jQuery”变量
                ///             来访问 jQuery。例如,在执行
                ///             $("div p") 的位置,您现在必须执行 jQuery("div p")。
                ///             核心部分
                ///     </summary>
                ///     <returns type="undefined" />
 
                window.$ = _$;
 
                if ( deep ) {
                        window.jQuery = _jQuery;
                }
 
                return jQuery;
        },
       
        // 是否准备好使用 DOM? 一旦准备好,请设置为 true。
        isReady: false,
       
        // 当 DOM 就绪时处理
        ready: function() {
                ///     <summary>
                ///             此方法为内部方法。
                ///     </summary>
                ///     <private />
 
                // Make sure that the DOM is not already loaded
                if ( !jQuery.isReady ) {
                        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                        if ( !document.body ) {
                                return setTimeout( jQuery.ready, 13 );
                        }
 
                        // Remember that the DOM is ready
                        jQuery.isReady = true;
 
                        // If there are functions bound, to execute
                        if ( readyList ) {
                                // Execute all of them
                                var fn, i = 0;
                                while ( (fn = readyList[ i++ ]) ) {
                                        fn.call( document, jQuery );
                                }
 
                                // Reset the list of functions
                                readyList = null;
                        }
 
                        // Trigger any bound ready events
                        if ( jQuery.fn.triggerHandler ) {
                                jQuery( document ).triggerHandler( "ready" );
                        }
                }
        },
       
        bindReady: function() {
                if ( readyBound ) {
                        return;
                }
 
                readyBound = true;
 
                // Catch cases where $(document).ready() is called after the
                // browser event has already occurred.
                if ( document.readyState === "complete" ) {
                        return jQuery.ready();
                }
 
                // Mozilla, Opera and webkit nightlies currently support this event
                if ( document.addEventListener ) {
                        // Use the handy event callback
                        document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
                       
                        // A fallback to window.onload, that will always work
                        window.addEventListener( "load", jQuery.ready, false );
 
                // If IE event model is used
                } else if ( document.attachEvent ) {
                        // ensure firing before onload,
                        // maybe late but safe also for iframes
                        document.attachEvent("onreadystatechange", DOMContentLoaded);
                       
                        // A fallback to window.onload, that will always work
                        window.attachEvent( "onload", jQuery.ready );
 
                        // If IE and not a frame
                        // continually check to see if the document is ready
                        var toplevel = false;
 
                        try {
                                toplevel = window.frameElement == null;
                        } catch(e) {}
 
                        if ( document.documentElement.doScroll && toplevel ) {
                                doScrollCheck();
                        }
                }
        },
 
        // See test/unit/core.js for details concerning isFunction.
        // Since version 1.3, DOM methods and functions like alert
        // aren't supported. They return false on IE (#2968).
        isFunction: function( obj ) {
                ///     <summary>
                ///             确定传递的参数是否为函数。
                ///     </summary>
                ///     <param name="obj" type="Object">要检查的对象</param>
                ///     <returns type="Boolean">如果该参数为函数,则为 true;否则为 false。</returns>
 
                return toString.call(obj) === "[object Function]";
        },
 
        isArray: function( obj ) {
                ///     <summary>
                ///             确定传递的参数是否为数组。
                ///     </summary>
                ///     <param name="obj" type="Object">要测试其是否为数组的对象。</param>
                ///     <returns type="Boolean">如果该参数为函数,则为 true;否则为 false。</returns>
 
                return toString.call(obj) === "[object Array]";
        },
 
        isPlainObject: function( obj ) {
                ///     <summary>
                ///             Check to see if an object is a plain object (created using "{}" or "new Object").
                ///     </summary>
                ///     <param name="obj" type="Object">
                ///             将检查其是否为纯对象的对象。
                ///     </param>
                ///     <returns type="Boolean" />
 
                // Must be an Object.
                // Because of IE, we also have to check the presence of the constructor property.
                // Make sure that DOM nodes and window objects don't pass through, as well
                if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
                        return false;
                }
               
                // Not own constructor property must be Object
                if ( obj.constructor
                        && !hasOwnProperty.call(obj, "constructor")
                        && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
                        return false;
                }
               
                // Own properties are enumerated firstly, so to speed up,
                // if last one is own, then all properties are own.
       
                var key;
                for ( key in obj ) {}
               
                return key === undefined || hasOwnProperty.call( obj, key );
        },
 
        isEmptyObject: function( obj ) {
                ///     <summary>
                ///             检查某个对象是否为空(不包含任何属性)。
                ///     </summary>
                ///     <param name="obj" type="Object">
                ///             将检查其是否为空的对象。
                ///     </param>
                ///     <returns type="Boolean" />
 
                for ( var name in obj ) {
                        return false;
                }
                return true;
        },
       
        error: function( msg ) {
                throw msg;
        },
       
        parseJSON: function( data ) {
                if ( typeof data !== "string" || !data ) {
                        return null;
                }
               
                // Make sure the incoming data is actual JSON
                // Logic borrowed from http://json.org/json2.js
                if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
 
                        // Try to use the native JSON parser first
                        return window.JSON && window.JSON.parse ?
                                window.JSON.parse( data ) :
                                (new Function("return " + data))();
 
                } else {
                        jQuery.error( "Invalid JSON: " + data );
                }
        },
 
        noop: function() {
                ///     <summary>
                ///             一个空函数。
                ///     </summary>
                ///     <returns type="Function" />
        },
 
        // 计算全局上下文中的脚本
        globalEval: function( data ) {
                ///     <summary>
                ///             在内部计算全局上下文中的脚本。
                ///     </summary>
                ///     <private />
 
                if ( data && rnotwhite.test(data) ) {
                        // Inspired by code by Andrea Giammarchi
                        // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
                        var head = document.getElementsByTagName("head")[0] || document.documentElement,
                                script = document.createElement("script");
 
                        script.type = "text/javascript";
 
                        if ( jQuery.support.scriptEval ) {
                                script.appendChild( document.createTextNode( data ) );
                        } else {
                                script.text = data;
                        }
 
                        // Use insertBefore instead of appendChild to circumvent an IE6 bug.
                        // This arises when a base node is used (#2709).
                        head.insertBefore( script, head.firstChild );
                        head.removeChild( script );
                }
        },
 
        nodeName: function( elem, name ) {
                ///     <summary>
                ///             检查指定的元素是否具有指定的 DOM 节点名称。
                ///     </summary>
                ///     <param name="elem" type="Element">要检查的元素</param>
                ///     <param name="name" type="String">要检查的节点名称</param>
                ///     <returns type="Boolean">如果指定的节点名称与节点的 DOM 节点名称匹配,则为 true;否则为 false</returns>
 
                return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
        },
 
        // args is for internal usage only
        each: function( object, callback, args ) {
                ///     <summary>
                ///             一个泛型迭代器函数,它可用于无缝地
                ///             循环访问对象和数组。此函数不同于
                ///             $().each(),该函数用于以独占方式循环访问 jQuery
                ///             对象。此函数可用于循环访问任何内容。
                ///             该回调具有两个参数: key (对象)或 index (数组)作为
                ///             第一个参数,value 作为第二个参数。
                ///             JavaScript 部分
                ///     </summary>
                ///     <param name="obj" type="Object">
                ///              要循环访问的对象或数组。
                ///     </param>
                ///     <param name="fn" type="Function">
                ///              将针对每个对象执行的函数。
                ///     </param>
                ///     <returns type="Object" />
 
                var name, i = 0,
                        length = object.length,
                        isObj = length === undefined || jQuery.isFunction(object);
 
                if ( args ) {
                        if ( isObj ) {
                                for ( name in object ) {
                                        if ( callback.apply( object[ name ], args ) === false ) {
                                                break;
                                        }
                                }
                        } else {
                                for ( ; i < length; ) {
                                        if ( callback.apply( object[ i++ ], args ) === false ) {
                                                break;
                                        }
                                }
                        }
 
                // A special, fast, case for the most common use of each
                } else {
                        if ( isObj ) {
                                for ( name in object ) {
                                        if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
                                                break;
                                        }
                                }
                        } else {
                                for ( var value = object[0];
                                        i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
                        }
                }
 
                return object;
        },
 
        trim: function( text ) {
                ///     <summary>
                ///             移除字符串开始和结尾处的空白。
                ///             JavaScript 部分
                ///     </summary>
                ///     <returns type="String" />
                ///     <param name="text" type="String">
                ///             要修整的字符串。
                ///     </param>
 
                return (text || "").replace( rtrim, "" );
        },
 
        // results is for internal usage only
        makeArray: function( array, results ) {
                ///     <summary>
                ///             将任何内容转换为一个真正的数组。这是一个内部方法。
                ///     </summary>
                ///     <param name="array" type="Object">要转换为实际数组的任何内容</param>
                ///     <returns type="Array" />
                ///     <private />
 
                var ret = results || [];
 
                if ( array != null ) {
                        // The window, strings (and functions) also have 'length'
                        // The extra typeof function check is to prevent crashes
                        // in Safari 2 (See: #3039)
                        if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
                                push.call( ret, array );
                        } else {
                                jQuery.merge( ret, array );
                        }
                }
 
                return ret;
        },
 
        inArray: function( elem, array ) {
                if ( array.indexOf ) {
                        return array.indexOf( elem );
                }
 
                for ( var i = 0, length = array.length; i < length; i++ ) {
                        if ( array[ i ] === elem ) {
                                return i;
                        }
                }
 
                return -1;
        },
 
        merge: function( first, second ) {
                ///     <summary>
                ///             将两个数组合并在一起并移除所有重复项。
                ///             新数组是: 第一个数组中的所有结果,
                ///             后跟第二个数组中的唯一结果。
                ///             JavaScript 部分
                ///     </summary>
                ///     <returns type="Array" />
                ///     <param name="first" type="Array">
                ///              要合并的第一个数组。
                ///     </param>
                ///     <param name="second" type="Array">
                ///              要合并的第二个数组。
                ///     </param>
 
                var i = first.length, j = 0;
 
                if ( typeof second.length === "number" ) {
                        for ( var l = second.length; j < l; j++ ) {
                                first[ i++ ] = second[ j ];
                        }
                } else {
                        while ( second[j] !== undefined ) {
                                first[ i++ ] = second[ j++ ];
                        }
                }
 
                first.length = i;
 
                return first;
        },
 
        grep: function( elems, callback, inv ) {
                ///     <summary>
                ///             使用筛选器函数从数组中筛选出项。
                ///             将向指定的函数传递两个参数:
                ///             当前数组项和该项在数组中的索引。
                ///             该函数必须返回“true”以将该项保留在数组中,
                ///             若返回 false 则将移除该项。
                ///             });
                ///             JavaScript 部分
                ///     </summary>
                ///     <returns type="Array" />
                ///     <param name="elems" type="Array">
                ///             array 要在其中查找项的数组。
                ///     </param>
                ///     <param name="fn" type="Function">
                ///              要用于处理每一项的函数。
                ///     </param>
                ///     <param name="inv" type="Boolean">
                ///              反转选择 - 选择函数的反函数。
                ///     </param>
 
                var ret = [];
 
                // Go through the array, only saving the items
                // that pass the validator function
                for ( var i = 0, length = elems.length; i < length; i++ ) {
                        if ( !inv !== !callback( elems[ i ], i ) ) {
                                ret.push( elems[ i ] );
                        }
                }
 
                return ret;
        },
 
        // arg is for internal usage only
        map: function( elems, callback, arg ) {
                ///     <summary>
                ///             将一个数组中的所有项转换为另一个项数组。
                ///             针对数组中每一项调用提供给此方法的转换函数,
                ///             并向该函数传递一个参数:
                ///             要转换的项。
                ///             然后,该函数可以返回转换后的值、“null”
                ///             (以移除相应项)或值数组 - 这些数据将
                ///             会修整到完整的数组中。
                ///             JavaScript 部分
                ///     </summary>
                ///     <returns type="Array" />
                ///     <param name="elems" type="Array">
                ///             array 要转换的数组。
                ///     </param>
                ///     <param name="fn" type="Function">
                ///              要用于处理每一项的函数。
                ///     </param>
 
                var ret = [], value;
 
                // 遍历数组,并将每个项转换为
                // 一个或多个新值。
                for ( var i = 0, length = elems.length; i < length; i++ ) {
                        value = callback( elems[ i ], i, arg );
 
                        if ( value != null ) {
                                ret[ ret.length ] = value;
                        }
                }
 
                return ret.concat.apply( [], ret );
        },
 
        // 用于对象的全局 GUID 计数器
        guid: 1,
 
        proxy: function( fn, proxy, thisObject ) {
                ///     <summary>
                ///             采用一个函数,并返回一个将始终具有特定范围的新函数。
                ///     </summary>
                ///     <param name="fn" type="Function">
                ///                                         

热门排行

今日推荐

热门手游