我正在尝试在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小提琴示例我正在使用$.get()
调用 - 因为在我的应用程序中我使用小胡子将模板加载到信息块中
- 正在加载的示例内容与$.get()
调用无关(是的,我可以在没有before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:update) << :avatar
end
调用的情况下实现相同)但我只是尝试使用类似的代码布局+时序到我的自己的申请
答案 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);
});
答案 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/代码并完成它。