1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>twitframe</title>
7 <meta name="description" content="Embed Tweets in an iframe">
8 <style>
9 body {
10 font-family: helvetica neue, arial, helvetica, sans-serif;
11 font-size: 10pt;
12 margin: 1em auto;
13 max-width: 760px;
14 }
15
16 h1 {
17 margin: 0;
18 }
19
20 a {
21 color: #0000dd;
22 }
23
24 code,
25 pre {
26 background-color: #f2f2f2;
27 display: block;
28 margin: 1em auto;
29 outline: 1px solid #bbb;
30 overflow-x: auto;
31 padding: 1em;
32 }
33
34 div.iframe,
35 iframe {
36 font-family: serif;
37 font-size: 12pt;
38 margin-left: 1em;
39 }
40
41 div.iframe {
42 background-color: #fafafa;
43 height: 250px;
44 overflow-x: auto;
45 padding: 1em;
46 width: 550px;
47 }
48
49 div.iframe,
50 iframe.gray {
51 background-color: #fafafa;
52 }
53
54 tt {
55 color: green;
56 }
57
58 hr {
59 border: 1px solid gray;
60 }
61 </style>
62</head>
63<body>
64 <h1>twitframe</h1>
65
66 <p>
67 twitframe allows one to display
68 <a
69 href="https://developer.x.com/en/docs/x-for-websites/embedded-tweets/overview"
70 rel="noopener noreferrer"
71 target="_blank"
72 >Embedded Tweets</a> on websites to dynamically show retweet and favorite counts, inline media/card data,
73 and allow users to retweet/reply/favorite Tweets, all while isolating the Javascript and DOM manipulation in an <tt>iframe</tt>.
74 This increases security and speeds up website page loads.
75 </p>
76
77 <p style="color: gray; font-style: italic;">
78 This is an independent service not affiliated with Twitter in any way.
79 No guarantee of availability or security is made by using this service.
80 </p>
81
82 <p style="color: gray; font-style: italic;">
83 You're currently browsing a version of twitframe hosted by <strong>Rita.moe</strong>, with slight modifications to the original code.
84 </p>
85
86 <h3>Use</h3>
87
88 <p>
89 Add an <tt><iframe></tt> to your HTML document and pass (at least) the full URL to the Tweet as a
90 <a
91 rel="noopener noreferrer"
92 target="_blank"
93 href="https://en.wikipedia.org/wiki/Percent-encoding"
94 >URL-encoded</a> parameter <tt>url</tt> to <tt>http://tf.rita.moe/show</tt>:
95 </p>
96
97 <p>
98 <code>
99 <iframe border="0" frameborder="0" height="250" width="550"<br>
100 src="https://tf.rita.moe/show?<span style="color: green;">url=https%3A%2F%2Ftwitter.com%2Fjack%2Fstatus%2F20</span>"><br>
101 </iframe>
102 </code>
103 </p>
104
105 <p>
106 This example code would produce the following (without the gray background):
107 </p>
108
109 <iframe
110 border="0"
111 class="gray"
112 frameborder="0"
113 height="300"
114 src="https://tf.rita.moe/show?url=https%3A%2F%2Ftwitter.com%2Fjack%2Fstatus%2F20"
115 width="550"
116 ></iframe>
117
118 <p>
119 Note that a height of 300 may be too big for short tweets such as this one, but too small for long tweets with embedded media.
120 See <a href="#sizing">sizing</a> below to automatically size the <tt>iframe</tt> based on its size.
121 </p>
122
123 <p>
124 <h3>Graceful Degredation</h3>
125 </p>
126
127 <p>
128 If the Tweet data is known beforehand, it can be passed to twitframe to be displayed before Twitter's Javascript loads.
129 The following parameters may be passed:
130 </p>
131
132 <p>
133 <ul>
134 <li><tt>tweet</tt> - The full text of the Tweet</li>
135 <li><tt>author_name</tt> - The full name of the Tweet's author</li>
136 <li><tt>author_username</tt> - The username of the Tweet's author, including the @ sign</li>
137 <li><tt>datetime</tt> - The date and time of the Tweet, in ISO 8601 format or a Unix timestamp</li>
138 </ul>
139 </p>
140
141 <p>
142 Each parameter should be properly URL-encoded when used as the URL for the iframe. An example using PHP:
143 </p>
144
145 <p>
146<pre>
147<?php
148 $tf = "https://tf.rita.moe/show?" . http_build_query(array(
149 "url" => "https://twitter.com/jack/status/20",
150 "tweet" => "just setting up my twttr",
151 "author_name" => "Jack Dorsey",
152 "author_username" => "jack",
153 "datetime" => "1142974214",
154 ));
155
156 echo "<iframe border=\"0\" frameborder=\"0\" height=\"250\" width=\"550\" "
157 . "src=\"" . $tf . "\"></iframe>";
158?>
159</pre>
160 </p>
161
162 <p>
163 If Twitter's Javascript could not be loaded, this example would produce the following (without the gray background):
164 </p>
165
166 <p>
167 <iframe
168 border="0"
169 class="gray"
170 frameborder="0"
171 height="300"
172 src="https://tf.rita.moe/show?url=https%3A%2F%2Ftwitter.com%2Fjack%2Fstatus%2F20&tweet=just+setting+up+my+twttr&author_name=Jack+Dorsey&author_username=jack&datetime=1142974214&force_fail=1"
173 width="550"
174 ></iframe>
175 </p>
176
177 <h3>Styling</h3>
178
179 <p>
180 The following optional parameters may be passed to affect the style of the embedded Tweet.
181 These are passed directly through to Twitter's Javascript.
182 </p>
183
184 <p>
185 <ul>
186 <li>
187 <tt style="color: green;">align</tt>
188 - Alignment of the embedded Tweet inside the iframe - can be
189 <tt style="color: green;">left</tt>,
190 <tt style="color: green;">center</tt>, or
191 <tt style="color: green;">right</tt>
192 </li>
193
194 <li>
195 <tt style="color: green;">link_color</tt>
196 - Hex code for link color
197 </li>
198
199 <li>
200 <tt style="color: green;">theme</tt>
201 - <a
202 rel="noopener noreferrer"
203 target="_blank"
204 href="https://dev.twitter.com/web/embedded-tweets/parameters"
205 >Theme</a> of Tweet display (such as <tt>dark</tt>)
206 </li>
207
208 <li>
209 <tt style="color: green;">conversation</tt>
210 - Disable showing previous Tweet in a thread when set to <tt>none</tt>
211 </li>
212
213 <li>
214 <tt style="color: green;">cards</tt>
215 - Disable showing media previews when set to <tt>hidden</tt>
216 </li>
217
218 <li>
219 <tt style="color: green;">lang</tt>
220 - Language code for the interface (such as <tt>en</tt>)
221 </li>
222 </ul>
223 </p>
224
225 <h3 id="sizing">Sizing</h3>
226
227 <p>
228 As with any iframe, its height and width within the parent document are static, and must be included as attributes in the
229 <tt><iframe></tt> tag or applied with CSS. Reasonable recommendations to display most Tweets (without embedded media)
230 without scrolling are <tt>height="300"</tt> and <tt>width="550"</tt>.
231 To automatically resize the height of the iframe after it has loaded, some Javascript is required.
232 </p>
233
234 <p>
235 Since a parent HTML page loading an iframe from <tt>tf.rita.moe</tt> has loaded a cross-origin resource, the parent HTML page is not
236 permitted to access the iframe's DOM to find out its height. Newer browsers implementing
237 <tt><a
238 rel="noopener noreferrer"
239 target="_blank"
240 href="https://developer.mozilla.org/en-US/docs/DOM/window.postMessage"
241 >window.postMessage</a></tt>
242 can send a message to the tf.rita.moe iframe (which it is listening for) and request its height after Twitter's Javascript loads.
243 <tt>tf.rita.moe</tt> will send a response message with the height after it has loaded the Twitter content.
244 </p>
245
246 <p>
247 Using Javascript, the following code will send a message to each <tt><iframe></tt> element on the page that you have named like
248 "<tt>tweet_281974362784022528</tt>":
249 </p>
250
251 <p>
252<pre>
253document.addEventListener('DOMContentLoaded', () => {
254 // Find all iframes with ids starting with "tweet_"
255 const tweetIframes = document.querySelectorAll('iframe[id^="tweet_"]')
256 tweetIframes.forEach((iframe) => {
257 iframe.addEventListener('load', () => {
258 iframe.contentWindow.postMessage(
259 {
260 element: iframe.id,
261 query: 'height'
262 },
263 'https://tf.rita.moe',
264 )
265 })
266 })
267})
268
269// Listen for the return message once the tweet has been loaded
270window.addEventListener('message', (e) => {
271 if (e.origin !== 'https://tf.rita.moe') return
272
273 const data = e.data
274 if (data?.height && data?.element?.match(/^tweet_/)) {
275 const iframe = document.getElementById(data.element)
276 if (iframe) {
277 iframe.style.height = parseInt(data.height, 10) + 'px'
278 }
279 }
280})
281</pre>
282 </p>
283
284 <p>
285 This code resizes the twitframe iframes after they have loaded, increasing the height to display the embedded card information.
286 </p>
287
288 <iframe
289 border="0"
290 frameborder="0"
291 height="300"
292 id="tweet_1291863596922806273"
293 src="https://tf.rita.moe/show?url=https%3A%2F%2Ftwitter.com%2Felonmusk%2Fstatus%2F1604617643973124097&conversation=none"
294 width="550"
295 ></iframe>
296
297 <script>
298 document.addEventListener('DOMContentLoaded', () => {
299 // Find all iframes with ids starting with "tweet_"
300 const tweetIframes = document.querySelectorAll('iframe[id^="tweet_"]')
301 tweetIframes.forEach((iframe) => {
302 iframe.addEventListener('load', () => {
303 iframe.contentWindow.postMessage(
304 {
305 element: iframe.id,
306 query: 'height'
307 },
308 'https://tf.rita.moe',
309 )
310 })
311 })
312 })
313
314 // Listen for the return message once the tweet has been loaded
315 window.addEventListener('message', (e) => {
316 if (e.origin !== 'https://tf.rita.moe') return
317
318 const data = e.data
319 if (data?.height && data?.element?.match(/^tweet_/)) {
320 const iframe = document.getElementById(data.element)
321 if (iframe) {
322 iframe.style.height = parseInt(data.height, 10) + 'px'
323 }
324 }
325 })
326 </script>
327</body>
328</html>