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


How to make second autocomplete options dependent on first autocomplete selection using jQuery?

我有一个带有文本输入和选择选项框的表单。文本字段使用自动建议,允许用户从列表中选择选项。一旦从自动建议中选择了一个值,选择选项框就会填充依赖于选择的选项。

我正在努力改变代码,使第二个框是一个文本输入,以及,以免限制用户的选择(即两个字段应该允许自由文本条目,如果用户不想从可用的选择中进行选择)。

我想我已经盯着这段代码太久了,希望能得到一些帮助。显然,需要在loadCountry, populateSelectloadcountrySelect功能中进行更改。

我使用PHP, jQuery和jQuery UI自动完成。

如果您能提供任何帮助,我将非常感激!

脚本:

<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.';
    }
}
?>

您将需要修改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);
            }
        });
    }
});

只是为了一些润色,当#continent_autocomplete改变时,你可能想要清除#country_autocomplete。您可以为自动完成的change事件添加一个事件处理程序:

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

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

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

autocomplete.php (agly style,整个逻辑放在一个地方——只是为了展示原理)

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);
                })
        }],  
    });
});
相关文章: