自动完成如何避免重复选择

autocomplete How to avoid duplicate selection

我正在使用 JQuery 自动完成功能。我想避免重复选择预选和预定位(预取)列表。

以下脚本适用于当前选定的列表。但是我怎么能用 document onload.

获取的预定位列表呢?

/////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// //////

JS

$(document).on('focus','.search',function(){
let type = $(this).data('type');

$(this).autocomplete({
    source: function( request, response ) {
        $.ajax({
            url : 'autocomplete.php',
            dataType: "json",
            method: 'post',
            data: {
               name_startsWith: request.term,
               type: type
            },
            success: function( data ) {
            let selected = [],
               uniques = [],
               choices = [];

            $('tr .search[id^="name_"]').each(function(){
             let value = this.value.trim().toLowerCase();
             if (value && selected.indexOf(value) < 0) {
               selected.push(value);
             }
           });

           data.forEach(item => {
             let value = item.name.trim().toLowerCase();

             if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
               choices.push({
                 label: item.name,
                 value: item.name,
                 data: item,
                 type: 'name'
               });
               uniques.push(value);
             }

           });

           response(choices);
        }
    });
},
autoFocus: true,
minLength: 1,
select: function( event, ui ) {
    // Strips the 'team_' part, leaving just the number.
    let id_num = $(this).attr('id').substring(5);

    $(this).val(ui.item.value);
    $('#id_' + id_num).val(ui.item.data.id).change();
    $('#marks_' + id_num).val(ui.item.data.marks);
    $(this).attr('data-type', ui.item.type); 
    return false;
},
appendTo: $(this).parent()
});
});    

HTML

<table class="table table-bordered table-hover" id="pat_tests">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Name</th>
                                    <th>Marks</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td> <input type="number" id="id_1"> </td>
                                    <td><input type="text" id="name_1" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_1" ></td>
                                </tr>
                                <tr>
                                    <td> <input type="number" id="id_2"> </td>
                                    <td><input type="text" id="name_2" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_2" ></td>
                                </tr>
                                <tr>
                                    <td> <input type="number" id="id_3"> </td>
                                    <td><input type="text" id="name_3" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_3" ></td>
                                </tr>
                            </tbody>
                        </table>

                        <h2>Pre Selected List of Students</h2>
                        <p class="selected">Mario</p>
                        <p class="selected">Nico"</p>
                        <p class="selected">Mento</p>

PHP

