如何使用jQuery创建第二个自动完成选项依赖于第一个自动完成选择?

时间:2011-11-16 03:14:20

标签: php jquery jquery-ui dependencies jquery-ui-autocomplete

我有一个带有文本输入和选择选项框的表单。文本字段使用自动提示来允许用户从列表中选择选项。从autosuggest中选择一个值后,将使用取决于所选内容的选项填充选择选项框。

我正在努力更改代码,以便第二个框也是文本输入,以便不限制用户选择(即,如果用户不想从中选择,则两个字段都应允许自由文本条目可供选择)。

我想我已经盯着这段代码太久了,并且会喜欢一些帮助。显然,更改需要包含在loadCountrypopulateSelectloadcountrySelect函数中。

我正在使用PHP,jQuery和jQuery UI Autocomplete

非常感谢您提供的任何帮助!

脚本:

<script src="../../scripts/jquery-1.6.4.js"></script>
<script src="../../scripts/jqueryui/ui/jquery.ui.core.js"></script>
<script src="../../scripts/jquery.ui.widget.js"></script>
<script src="../../scripts/jquery.ui.position.js"></script>
<script src="../../scripts/jquery.ui.autocomplete.js"></script>
<script type="text/javascript">

$(document).ready(function() {

    function ord(chr) {

        return chr.charCodeAt(0);

    }

    function chr(num) {

        return  String.fromCharCode(num);

    }

    function quote(str) {

        return '"' + escape(str.replace('"', "'")) + '"';

    }

    String.prototype.titleCase = function () {

        var chars = [" ", "-"];
        var ths = String(this).toLowerCase();

        for (j in chars){

            var car = chars[j];
            var str = "";
            var words = ths.split(car);
            for(i in words){

                str += car + words[i].substr(0,1).toUpperCase() + words[i].substr(1);

            }

            ths = str.substr(1);

        }

        return ths;

    }

    function incrementTerm(term) {

        for (var i = term.length - 1; i >= 0; i--){

            var code = term.charCodeAt(i);

            if (code < ord('Z'))

                return term.substring(0, i) + chr(code + 1);

        }

        return '{}'

    }

    function parseLineSeperated(data){

        data = data.split("\n");

        data.pop(); // Trim blank element after ending newline

        var out = []

        for (i in data){

            out.push(data[i].titleCase());

        }

        return out;

    }

    function guess(value){

        var oldValue = $('.continent_autocomplete').val();

        if (oldValue == value)

            return;

        $('.continent_autocomplete').val(value);

        $('.continent_autocomplete').caret(oldValue.length, value.length);

    }

    function clearGuess(){

        var field = $('.continent_autocomplete');

        field.val(field.val().substring(0, field.caret().start));

    }

    function loadcontinent(request, response) {

        var startTerm = request.term.toUpperCase();

        var endTerm = incrementTerm(startTerm);

        $.ajax({

            url: '/db/continent.php?startkey='+startTerm+'&endkey='+endTerm,

            success: function(data) {

                var items = parseLineSeperated(data);

                response(items);

            },

            error: function(req, str, exc) {

                alert(str);

            }

            });

    }

    function loadcountry(handler) {

        var continent = $('.continent_autocomplete').val().toUpperCase();


        $.ajax({

            url: '/db/country.php?key=' + continent,

            success: function(data) {

                handler(parseLineSeperated(data));

            },

            error: function(req, str, exc) {

                alert(str);

            }

            });

    }

    function populateSelect(select, options) {

        select.html('');

        if (options.length) {

            enableSelect();

            for (i in options){

                var option = options[i];

                select.append($('<option></option>').val(option).html(option));

            }

        } else {

            disableSelect('Country');

        }

    }

    function loadcountrySelect(continentObj){

        disableSelect('Loading...');

        loadcountry(function(options){

            populateSelect($('.country_autocomplete'), options);

        });

    }

    function disableSelect(message){

        var select = $('.country_autocomplete');

        select.html("<option>" + message + "</option>");

        select.attr('disabled', true);

    }

    function enableSelect(){

        var select = $('.country_autocomplete');

        select.attr('disabled', false);

    }

    populateSelect($(".country_autocomplete"), []);

    $("input.continent_autocomplete").autocomplete({

        source: loadcontinent,

        select: function(event, ui){

            $("input.continent_autocomplete").val(ui.item.value);

            loadcountrySelect(event.target);

        }

    });


    $("input.continent_autocomplete").keyup(function (event){

        var code = (event.keyCode ? event.keyCode : event.which);

        if (code == 8) { // Backspace

            clearGuess();

        }

        event.target.value = event.target.value.titleCase();

        loadcountrySelect(event.target);

    });
});

</script>

HTML:

<div id="continent_name">
    <label> Continent Name:</label>
    <input type="text" id="continent_name" name="continent_name" class="continent_autocomplete" />
</div>
<div id="country">
    <label> Country:</label>
    <input type="text" id="country_autocomplete" name="country_autocomplete" class="country_autocomplete" />
</div>

continent.php

<?php

$db_host        = 'XXX';
$db_user        = 'XXX';
$db_password    = 'XXX';
$db_name        = 'XXX';

