пример загрузки с Twitter

280

Я пытаюсь найти рабочий пример элемента начальной загрузки twitter, который будет вызывать ajax, чтобы заполнить его выпадающий список.

У меня есть работающий пример автозаполнения JQuery, который определяет URL-адрес ajax и как обработать ответ

<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
    var options = { minChars:3, max:20 };
    $("#runnerquery").autocomplete('./index/runnerfilter/format/html',options).result(
            function(event, data, formatted)
                {
                    window.location = "./runner/index/id/"+data[1];
                }
            );
       ..

Что мне нужно изменить, чтобы преобразовать это в пример typeahead?

<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
    var options = { source:'/index/runnerfilter/format/html', items:5 };
    $("#runnerquery").typeahead(options).result(
            function(event, data, formatted)
                {
                    window.location = "./runner/index/id/"+data[1];
                }
            );
       ..

Я собираюсь дождаться решения проблемы « Добавление поддержки удаленных источников для typeahead ».

emeraldjava
источник
Чтобы быть более конкретным, мне интересно, как параметры автозаполнения и функции обработки результатов отображаются на параметры textahead? Существует ли определенный набор функций обработки результатов текстовых уведомлений, которые можно переопределить, или метод с именем унаследован от базового API jquery.
изумруджава
1
Не могли бы вы отметить ответ Стейна Ван Баэля как правильный? Ответ Богерта работает только для устаревших версий Bootstrap.
Джайлс Робертс

Ответы:

302

Изменить: typeahead больше не входит в Bootstrap 3. Проверьте:

Начиная с Bootstrap 2.1.0 до 2.3.2, вы можете сделать это:

$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('/typeahead', { query: query }, function (data) {
            return process(data.options);
        });
    }
});

Чтобы использовать данные в формате JSON следующим образом:

{
    "options": [
        "Option 1",
        "Option 2",
        "Option 3",
        "Option 4",
        "Option 5"
    ]
}

Обратите внимание, что данные JSON должны иметь правильный тип MIME (application / json), поэтому jQuery распознает их как JSON.

Стейн Ван Баел
источник
3
Как и в форке Typeahead, данные должны быть массивом строк JSON, а тип контента должен быть application / json.
Стейн Ван Баел
9
2.1 может использовать json, который не является просто массивом строк? Мне нужно, чтобы значение для пользователя и использовать идентификатор для дальнейшей обработки. Это возможно без подбора кастомной вилки?
Антон
2
@Stijin Есть ли примеры того, как эта анонимная функция будет использоваться здесь для обработки идентификатора для отображаемой опции? Спасибо!
Acyra
1
Я хотел бы отметить, что использование этого метода приводит к тому, что AJAX вызывается для каждого нажатия клавиши на входе. Если сервер возвращает по существу статические данные (т.е. ничего не делает с запросом), то это может быть довольно расточительным.
Дологан,
2
зачем использовать getвместо getJSON? Это кажется более подходящим.
greg0ire
119

Вы можете использовать форк BS Typeahead, который поддерживает вызовы ajax. Тогда вы сможете написать:

$('.typeahead').typeahead({
    source: function (typeahead, query) {
        return $.get('/typeahead', { query: query }, function (data) {
            return typeahead.process(data);
        });
    }
});
Bogert
источник
1
«Умное предположение» jQuery для типа возврата данных POST не работало, например, когда я вернулся ["aardvark", "apple"]. Я должен был явно установить dataTypeпараметр в $.postвызове. Смотрите jQuery.post () .
Расти Фаусак
1
@rfausak В качестве альтернативы, установите Content-typeзаголовокapplication/json
Rusty Fausak
23
я получаю Uncaught TypeError: Невозможно вызвать метод 'toLowerCase' из неопределенного
Кришнапрасад Варма
В отправленной вами ссылке я даже не получаю sourceфункцию для выполнения.
Джеймс
8
Хороший ответ! Я бы использовал запрос GET вместо этого, просто чтобы соответствовать стандартам REST.
Мауро
72

Начиная с Bootstrap 2.1.0:

HTML:

<input type='text' class='ajax-typeahead' data-link='your-json-link' />

Javascript:

$('.ajax-typeahead').typeahead({
    source: function(query, process) {
        return $.ajax({
            url: $(this)[0].$element[0].dataset.link,
            type: 'get',
            data: {query: query},
            dataType: 'json',
            success: function(json) {
                return typeof json.options == 'undefined' ? false : process(json.options);
            }
        });
    }
});

Теперь вы можете создать единый код, разместив ссылки «json-request» в своем HTML-коде.

Thantifaxath
источник
11
Но я бы поменял его на использование $(this)[0].$element.data('link').
Эндрю Эллис
илиthis.$element.data('link')
Ричард87
51

