Twitter嵌入式时间线回调

13
我将为您翻译以下内容,涉及编程和Twitter嵌入式时间轴。请注意,我会尽力使翻译通俗易懂,但不会提供解释或回答问题。

我一直在研究Twitter的嵌入式时间轴。我一直在尝试弄清楚是否有可能知道时间轴何时加载完成并在页面上显示。这个问题已被请求, 但尚未实现。我已经走到了死路,希望有人能帮助我找到解决方案。以下是我迄今为止发现的内容:

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

<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的内容已准备好,但是头像图片和“关注@用户名”按钮尚未下载完毕。 iframeheight属性设置为0,这样在没有图像的情况下不会看到内容。

  3. 头像图片已下载完成,但是“关注@用户名”按钮仍在下载中。内容仍然不可见。

  4. “关注@用户名”按钮已完成下载。 将iframeheight属性设置为与iframe内容的高度相匹配。时间线现在可见。

现在,我已经尝试了我能想到的所有方法来确定时间线何时可见(不使用settimeout/interval)。 目标是具有非轮询事件/函数/回调。到目前为止,我尝试过以下方法但没有成功:

  • iframe上设置事件侦听器(例如onloadDOMContentLoadedDOMFrameContentLoaded等),以了解内容何时加载完成。这不起作用,因为iframe没有src属性。经过查看混淆的代码(我找不到未压缩的版本),我的猜测是它使用写入将内容添加到iframe的正文中。
  • 设置事件侦听器以了解iframe上的height属性何时更改。理论上,此事件应触发三次:首先在内容加载时触发,其次在将height设置为0时触发,第三次在将height设置为显示完全加载的时间轴时触发。然而,我只能让事件针对前两种情况触发,而从未为第三种情况(我真正想要的那个)触发。我使用了DOMSubtreeModifiedonreadystatechangeonpropertychange,但只有DOMSubtreeModified在触发事件时起作用。
  • iframe的内容上设置事件侦听器。因为JavaScript可以从Twitter内部进入iframe,所以可以抓取iframe内的任何元素(例如documentwindow)。然而,在iframewindowdocument上添加onloadDOMContentLoadedDOMFrameContentLoaded事件侦听器仍未触发这些事件。
  • 在“关注@用户名”按钮上设置事件侦听器。该按钮实际上是一个具有src属性的iframe。通过设置onload事件,它将在加载时触发。但是,onload事件将始终触发两次。第一次是在下载完成后,第二次是在处理完成后。在第二个触发之后立即,时间轴将显示。不过,要实现这一点相当麻烦(我想一切都是),因为必须等待iframe的内容加载完成,然后获取“关注@用户名”iframe,在其上设置onload事件,然后等待第二个事件触发。
  • 使用twttr.widgets.createTimeline()函数,其中包含回调的可选参数。但是,当iframe可见时(步骤4),回调会在内容准备就绪(步骤2)时调用,而不是在可见时。

我可能忘记了一些组合。我知道有一个github gist使用Twitter的widget.js,但添加了回调函数。我无法使其工作。

抱歉问题比较长,但希望有人能够帮助。谢谢。

3个回答

11
我会在这里发布我的解决方案,即使已经过去1个月,以防再次有人发现此帖子,我所要做的是进行轮询,直到iframe的宽度>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);
}

1
根据你想要做的事情,检查宽度可能行不通,如果出现这种情况,请尝试检查高度的值。我不得不这样做才能让我的东西正常工作。 - rclai

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 事件。但是,有解决方法

最后,您可以在我编写的Twitter嵌入式时间轴抓取程序中查看我处理此问题的方法。


那个爬虫是如何工作的?我看了一下,你通过脚本从另一个域访问IFrame的内容,这会导致安全错误。这是一个很酷的想法,我只是想知道你是否做了额外的事情来解决这个问题。 - Andy
@Andy,爬虫程序不会尝试访问来自另一个域的IFrame。Twitter小部件包括一个动态创建IFrame的脚本,但它不会直接从另一个域加载它,因此在尝试抓取时不会出现任何安全错误。 - Joomy Korkut
我之前不知道 twttr.events.bind。它似乎也在正确的时间触发。如果有其他人想知道哪些事件是可绑定的,可以在这里找到所有信息:https://dev.twitter.com/docs/tfw/events。另外,只有 IE8 及以下版本不支持脚本的 onload 事件。IE9+ 支持(参见 http://pieisgood.org/test/script-link-events/)。 - Steven Lambert

3
你可以尝试使用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();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接