我的ember应用程序必须打开一个窗口(通过外部JS API),相应的API指令应该由控制器操作调用,因为它应该转换到另一个路由。
我的问题是,当操作被触发时,窗口不会打开。它只会从直接处理可信事件的代码中打开,即用户的单击。
因此,摆脱Ember,使用jQuery进行调试,并假设window.open()
指令在MyLib.login()
中,这段代码A有效:
$('#mybutton').click(() ->
MyLib.login()
)
但这个代码B没有:
$.myNamespace = {
myLoginFunction: () ->
MyLib.login()
}
$('#mybutton').click(() ->
$.myNamespace.myLoginFunction()
)
成员操作也不起作用,生成与B相同的代码,即调试后window.open()
将返回一个未定义的对象。
我的问题是:
- 有没有一种方法可以让代码B工作?(考虑到因数分解的原因,这很有意义)
- 有没有办法Ember动作也能起作用
附言:为了提高透明度,我所说的库是Deezer的JavaScriptSDK。
PPS:请原谅我的CoffeeScript
首先,您要面对的是目前大多数浏览器默认启用的弹出窗口阻止程序。
我只熟悉弹出窗口拦截器在Firefox中的工作方式(最初在bug 252326中实现,此后没有太大变化),但其他浏览器也类似。这个想法很简单:弹出窗口只能在响应明确的用户操作时打开。这超出了可信事件的范围,只有鼠标点击和按键才算是此类操作。所有其他弹出窗口都被认为是不可取的,将被阻止。
因此,为了回答您的问题:
如何将Ember操作视为可信事件,以便window.open成功?
任何响应用户操作而运行的代码(意味着同步代码执行)都可以打开弹出窗口。至于其他代码,例如延迟操作(包括对响应用户操作而执行的同步代码的异步回调)或响应应用程序生成的事件的代码-弹出窗口阻止程序不会让它通过,对此你无能为力。web应用程序不能伪造可信事件,就像它不能随意绕过弹出窗口阻止程序一样(任何一个都是安全问题)。
有没有办法Ember动作也能起作用?
你基本上有两个选择:
- 如果被阻止,
window.open()
将在Firefox中返回null
(其他浏览器中的行为可能不同)。你可以检测到这一点,并要求用户将你的网站添加到弹出窗口阻止程序例外中。然而,他们中的大多数人会忽视这些要求 - 您可以更改web应用程序的工作方式。例如,当用户单击"登录"按钮时,您可以打开一个空的弹出窗口,但稍后只会用真实内容填充。或者,您可以将登录操作移动到弹出窗口中。或者你可以完全停止使用弹出窗口,而是在主窗口中显示一个层。你的选择
显然,第二种选择更有意义,所有网站都是这样做的。对抗浏览器的安全机制并不有趣。
感谢您的评论和反馈。尽管如此,通过解决我的问题,我可以回答我自己的问题。
当点击或其他用户事件触发时,Ember操作ARE被视为可信操作。
我的问题有点愚蠢。我意识到我的login
函数首先调用了loginStatus
函数,真正的登录是在异步回调中执行的,这取决于loginStatus
响应的结果。回调丢失了"trusted"属性是有道理的。