谷歌地图infobubble动态内容未加载第一个标记点​​击

时间:2015-10-17 08:16:38

标签: jquery google-maps infowindow domready infobubble

我正在尝试在Google地图infobubble中添加动态内容:
- 一个第一个标记点​​击一个空的信息块出现
- 在 SECOND 点击标记时加载了正确的内容

根据this answer我在先前定义的信息对象上使用domready事件来启动加载动态内容的函数。
...虽然该答案中的JS小提琴具有误导性,因为“动态”内容实际上是使用domready调用的content选项new InfoBubble()之前加载的domready

我在控制台中获得所有正确的信号,google.maps.event.trigger(this, 'domready');功能正在完成,并且在第一次标记点击时正确找到了内容。

试过:

  • 查看the infobubble.js code并将console.logs放在第1231行的任一侧:
    disableAnimation: true
    结果表明,在动态函数开始之前,domready确实被解雇了。

  • 使用infobubble setTimeout()选项禁用动画 - 认为在调用domready后可能会减慢信息量负载 - 但它无法正常工作

  • 添加$.get()最多3秒,但这似乎没有帮助......无论如何,这将是一个糟糕的黑客。

如何在首次点击标记时加载动态内容?

JS Fiddle here

注意:
- 对于js小提琴示例我正在使用$.get()调用 - 因为在我的应用程序中我使用小胡子将模板加载到信息块中 - 正在加载的示例内容与$.get()调用无关(是的,我可以在没有before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:update) << :avatar end 调用的情况下实现相同)但我只是尝试使用类似的代码布局+时序到我的自己的申请

2 个答案:

答案 0 :(得分:2)

问题似乎是信息量的open_ - 方法(将在open - 方法中调用):

InfoBubble.prototype.open_ = function(opt_map, opt_anchor) {
  this.updateContent_();

  if (opt_map) {
    this.setMap(opt_map);
  }
  //............................
}

首先调用方法updateContent_(将触发domready - 事件),然后设置map。但是,在设置map - 属性之前,叠加层不会被添加到地图中,内容是尚未附加到文档的DocumentFragment / Node,因此jQuery可能找不到它。

可能的解决方案:

使用信息块的content_ - 属性作为jQuery选择器的上下文,那么内容是否已经附加到文档中无关紧要

google.maps.event.addListener(marker, 'click', function () {

  google.maps.event.addListenerOnce(infoBubble,'domready',function () {

    var that=this;            
    //when we load the additional content asynchronously, 
    //make sure that it's the correct content we are loading
    var token=new Date().getTime()*Math.random();
    that.set('token',token);

    $.get('https://lh4.googleusercontent.com/-_Cox6aEnSkU/UQ_B0LK4khI/AAAAAAAAAzw/4H4dsWGPgeE/s150/go-button.png', function (myImage) {
      if(that.get('token')===token){
        $(".dialog",that.content_).html('<img id="theImg" src="https://goo.gl/phmzis" />');
      }     
        })

  });
  infoBubble.open(map, marker);
});

http://jsfiddle.net/doktormolle/aLtz76ym/

答案 1 :(得分:0)

感谢观察in the answer by Dr.Molle我已经找到了解决方案 - 这确实与domready代码中updateContent_()事件触发器的位置有关。

不幸的是,在open_()被调用之前,setMap()函数当前位于domready函数中,这意味着domready被解雇了infoBubble被添加到DOM。

由于setMap()是异步的,因此open_()调用setMap()之后只能添加setMap()触发器,而{ {1}}函数没有特定的回调。

但是,根据infobubble.js(这个插件正在使用的内容),setMap()函数调用onAdd()函数一次调用setMap()后调用domready有效的地图对象:

  

onAdd():实现此方法以初始化overlay DOM元素。在使用有效映射调用setMap()之后调用此方法一次。此时,窗格和投影将被初始化。

更简单:

  

在onAdd()方法中,您应该创建DOM对象并将它们作为窗格的子项追加。

因此,我们应该在<{1}}函数中触发onAdd()事件, infoBubble附加到地图窗格后

/**
 * On Adding the InfoBubble to a map
 * Implementing the OverlayView interface
 */
InfoBubble.prototype.onAdd = function() {
  if (!this.bubble_) {
    this.buildDom_();
  }

  this.addEvents_();

  var panes = this.getPanes();
  if (panes) {
    panes.floatPane.appendChild(this.bubble_);
    panes.floatShadow.appendChild(this.bubbleShadow_);
  }
  google.maps.event.trigger(this, 'domready');    // infobubble has now been added to DOM so we can fire `domready`
};

我为谷歌创建了documentation for OverlayView来更新pull-request并解决此问题。

JS在这里使用更新的代码(请参阅javascript窗口中新行domready展示位置的第910行) 的 infobubble.js code

注意:
- 我已经在旧domready电话和正确(更新)domready电话的jsfiddle中添加了时间戳 - 您将在console.log中看到它们 - 它来了在我的系统上大约20ms(它会随系统速度而变化)
- 它显示旧的domready确实在infoBubble附加到窗格之前发射 - 这样可以了解您需要在setTimeout电话中放置任何功能的最低domready

如果您想使用没有修复的原始代码 - setTimeout hack: http://jsfiddle.net/goredwards/7r96we66/
...你可以玩setTimeout持续时间并查看最小值 - 我在快速机器上下降到大约5ms。显然,您必须使用此hack在生产代码中使用其他方式来应对最慢的机器(即您将setTimeout持续时间置于最高级别你可以忍受 - 没有烦恼~150-250ms - 甚至覆盖你最慢的系统。) ...或者你可以复制并更新http://jsfiddle.net/goredwards/xeL7dxye/代码并完成它。