if(!empty($_POST['type'])){
$type = $_POST['type'];
$name = $_POST['name_startsWith'];
$query = $db->prepare("SELECT id, name, marks FROM class where (name LIKE '".$name."%') ");
$query->execute();
$data = array();

$i = 0;
while ($row = $query->fetch(PDO:: FETCH_ASSOC)) {

    $data[$i]['id'] = $row['id'];
    $data[$i]['name'] = $row['name'];
    $data[$i]['marks'] = $row['marks'];
++$i;
}  
echo json_encode($data);

更新后的答案: 因为您更改了 HTML 解决方案可能基于:

if ($('.selected:contains(' + value + ')').length == 0) {

更新后的代码段:

$(document).on('focus', '.search', function (e) {
    let type = $(this).data('type');
    $(this).autocomplete({
        source: function (request, response) {
            $.ajax({
                url: 'https://api.github.com/repositories?since=364',
                dataType: "json",
                method: 'get',
                data: {
                    name_startsWith: request.term,
                    type: type
                },
                success: function (data) {
                    data = data.map((a) => ({name: a.name || ''})).filter((e) => e.name.indexOf('_') == -1);
                    let selected = [],
                            uniques = [],
                            choices = [];
                    $('tr .search[id^="name_"]').each(function () {
                        let value = this.value.trim().toLowerCase();
                        if (value && selected.indexOf(value) < 0) {
                            selected.push(value);
                        }
                    });
                    data.forEach(function (item) {
                        let value = item.name.trim().toLowerCase();
                        if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                            if ($('.selected:contains(' + value + ')').length == 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        }
                    });
                    response(choices);
                }
            });
        },
        autoFocus: true,
        minLength: 1,
        select: function (event, ui) {
            // Strips the 'team_' part, leaving just the number.
            let id_num = $(this).attr('id').substring(5);
            $(this).val(ui.item.value);
            $('#id_' + id_num).val(ui.item.data.id).change();
            $('#marks_' + id_num).val(ui.item.data.marks);
            $(this).attr('data-type', ui.item.type);
            return false;
        },
        appendTo: $(this).parent()
    });
});
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>

<table class="table table-bordered table-hover" id="pat_tests">
    <thead>
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Marks</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td> <input type="number" id="id_1"> </td>
        <td><input type="text" id="name_1" class="search" data-type="type"></td>
        <td><input type="number" id="marks_1" ></td>
    </tr>
    <tr>
        <td> <input type="number" id="id_2"> </td>
        <td><input type="text" id="name_2" class="search" data-type="type"></td>
        <td><input type="number" id="marks_2" ></td>
    </tr>
    <tr>
        <td> <input type="number" id="id_3"> </td>
        <td><input type="text" id="name_3" class="search" data-type="type"></td>
        <td><input type="number" id="marks_3" ></td>
    </tr>
    </tbody>
</table>

<h2>Pre Selected List of Students</h2>
<p class="selected">invisible</p>
<p class="selected">tinder</p>
<p class="selected">ike</p>

尝试select tinder,仅供测试。

旧答案:

第一个问题:在每个焦点事件上初始化自动完成!请避免多次初始化。

如果我没理解错的话,您想从自动完成列表中删除具有已包含在预选学生列表之一中的值的元素。 如果是这样,您可以在 choices.push({ 之前添加一个测试:

if ($('.selected:text[value="' + item.name + '"]').length == 0) {

完整代码:

$(document).on('focus', '.search', function (e) {
    let type = $(this).data('type');
    $(this).autocomplete({
        source: function (request, response) {
            $.ajax({
                url: 'your url',
                dataType: "json",
                method: 'post',
                data: {
                    name_startsWith: request.term,
                    type: type
                },
                success: function (data) {
                    let selected = [],
                            uniques = [],
                            choices = [];
                    $('tr .search[id^="name_"]').each(function () {
                        let value = this.value.trim().toLowerCase();
                        if (value && selected.indexOf(value) < 0) {
                            selected.push(value);
                        }
                    });
                    data.forEach(function (item) {
                        let value = item.name.trim().toLowerCase();
                        if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                            if ($('.selected:text[value="' + item.name + '"]').length == 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        }
                    });
                    response(choices);
                }
            });
        },
        autoFocus: true,
        minLength: 1,
        select: function (event, ui) {
            // Strips the 'team_' part, leaving just the number.
            let id_num = $(this).attr('id').substring(5);
            $(this).val(ui.item.value);
            $('#id_' + id_num).val(ui.item.data.id).change();
            $('#marks_' + id_num).val(ui.item.data.marks);
            $(this).attr('data-type', ui.item.type);
            return false;
        },
        appendTo: $(this).parent()
    });
});

我推荐在Js中使用数组,可以把preselected放在里面。然后用它来验证如果没有选择已经推入它然后你可以添加到你的 dom。

所以在 js 中你会得到类似

的东西
var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];

以上脚本第一行中的代码使数组为空或已选中(如果选中的不为空) 然后你可以用它来检查一个项目是否被选中。最好在 php 之前使用 $selected = array_map('strtolower', $selected); (根据您的代码)

编辑

<script type="text/javascript">

    //in case you have php array of already selected items. remove it if $selected is not provided in php.
    //var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];

    var selected = []; 
    $(".selected").each(function(index, value){ 
        selected.push($(this).text().trim().toLowerCase()); 
    });

    $(document).on('focus', '.search', function (e) {
        let type = $(this).data('type');
        $(this).autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: 'your url',
                    dataType: "json",
                    method: 'post',
                    data: {
                        name_startsWith: request.term,
                        type: type
                    },
                    success: function (data) {
                        let uniques = [],
                            choices = [];
                        data.forEach(function (item) {
                            let value = item.name.trim().toLowerCase();
                            if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        });
                        response(choices);
                    }
                });
            },
            autoFocus: true,
            minLength: 1,
            select: function (event, ui) {
                // Strips the 'team_' part, leaving just the number.
                let id_num = $(this).attr('id').substring(5);
                $(this).val(ui.item.value);
                $('#id_' + id_num).val(ui.item.data.id).change();
                $('#marks_' + id_num).val(ui.item.data.marks);
                $(this).attr('data-type', ui.item.type);
                selected.push(ui.item.value.trim().toLowerCase());
                return false;
            },
            appendTo: $(this).parent()
        });
    });
</script>

如果您将 js 作为外部文件加载,请不要担心。只要确保定义

<script>
    var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];
</script>

之前。