尝试动态加载API和JS文件

我正在尝试动态加载Skyscanner API但它似乎不起作用。 我尝试了一切可能的方式,一切都发生了,内容消失了。

我试过console.log没有结果; 我尝试了chrome的开发人员工具中的元素,虽然所有内容的css保持不变,但内容仍然消失(我认为它可能是在html / body类型上添加display:none)。 我尝试了所有Google的异步技巧,但又是空白页。 我尝试了所有用于异步加载的js插件,结果仍然相同。

Skyscanner的API文档很差,虽然它们提供回调但它不像google API的回调那样工作。

示例: http : //jsfiddle.net/7TWYC/

在头部加载API的示例: http : //jsfiddle.net/s2HkR/

那么如何在按钮点击或异步上加载api? 没有文件在HEAD部分。 如果有办法阻止document.write使页面空白或以任何其他方式。 我不介意使用普通的js,jQuery或PHP。

编辑:

我已经将奖金设置为我以前50的50美元。

Orlando Leite回答了关于如何使这个asynch api加载的非常接近的想法,虽然有些function不起作用,比如选择日期,我无法设置样式。

我正在寻找一个答案,我将能够使用所有function,以便它可以正常工作,如果它是在加载时加载。

这是奥兰多的最新小提琴: http : //jsfiddle.net/cxysA/12/

编辑2在Gijs答案:

Gijs提到了覆盖document.write的两个链接。 这听起来很棒,但我认为不可能实现我的目标。

我使用John的Resig方法来阻止document.write,可以在这里找到: http : //ejohn.org/blog/xhtml-documentwrite-and-adsense/

当我使用这种方法时,我成功加载了API,但是根本没有加载snippets.js文件。

小提琴: http : //jsfiddle.net/9HX7N/

对于像这样的有问题的情况,你可以只覆盖document.write 。 Hacky就像地狱一样,但是它可以工作,你可以决定所有内容的去向。 见例如。 这篇博文来自John Resig 。 这忽略了IE,但是通过一些工作,这个技巧也适用于IE,参见例如。 这篇博文 。

因此,我建议使用您自己的函数覆盖document.write ,在必要时批量输出,并将其放在您喜欢的位置(例如,在底部的div中)。 这应该可以防止脚本破坏页面的内容。

编辑:好的,所以我花了一些时间来研究这个脚本。 为了将来参考,请使用http://jsbeautifier.org/之类的内容来调查第三方脚本。 这种方式更容易阅读。 幸运的是,几乎没有任何混淆/缩小,所以你有他们的API文档的补充(我无法找到,顺便说一句 – 我只发现’代码向导’,我没有兴趣) 。

这是一个几乎可以工作的例子: http : //jsfiddle.net/a8q2s/1/

这是我采取的步骤:

  1. 覆盖document.write 。 这需要加载初始脚本之前发生。 您的替换函数应将其代码字符串附加到DOM中。 不要调用旧的document.write ,这只会让你犯错误而且无论如何也不会做你想做的事。 在这种情况下,你很幸运,因为所有内容都在一个document.write调用中(检查初始脚本的来源)。 如果情况并非如此,那么你必须批量处理所有内容,直到他们给你的HTML有效和/或你确定没有其他内容可来。
  2. 使用jQuery的$.getScript或等效项单击按钮上的初始脚本。 传递一个回调函数(为了清楚起见,我使用了一个命名函数引用,但如果你愿意,可以内联它)。
  3. 告诉Skyscanner加载模块。

编辑#2:哈,他们有一个API( skyscanner.loadAndWait ),用于在脚本加载后获得回调。 使用它有效:

http://jsfiddle.net/a8q2s/3/

(注意:这似乎仍然在内部使用超时循环)

我相信你想要的是它:

 function loadSkyscanner() { function loaded() { t.skyscanner.load('snippets', '1', {'nocss' : true}); var snippet = new t.skyscanner.snippets.SearchPanelControl(); snippet.setCurrency('GBP'); snippet.setDeparture('uk'); snippet.draw(document.getElementById('snippet_searchpanel')); } var t = document.getElementById('sky_loader').contentWindow; var head = t.document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.onreadystatechange= function() { if(this.readyState == 'complete') loaded(); } script.onload= loaded; script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY'; head.appendChild(script); } $("button").click(function(e) { loadSkyscanner(); }); 

它在iframe#sky_loader中加载skyscanner,在调用加载函数后创建SearchPanelControl。 但最后,片段在主文档中绘制。 这真的是一个奇怪的解决方法,但它确实有效。

唯一的限制是,你需要一个iframe。 但您可以使用display:none隐藏它。

一个工作的例子

编辑

对不起,我没看到。 现在我们可以看到skyscanner API有多糟糕。 它放置两个div来进行自动完成,但不是相对于你调用绘制的元素,而是文档。 在iframe中加载脚本时,document是iframe文档。

有一个解决方案,但我不建议,实际上是一个解决方法:

  function loadSkyscanner() { var t; this.skyscanner; var iframe = $(""); function realWorkaround() { var tbody = t.document.getElementsByTagName("body")[0]; var body = document.getElementsByTagName("body")[0]; while( tbody.children.length != 0 ) { var temp = tbody.children[0]; tbody.removeChild( temp ); body.appendChild( temp ); } } function snippetLoaded() { skyscanner = t.skyscanner; var snippet = new skyscanner.snippets.SearchPanelControl(); snippet.setCurrency('GBP'); snippet.setDeparture('uk'); snippet.draw(document.getElementById('snippet_searchpanel')); setTimeout( realWorkaround, 2000 ); } var loaded = function() { console.log( "loaded" ); t = document.getElementById('sky_loader').contentWindow; t.onLoadSnippets( snippetLoaded ); } $("body").append(iframe); iframe.load(loaded); } $("button").click(function(e) { loadSkyscanner(); }); 

在加载代码段时,使用另一个加载和回调的html加载iframe。 加载后,在设置超时后创建所需的片段,因为我们无法知道何时加载了SearchPanelControl。 此realWorkaround将自动完成div移动到主文档。

你可以在这里看到一个工作示例

加载的iframe就是这个

编辑

修复了您找到的错误并更新了链接。

for循环已经消失并增加了一段时间,现在效果更好。

  while( tbody.children.length != 0 ) { var temp = tbody.children[0]; tbody.removeChild( temp ); body.appendChild( temp ); } 

skyrunner.js文件中,他们使用document.write使页面在加载回调时变为空白……所以这是你的场景中的一些后果..

  1. 单击按钮时,这会使页面空白。
  2. 因此,它删除了页面甚至’jQuery.js’中的所有内容,这就是为什么回调不起作用..即,无法调用main函数,因为这是使用jQuery编写的。
  3. 你错过了一个id = map的目标’div’标签(根据代码)。 实际上这是地图加载的目标。
  4. 我观察到的另一件事是map在当前上下文中实际上不是div,即将api映射到load。

在这里你必须采用旧学校方法,那就是..你应该在头部内容的顶部包含你的skyrunner.js文件。

因此,请尝试下载该文件并包含在head标签中。

谢谢