我正在尝试动态加载Skyscanner API,但它似乎不起作用。我尝试了一切可能的方式,一切都发生了,内容消失了。
我试过console.log但没有结果;我尝试了chrome的开发人员工具中的元素,虽然所有内容的css保持不变,但内容仍然消失(我认为它可能是在html / body类型上添加display:none)。我尝试了所有Google的异步技巧,但又是空白页。我尝试了所有用于异步加载的js插件,结果仍然相同。
Skyscanner的API文档很差,虽然它们提供回调但它不像google API的回调那样工作。
在头部加载API的示例:http://jsfiddle.net/s2HkR/
那么如何在按钮点击或异步上加载api?没有文件在HEAD部分。如果有办法阻止document.write使页面空白或以任何其他方式。我不介意使用普通的js,jQuery或PHP。
编辑:
我已经将奖金设置为我以前50的上限。
Orlando Leite回答了关于如何使这个asynch api加载的非常接近的想法,虽然有些功能不起作用,例如选择日期,我无法设置样式。
我正在寻找一个答案,我将能够使用所有功能,以便它可以正常工作,如果它是在加载时加载。
以下是奥兰多的更新小提琴: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文件。
答案 0 :(得分:5)
我相信你想要的是:
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 = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></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移动到主文档。
You can see a work example here
修改强>
修复了您找到的错误并更新了链接。
for
循环已经消失并添加了一段时间,现在效果更好。
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
答案 1 :(得分:3)
在skyrunner.js
文件中,他们使用document.write使页面在加载回调时变为空白......所以这是你的场景中的一些后果..
在这里你必须采用旧学校方法,那就是..你应该在头部内容的顶部包含你的skyrunner.js文件。
所以尝试下载该文件并包含在head标签中。
由于
答案 2 :(得分:3)
对于像这样的有问题的情况,您可以覆盖document.write
。 Hacky是地狱,但它确实有效,你可以决定所有内容的去向。见例如。 this blogpost by John Resig。这忽略了IE,但是通过一些工作,这个技巧也适用于IE,参见例如。 this blogpost
因此,我建议使用您自己的函数覆盖document.write
,在必要时批量输出,并将其放在您喜欢的位置(例如,在<body>
底部的div中)。这应该可以防止脚本破坏您网页的内容。
编辑:好的,所以我花了一些时间来研究这个脚本。为了将来参考,请使用http://jsbeautifier.org/之类的内容来调查第三方脚本。这种方式更容易阅读。幸运的是,几乎没有任何混淆/缩小,所以你有他们的API文档的补充(我无法找到,顺便说一句 - 我只找到'代码向导',我没有兴趣)
这是一个几乎可以运作的例子:http://jsfiddle.net/a8q2s/1/
以下是我采取的步骤:
document.write
。这需要在之前加载初始脚本。您的替换函数应将其代码字符串附加到DOM中。不要打电话给旧的document.write
,这只会让你犯错误而且不会做你想做的事情。在这种情况下,您很幸运,因为所有内容都在一个document.write
调用中(检查初始脚本的来源)。如果不是这种情况,那么你必须批量处理所有内容,直到他们给你的HTML有效和/或你确定没有其他内容出现。$.getScript
或等效项单击按钮上的初始脚本。传递一个回调函数(为了清楚起见,我使用了一个命名的函数引用,但如果你愿意,可以内联它。)编辑#2:哈,他们有一个API(skyscanner.loadAndWait
),用于在脚本加载后获得回调。使用它:
(注意:这似乎仍然在内部使用超时循环)