谷歌地点自动完成搜索框:如何控制预测的启用或禁用

7

有没有可能控制(启用/禁用)Google地点自动完成搜索框(google.maps.places.SearchBox)的预测服务?

换句话说: 有没有可能暂时将HTML输入元素从自动完成搜索框服务中分离,然后重新附加它?

问题在于,我在与SearchBox服务连接的HTML输入元素下方显示服务结果。问题是,在结果显示后,当用户再次聚焦于输入元素时,预测结果会显示在结果之上并遮挡其视图。我希望在用户更改输入元素中的文本之前禁用预测。

enter image description here

EDIT 26/Aug/2016:

目前Javascript API不支持禁用预测。因此,我刚刚在Google上提出了一个功能请求。如果您对该功能感兴趣,请为其投票:Autocomplete SearchBox - Control (enable/disable) predictions.

EDIT 07/Sep/2016 - 奖励更新:

感谢所有参与回答和推广问题的人。

奖励的主要目标是找到使用当前可用手段的解决方案。恐怕这没有发生,所以我决定不授予奖励。

虽然下面的答案都没有提供解决方案,但每个答案都提供了某种线索,所以谢谢!也许这些线索将指向未来的解决方案。

奖励的次要目标(尽管没有直接传达)是促进Autocomplete SearchBox - Control (enable/disable) predictions功能请求。它的状态已更改为NeatIdea,并分配了内部跟踪号码。这是一个好迹象。

5个回答

3

您可以这样做:在用户选择地点后,您可以将类disabled添加到该输入字段中。这将有助于根据类名启用/禁用预测。

在自动完成代码所在的位置,您可以将其包装在if else语句中。

let field = document.getElementById('location');
if ( field.className.indexOf('disabled') > -1 ) {
  google.maps.event.clearInstanceListeners(field);
}
else {

  let autocomplete = new google.maps.places.Autocomplete( field, {types: ['geocode']} );
  autocomplete.addListener('place_changed', () => {
    let place = autocomplete.getPlace();
    let filed_val = field.value; // incase you need it
    field.classList.add('disabled');
  });

}

这将在用户选择地点后删除自动完成功能… 如果您想的话,稍后可以从此字段中去除 disabled 类,并使其再次正常工作。

我理解你的例子的意思,尽管你使用 google.maps.places.Autocomplete 而不是 google.maps.places.SearchBox。但我不喜欢它通过创建新的服务对象来重新启用预测,而旧的对象仍然在内存中。理想情况下应该在旧对象上重新启用 DOM 事件。 - Michal Foksa
恰当地,做适合你需要的事情,这只是为了向您展示其中一种方法... - Dhruv Kumar Jha

1

我的解决方案是在AngularJS中使用指令。

.pac-contained 是在创建Autocomplete服务实例后创建的,例如:new google.maps.places.Autocomplete(…)new google.maps.places.SearchBox(…)

我所做的是在文档中查找刚刚创建的 .pac-container,存储其引用并将该容器标记为已处理(通过添加任意类 .predictions-control)。仅当预期在应用程序中存在多个 .pac-container 时才需要“标记”容器。

现在,有了这个引用,我可以控制具有预测的 .pac-contained 的可见性(隐藏或显示)。

// Container element with predictions.
var pacContainer = null;

/***
 * Find predictions container without predictions-control class set.
 * Then set  predictions-control class to it and convert it into
 * Angular's jqLite object.
 * @return {jqLite object} - container or null when not found.
 */
function getPredictionsContainer() {
    // Get div.pac-container without predictions-control class.
    var e = document.querySelector('div.pac-container:not(.predictions-control)');
    if (e){
        var container = angular.element(e);
        container.addClass('predictions-control');
        console.log('predictions-control: Container found.');
        return container;
    } else {
        console.warn('predictions-control: Container not found!');
    }
    return null;
} // getPredictionsContainer

/***
 * Loop in 50ms intervals until container is found.
 */
function untilContainerFound(){
    pacContainer = getPredictionsContainer();
    if (pacContainer == null){
        $timeout(untilContainerFound, 50);
    }
} // untilContainerFound

this.init = function() {
    untilContainerFound();
}; // this.init

/***
 * Prevent predictions to be displayed when user clicks on the
 * input element. It is achieved by adding ng-hide CSS class to
 * predictions container. Predictions container is identified by
 * ".pac-container" CSS class selector.
 */
this.hidePredictions = function() {
    // If predictions container was not found at directive
    // initialization try to find it now.
    if (pacContainer === null){
        pacContainer = getPredictionsContainer();
    }
    if (pacContainer){
        console.log('predictions-control: Hiding predictions.');
        pacContainer.addClass('ng-hide');
    } else {
        console.warn('predictions-control: Container not found!');
    }
}; // this.hidePredictions

/***
 * Show predictions again by removing ng-hide CSS class from
 * predictions container.
 */
this.showPredictions = function() {
    console.log('predictions-control: Showing predictions.');
    if (pacContainer){
        pacContainer.removeClass('ng-hide');
    }
}; // this.showPredictions

在服务实例创建后立即调用init()函数:
// Create SearchBox service for auto completing search terms.
autocomplete = new google.maps.places.SearchBox( inputElem[0] );
// OR
// autocomplete = new google.maps.places.Autocomplete( ..... );
autocomplete .addListener('places_changed', callback);

predictionsCtrl.init();

注意:只要确保不同时创建两个自动完成服务(例如:每个服务在不同的选项卡上),或者可以等待下一个服务的创建,直到找到前一个服务的 .pac-container,即使有多个自动完成服务实例,它也可靠地工作。

0

没有必要也没有意义:预测是SearchBox的全部意义和存在理由。如果您不想要预测,可以使用Places库中的文本搜索

如果用户再次点击/聚焦搜索框,则可能并不关心建议所遮挡的结果。谷歌地图也有相同的行为,这不是问题,对吧?

如果您无法在SearchBox和结果之间放置一些空间(例如this tool),并且您绝对必须暂时禁用建议,那么我建议您销毁google.maps.places.SearchBox对象,并稍后创建一个新的对象,附加到相同的HTML输入元素上。


这是为移动应用程序设计的,因此屏幕空间和键盘点击次数非常宝贵,这就是为什么我不能将结果放在下面并想使用“SearchBox”服务(“Text Search”是没有预测的“SearchBox”)。销毁和重新创建“SearchBox”服务不起作用。无论如何,感谢您的回答。 - Michal Foksa

0
可能有价值的信息。

这与API V3.29相关(不确定它是否总是准确的)。
API为自动完成创建的div元素具有“pac-container pac-logo”的类。
利用document.querySelector('.pac-container'),您可以在其他地方的单击事件上将其样式属性设置为display: none。

注意:当用户在searchBox中点击返回时,谷歌会将样式属性更改回适当的内容,因此您只需要设置一次,不必再次设置。
(这可能比涉及angular更容易和更清洁)。

希望这能帮助某些人(我不得不添加一个CSS规则来增加应用程序中的z-index以使自动完成显示出来)。

0
如果您将disabled属性添加到文本框中,那么这将禁用预测。
使用readonly属性则不会。
这在某些情况下可能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接