Все ответы относятся к типу BootStrap 2, которого больше нет в BootStrap 3.

Для всех, кто направил сюда, ищет пример AJAX, используя новый пост-Bootstrap Twitter typeahead.js , вот рабочий пример. Синтаксис немного отличается:

$('#mytextquery').typeahead({
  hint: true,
  highlight: true,
  minLength: 1
},
{
  limit: 12,
  async: true,
  source: function (query, processSync, processAsync) {
    processSync(['This suggestion appears immediately', 'This one too']);
    return $.ajax({
      url: "/ajax/myfilter.php", 
      type: 'GET',
      data: {query: query},
      dataType: 'json',
      success: function (json) {
        // in this example, json is simply an array of strings
        return processAsync(json);
      }
    });
  }
});

В этом примере используются синхронные (вызов processSync ) и асинхронные предложения, поэтому вы увидите, что некоторые параметры появляются сразу, а затем добавляются другие. Вы можете просто использовать один или другой.

Существует множество привязываемых событий и несколько очень мощных опций, в том числе работа с объектами, а не со строками, и в этом случае вы будете использовать собственную настраиваемую функцию отображения для отображения ваших элементов в виде текста.

Джонатан Лидбек
источник
1
Спасибо. Еще один вопрос: с processAsync я получаю «TypeError: ideas.slice не является функцией». Как должен выглядеть возвращаемый JSON? Вот мое лучшее предположение: {: ideas => ["Вещь 1", "Вещь 2", "Вещь 3"]}
user1515295
1
Убедитесь, что вы возвращаете правильную строку JSON. Ваша функция предложения AJAX должна возвращать массив строк, например ["Thing 1","Thing 2"], или с пользовательской функцией отображения, массив объектов в соответствии с вашими потребностями, например,[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Джонатан Лидбек
Я возвращаюсь [{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}], Теперь я хочу показать два столбца в раскрывающемся списке typeahead с идентификатором и меткой. Как я могу это сделать?
Вишал
2
О ГОСПОДИ!!! Я искал последние 3 дня, никто не упомянул об этом. Я тестировал с функцией синхронизации до сих пор. СПАСИБО ПРИЯТЕЛЬ!!
Гилсон Пи Джей
Спасибо ! Отлично работает с начальной загрузкой 4.3 и jquery 3.4. Но перечисленные параметры не выделяются, когда на них наведена мышь. Я думал, что это должно быть частью самого typeahead.
Бинита Бхарати
25

Я дополнил оригинальный плагин Bootstrap typeahead возможностями ajax. Очень прост в использовании:

$("#ajax-typeahead").typeahead({
     ajax: "/path/to/source"
});

Вот репозиторий Github : Ajax-Typeahead

Пол Варелис
источник
Я посмотрел на код Гудбергур; честно говоря, мне больше всего понравился этот. Это немного более дружелюбно и предлагает больше функциональности. Хорошая работа, Пол! Единственное, что я хотел бы предложить, это в вашем README напомнить пользователю, что ему нужно проанализировать свои JSON-данные в JS, чтобы ваш код мог правильно их использовать. Я предполагал, что вы разбираете это для меня, так что повесил меня немного. В остальном, довольно мило, спасибо! :)
Бэйн
3
Ваш сервер возвращает строку вместо объекта JSON. $ .ajax () jQuery используется для выполнения вызова, и он заботится о разборе.
Пол Warelis
1
абсолютно правильно, спасибо за улов! :) Этот плагин работает очень хорошо.
Бэйн
Привет, как должна JSONвыглядеть сторона сервера ? Я получаю Uncaught TypeError: Cannot read property 'length' of undefined . Я использую json_encode($array)и отправляю правильные заголовки ( 'Content-Type: application/json; charset=utf-8'). JQuery версияjQuery v1.9.1
Kyslik
5

Я сделал некоторые изменения в jquery-ui.min.js:

