Twitter Embedded Timeline Callback

javascript, twitter

Solution

When you copy and paste the code you get from Twitter, you have to replace this:

<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>

With this:

<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>

Of course, the doSomething function called above is your callback that runs when your embedded timeline loads and renders.

Also, I guess this solution doesn't work in Internet Explorer since it doesn't support onLoad events for script elements. Yet there are solutions for that.

Last, you can see my approach to this issue in the Twitter embedded timeline scraper I wrote.

Problem

I've been doing a lot of research into Twitter's Embedded Timelines. I've been trying to figure out if it is possible to know when the timeline is finished loading and displays on the page. This issue has been requested, but has yet to be implemented. I have come to a dead end an am hoping someone is able to help me find the solution. Here is what I have found so far: The code to add an Embedded Timeline: ``` <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> ``` What happens when the script is run: The script replaces the `<a>` tag with an `<iframe>` element. The contents of the `iframe` are ready, but the avatar image and the 'follow @username' button are not done downloading. The `iframe`'s `height` attribute is set to 0 so that you don't see the content without the images. The avatar image is downloaded, but the 'follow @username' button is still downloading. Content is still not visible. The 'follow @username' button is finished downloading. The `iframe`'s `height` attribute is set to match the height of the contents of the `iframe`. The timeline is now visible. Now, I've tried everything I can think of to figure out when the timeline is visible (without using settimeout/interval). The goal is to have a non-polling event/function/callback. Here is what I have tried so far without success: - Setting event listeners on the `iframe` (such as `onload`, `DOMContentLoaded`, `DOMFrameContentLoaded`, etc) to know when the content has finished loading. This doens't work becuase the `iframe` has no `src` attribute. After going through the uglified code (I was unable to find an uncompressed version), my guess is that it is using writes to add the content to the body of the `iframe`. - Setting event listeners to know when the `height` attribute changes on the `iframe`. Theoretically, this event should fire three times: first when the content loads, second when the `height` is set to 0, and third when the `height` is set to show the fully loaded timeline. However, I was only able to get the event to fire for the first two cases and never for the third (the one I actually wanted). I used `DOMSubtreeModified`, `onreadystatechange`, and `onpropertychange`, but only `DOMSubtreeModified` worked for firing the event. - Setting event listeners on the cotents of the `iframe`. Because JavaScript can reach inside of the `iframe` from Twitter, it is possible to grab any element inside the `iframe` (such as `document` or `window`). However, adding `onload`, `DOMContentLoaded`, or `DOMFrameContentLoaded` event listeners on the `window` or `document` of the `iframe` still does not fire those events. - Setting event listeners on the 'follow @username' button. The button is actually an `iframe` that does have a `src` attribute. By setting an `onload` event, it will get fired when it is loaded. However, the `onload` event will always fire twice. The first time when it has finished downloading and the second when it has finished processing. Immediatly after the second trigger, the timeline will be shown. To implement this is quite the hack though (I guess everything is) since you must wait for the contents of the `iframe` to load, reach inside and get the 'follow @username' `iframe`, set an `onload` event on it, then wait for the second event to fire. - Using the `twttr.widgets.createTimeline()` function, which has an optional parameter for a callback. However, the callback is called when the content is ready (step 2), but not when the iframe is visible (step 4). There's probably a few more combinations I forgot at this point. I know there exists a github gist that uses the Twitter `widget.js`, but adds callbacks to it. I was unable to get this to work. Sorry for the log question, but I hope someone is able to help. Thanks.

Original source

Related problems