$db = new mysqli($db_host , $db_user ,$db_password, $db_name);

if(!$db) {

    echo 'There was a problem connecting to the database';
} else {

    if(isset($_GET['startkey'])) {
        $mysearchString = $db->real_escape_string($_GET['startkey']);


        if(strlen($mysearchString) >0) {


            $query = $db->query("SELECT DISTINCTROW Continent 
                                FROM locations 
                                WHERE Continent 
                                LIKE '$mysearchString%' 
                                LIMIT 10"); 

            if($query) {

                while ($result = $query ->fetch_object()) {

                        print ucwords(strtolower($result->Continent))."\n";
                }

            } else {

                echo 'ERROR: There was a problem with the query.';
            }

        } else {

        } 

    } else {

        echo 'Access denied.';
    }
}
?>

country.php

<?php
$db_host        = 'XXX';
$db_user        = 'XXX';
$db_password    = 'XXX';
$db_name        = 'XXX';

$db = new mysqli($db_host , $db_user ,$db_password, $db_name);

if(!$db) {

    echo 'There was a problem connecting to the database';

} else {

    if(isset($_GET['key'])) {

        $mysearchString = $db->real_escape_string($_GET['key']);

        if(strlen($mysearchString) >0) {

            $query = $db->query("SELECT Continent,Country,Abbrev 
                                 FROM locations 
                                 WHERE Continent 
                                 LIKE '$mysearchString%' 
                                 ORDER BY Country
                                 LIMIT 20");    

            if($query) {

                while ($result = $query ->fetch_object()) {

                    print ucwords(strtolower($result->Country))."/".
                          ucwords(strtolower(strtok($result->Abbrev,";")))."\n";

                }

            } else {

                echo 'ERROR: There was a problem with the query.';

            }

        } else {

        } 

    } else {

        echo 'Access denied.';

    }

}
?>

2 个答案:

答案 0 :(得分:0)

您需要修改PHP以使其最佳地工作(在服务器上进行过滤)。我会更新你的PHP,以便它用两个参数查询你的数据库(一个用于国家,一个用于大陆):

$continent = $db->real_escape_string($_GET['continent']);
$country = $db->real_escape_string($_GET['country']);

$query = $db->query("SELECT Continent,Country,Abbrev 
    FROM locations 
    WHERE Continent ='$continent' and Country like '$country%'
    ORDER BY Country
    LIMIT 20"); 

(请带上一粒盐;我不懂PHP)

基本上,通过一个大陆(在第一个input中选择国家搜索字符串(在第二个输入中键入)。

接下来,您需要将自动填充小部件应用于第二个input。类似的东西:

$("#country_autocomplete").autocomplete({
    source: function (request, response) {
        var continent = $("#continent_autocomplete").val()
            , country = request.term;

        $.ajax({
            url: '/db/country.php?continent=' + continent + "&country=" + country,
            success: function(data) {
                response(parseLineSeperated(data));
            },
            error: function(req, str, exc) {
                alert(str);
            }
        });
    }
});

为了进行一些改进,您可能希望在#country_autocomplete更改时清除#continent_autocomplete。您可以通过为自动填充change事件添加事件处理程序来完成此操作:

$("input.continent_autocomplete").autocomplete({
    source: loadcontinent,
    change: function () {
        $("#country_autocomplete).val('');
    }
});

最后,您要删除与填写国家/地区select有关的任何代码,因为您不再需要它。

答案 1 :(得分:0)

jQuery插件Autocomplete like Google支持这样的功能:

autocomplete.php (格调风格,整个逻辑在一个地方 - 只是为了显示原理)

if(!empty($_GET['foo_name']) && !empty($_GET['bar_number'])) {
    $sql = 'SELECT ... FROM ... WHERE';
    $db = new MySQLi(...);
    $db->query($sql);
    $numbers = [];
    while($row = $result->fetch_assoc()){
        $numbers[] = $row['bar_number'];
    }
}
echo json_encode($numbers);

<强> autocomplete.html

<link href="/components/autocompletelikegoogle/jquery.autocomplete.css" media="screen" rel="stylesheet" type="text/css">
<script type="text/javascript" src="/components/autocompletelikegoogle/jquery.autocomplete.js"></script>
<script type="text/javascript" src="/js/autocomplete.js"></script>

<input type="text" name="foo_name" id="foo-name" value="">
<input type="text" name="bar_number" id="bar-number" value="">

<强> autocomplete.js

$(function() {
    $("#foo").autocomplete({
        minLength: 3,
        limit: 5,
        source : [{
            url:"/my/ajax/controller/foo?data[foo_name]=%QUERY%",
            type:'remote'
        }],  
    });
});

$(function() {
    $("#bar").autocomplete({
        minLength: 3,
        limit: 5,
        appendMethod:'replace',
        source : [
            function(query, add) {
                fooName = $('#foo-name').val();
                $.getJSON("/my/ajax/controller/bar?data[bar_number]=" + query + "&data[foo_name]=" + fooName, function(response) {
                    add(response);
                })
        }],  
    });
});