//Line 319 ORIG:
this.menu=d("<ul></ul>").addClass("ui-autocomplete").appendTo(d(...
// NEW:
this.menu=d("<ul></ul>").addClass("ui-autocomplete").addClass("typeahead").addClass("dropdown-menu").appendTo(d(...

// Line 328 ORIG:
this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr...
// NEW:this.element.attr....

// Line 329 ORIG:
this.active=a.eq(0).children("a")
this.active.children("a")
// NEW:
this.active=a.eq(0).addClass("active").children("a")
this.active.removeClass("active").children("a")`

и добавить следующий CSS

.dropdown-menu {
    max-width: 920px;
}
.ui-menu-item {
    cursor: pointer;        
}

Работает отлично.

bmoers
источник
какую версию jquery ui min вы используете?
изумруджава
Если вам это нужно для jQuery 1.7.1 и jQuery UI 1.8.16, то я создал GIST на основе вышеуказанного исправления, в котором показано, где изменить файл jQuery UI. gist.github.com/1884819 - строки комментируются // изменено
Ричард Холлис
Это довольно старый вопрос / ответ, но я просто хочу сказать, что изменение кода сторонних компонентов всегда плохая практика. Вам придется пересматривать все изменения каждый раз, когда вы обновляете их. В этом конкретном случае виджеты jQuery могут быть унаследованы, что является гораздо более безопасным способом их настройки. В общем, создайте свой собственный виджет, унаследуйте его от основного (в данном случае автозаполнение) и раскройте свое воображение! :)
AlexCode
3

Я использую этот метод

$('.typeahead').typeahead({
    hint: true,
    highlight: true,
    minLength: 1
},
    {
    name: 'options',
    displayKey: 'value',
    source: function (query, process) {
        return $.get('/weather/searchCity/?q=%QUERY', { query: query }, function (data) {
            var matches = [];
            $.each(data, function(i, str) {
                matches.push({ value: str });
            });
            return process(matches);

        },'json');
    }
});
Krava
источник
Было бы неплохо, если бы вы могли добавить какое-то объяснение к вашему ответу. Например, в чем отличие вашего решения от решений, представленных в уже существующих ответах?
Хонк
2

Можно делать звонки с помощью Bootstrap. В текущей версии нет проблем с обновлением исходного кода. Проблема с обновлением источника данных начальной загрузки Bootstrap с последующим ответом , то есть источник загрузочного обновления после обновления может быть снова изменен.

Пожалуйста, обратитесь к примеру ниже:

jQuery('#help').typeahead({
    source : function(query, process) {
        jQuery.ajax({
            url : "urltobefetched",
            type : 'GET',
            data : {
                "query" : query
            },
            dataType : 'json',
            success : function(json) {
                process(json);
            }
        });
    },
    minLength : 1,
});
neoeahit
источник
2

Для тех, кто ищет кофейную версию принятого ответа:

$(".typeahead").typeahead source: (query, process) ->
  $.get "/typeahead",
    query: query
  , (data) ->
    process data.options
Хендрик
источник
2

Я просмотрел этот пост, и все не хотело работать правильно, и в итоге собрал воедино кусочки из нескольких ответов, так что у меня есть 100% работающая демоверсия, и я вставлю ее сюда для справки - вставьте ее в файл php и убедитесь, что файлы включены в правильное место.

<?php if (isset($_GET['typeahead'])){
    die(json_encode(array('options' => array('like','spike','dike','ikelalcdass'))));
}
?>
<link href="bootstrap.css" rel="stylesheet">
<input type="text" class='typeahead'>
<script src="jquery-1.10.2.js"></script>
<script src="bootstrap.min.js"></script>
<script>
$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('index.php?typeahead', { query: query }, function (data) {
            return process(JSON.parse(data).options);
        });
    }
});
</script>
l0ft13
источник
2

Попробуйте это, если ваш сервис не возвращает правильный заголовок типа контента application / json:

$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('/typeahead', { query: query }, function (data) {
            var json = JSON.parse(data); // string to json
            return process(json.options);
        });
    }
});
Andres
источник
1

ОБНОВЛЕНИЕ: я изменил свой код с помощью этого форка

также вместо использования $ .each я изменил на $ .map, как это было предложено Томиславом Марковским

$('#manufacturer').typeahead({
    source: function(typeahead, query){
        $.ajax({
            url: window.location.origin+"/bows/get_manufacturers.json",
            type: "POST",
            data: "",
            dataType: "JSON",
            async: false,
            success: function(results){
                var manufacturers = new Array;
                $.map(results.data.manufacturers, function(data, item){
                    var group;
                    group = {
                        manufacturer_id: data.Manufacturer.id,
                        manufacturer: data.Manufacturer.manufacturer
                    };
                    manufacturers.push(group);
                });
                typeahead.process(manufacturers);
            }
        });
    },
    property: 'name',
    items:11,
    onselect: function (obj) {

    }
});

Однако я сталкиваюсь с некоторыми проблемами, получая

Uncaught TypeError: Невозможно вызвать метод 'toLowerCase' из неопределенного

как вы можете видеть на более новом посте, я пытаюсь выяснить здесь

надеюсь, что это обновление поможет вам ...

mmoscosa
источник
Не имеет отношения к OP: я бы использовал Array.mapвместо этого $.eachи заменил бы содержимое всей вашей successфункции обратного вызова наvar manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
Tomislav Markovski
спасибо @TomislavMarkovski Я изменил свой код, как вы предлагаете.
mmoscosa
0

У меня нет рабочего примера для вас, и у меня нет очень чистого решения, но позвольте мне рассказать вам, что я нашел.

Если вы посмотрите на код JavaScript для TypeAhead, он будет выглядеть так:

items = $.grep(this.source, function (item) {
    if (that.matcher(item)) return item
  })

Этот код использует метод "grep" jQuery для сопоставления элемента в исходном массиве. Я не видел ни одного места, где вы могли бы подключить вызов AJAX, поэтому нет «чистого» решения для этого.

Тем не менее, один довольно хакерский способ сделать это - воспользоваться преимуществами метода grep в jQuery. Первым аргументом grep является исходный массив, а вторым аргументом является функция, которая используется для сопоставления исходного массива (обратите внимание, что Bootstrap вызывает «совпадение», которое вы указали при его инициализации). То, что вы можете сделать, это установить источник в фиктивный одноэлементный массив и определить совпадение как функцию с вызовом AJAX. Таким образом, он будет запускать вызов AJAX только один раз (поскольку ваш исходный массив содержит только один элемент).

Это решение не только хакерское, но и будет страдать от проблем с производительностью, поскольку код TypeAhead предназначен для поиска при каждом нажатии клавиши (вызовы AJAX действительно должны происходить только после нескольких нажатий клавиш или после определенного количества времени простоя). Я советую попробовать, но придерживайтесь другой библиотеки автозаполнения или используйте ее только для ситуаций без AJAX, если у вас возникнут какие-либо проблемы.

Аамер Аббас
источник
0

при использовании ajax, попробуйте $.getJSON()вместо, $.get()если у вас есть проблемы с правильным отображением результатов.

В моем случае я получил только первый символ каждого результата, когда я использовал $.get(), хотя я использовал на json_encode()стороне сервера.

larsbo
источник
0

я использую $().one() для решения этого; Когда страница загружена, я отправляю ajax на сервер и жду, когда все будет готово. Затем передайте результат в функцию. $().one()важно. Потому что заставьте typehead.js присоединиться к вводу один раз. извините за плохое написание.

(($) => {
    
    var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
          var matches, substringRegex;
          // an array that will be populated with substring matches
          matches = [];
      
          // regex used to determine if a string contains the substring `q`
          substrRegex = new RegExp(q, 'i');
      
          // iterate through the pool of strings and for any string that
          // contains the substring `q`, add it to the `matches` array
          $.each(strs, function(i, str) {
            if (substrRegex.test(str)) {
              matches.push(str);
            }
          });
          cb(matches);
        };
      };
      
      var states = [];
      $.ajax({
          url: 'https://baconipsum.com/api/?type=meat-and-filler',
          type: 'get'
      }).done(function(data) {
        $('.typeahead').one().typeahead({
            hint: true,
            highlight: true,
            minLength: 1
          },
          {
            name: 'states',
            source: substringMatcher(data)
          });
      })
      

})(jQuery);
.tt-query, /* UPDATE: newer versions use tt-input instead of tt-query */
.tt-hint {
    width: 396px;
    height: 30px;
    padding: 8px 12px;
    font-size: 24px;
    line-height: 30px;
    border: 2px solid #ccc;
    border-radius: 8px;
    outline: none;
}

.tt-query { /* UPDATE: newer versions use tt-input instead of tt-query */
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
    color: #999;
}

.tt-menu { /* UPDATE: newer versions use tt-menu instead of tt-dropdown-menu */
    width: 422px;
    margin-top: 12px;
    padding: 8px 0;
    background-color: #fff;
    border: 1px solid #ccc;
    border: 1px solid rgba(0, 0, 0, 0.2);
    border-radius: 8px;
    box-shadow: 0 5px 10px rgba(0,0,0,.2);
}

.tt-suggestion {
    padding: 3px 20px;
    font-size: 18px;
    line-height: 24px;
    cursor: pointer;
}

.tt-suggestion:hover {
    color: #f0f0f0;
    background-color: #0097cf;
}

.tt-suggestion p {
    margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>

<input class="typeahead" type="text" placeholder="where ?">

Али Карими
источник
-1
 $('#runnerquery').typeahead({
        source: function (query, result) {
            $.ajax({
                url: "db.php",
                data: 'query=' + query,            
                dataType: "json",
                type: "POST",
                success: function (data) {
                    result($.map(data, function (item) {
                        return item;
                    }));
                }
            });
        },
        updater: function (item) {
        //selectedState = map[item].stateCode;

       // Here u can obtain the selected suggestion from the list


        alert(item);
            }

    }); 

 //Db.php file
<?php       
$keyword = strval($_POST['query']);
$search_param = "{$keyword}%";
$conn =new mysqli('localhost', 'root', '' , 'TableName');

$sql = $conn->prepare("SELECT * FROM TableName WHERE name LIKE ?");
$sql->bind_param("s",$search_param);            
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
    $Resut[] = $row["name"];
    }
    echo json_encode($Result);
}
$conn->close();

?>

Мохамед Айед
источник