Twitter嵌入式时间线回调

时间:2013-07-22 22:43:38

标签: javascript twitter

我一直在对Twitter的嵌入式时间表进行大量研究。我一直试图弄清楚是否有可能知道时间线何时完成加载并且显示在页面上。这issue has been requested,但尚未实施。我已经走到了尽头,希望有人能够帮助我找到解决方案。这是我到目前为止所发现的:

添加嵌入式时间轴的代码:

<a class="twitter-timeline" href="https://twitter.com/twitterapi" data-widget-id="YOUR-    WIDGET-ID-HERE">Tweets by @twitterapi</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

运行脚本时会发生什么:

  1. 该脚本将<a>标记替换为<iframe>元素。

  2. iframe的内容已准备就绪,但是头像图片和“关注@username”按钮未完成下载。 iframe的{​​{1}}属性设置为0,这样您就可以看到没有图片的内容。

  3. 下载了头像图片,但“关注@username”按钮仍在下载。内容仍然不可见。

  4. '关注@username'按钮已完成下载。 height的{​​{1}}属性设置为与iframe内容的高度相匹配。现在可以看到时间表。

  5. 现在,我已经尝试了我能想到的所有内容,以确定时间线何时可见(没有使用settimeout / interval)。目标是进行非轮询事件/函数/回调。以下是我迄今为止没有成功的尝试:

    • height上设置事件监听器(例如iframeiframeonload等)以了解内容何时加载完毕。这不起作用,因为DOMContentLoaded没有DOMFrameContentLoaded属性。在浏览了uglified代码后(我无法找到未压缩的版本),我的猜测是它正在使用写入将内容添加到iframe的正文中。
    • 设置事件侦听器,以了解srciframe属性的更改时间。从理论上讲,此事件应触发三次:首先加载内容,第二次加载height时设置为0,第三次设置iframe时显示完全加载的时间轴。但是,我只能让前两个案件的事件发生,而第三个案件(我实际想要的那个)从来没有。我使用了heightheightDOMSubtreeModified,但只有onreadystatechange才能解雇此事件。
    • onpropertychange的cotents上设置事件侦听器。因为JavaScript可以从Twitter中到达DOMSubtreeModified内部,所以可以抓取iframe内的任何元素(例如iframeiframe)。但是,在document的{​​{1}}或window上添加onloadDOMContentLoadedDOMFrameContentLoaded个事件侦听器仍然无法触发这些事件。
    • 在“关注@username”按钮上设置事件侦听器。该按钮实际上是window,具有document属性。通过设置iframe事件,它将在加载时被触发。但是,iframe事件将始终触发两次。第一次完成下载,第二次完成处理。在第二次触发后立即显示时间线。实现这一点非常糟糕(我想一切都是),因为你必须等待src的内容加载,到达内部并获得'follow @username'onload,设置一个{ {1}}事件,然后等待第二个事件发生。
    • 使用onload函数,该函数具有回调的可选参数。但是,当内容准备就绪时会调用回调(步骤2),但是当iframe可见时(步骤4)则不会调用回调。

    在这一点上我可能会忘记更多的组合。我知道存在使用Twitter iframe的{​​{3}},但会添加回调。我无法让它发挥作用。

    对不起日志问题,但我希望有人能够提供帮助。感谢。

3 个答案:

答案 0 :(得分:10)

当您复制并粘贴从Twitter获得的代码时,您必须将其替换为:

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

有了这个:

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";js.setAttribute('onload', "twttr.events.bind('rendered',function(e) {doSomething()});");fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

当然,上面调用的doSomething函数是在嵌入式时间轴加载和渲染时运行的回调函数。

此外,我猜这个解决方案在Internet Explorer中不起作用,因为它不支持脚本元素的onLoad事件。 Yet there are solutions for that

最后,您可以在the Twitter embedded timeline scraper I wrote中查看我对此问题的处理方法。

答案 1 :(得分:9)

我要在这里发布我的解决方案,即使它已经是1个月以防万一有人再次发现这个帖子,我要做的就是轮询,直到iframe有一个宽度&gt; 1作为回调的指标

if ($('.twitter-timeline').length) {
    //Timeline exists is it rendered ?
    interval_timeline = false;
    interval_timeline = setInterval(function(){
        console.log($('.twitter-timeline').width());
        if ($('.twitter-timeline').hasClass('twitter-timeline-rendered')) {
            if ($('.twitter-timeline').width() > 10) {
                //Callback
                clearInterval(interval_timeline);
                DoWhatEverYouNeedHere();
            }     
        }
    },200);
}

答案 2 :(得分:2)

您可以尝试使用Javascript工厂而不是属性绑定。 createTimeline方法返回一个promise,因此您可以在那里链接后加载活动。 请参阅Twitter文档:https://dev.twitter.com/web/embedded-timelines/parameters

twttr.widgets.createTimeline(
    "YOUR-WIDGET-ID-HERE",
    document.getElementById("container"),
    {
        height: 400,
        chrome: "nofooter",
        linkColor: "#820bbb",
        borderColor: "#a80000"
    }
)
.then(function(){
      DoSomething();
});