Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: chrome/common/extensions/docs/examples/extensions/news_a11y/feed.html

Issue 8309001: Adding `content_security_policy` to a few sample extensions. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: pageAction/pageaction_by_url Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <style> 4 <link href="feed.css" rel="stylesheet" type="text/css">
5 body { 5 <script id="iframe_script" type="text/not-javascript-i-swear">
Boris Smus 2011/10/18 21:51:38 How come we're doing this? Also, we should use an
Mike West 2011/10/19 09:43:57 We're doing this because I was too lazy to rewrite
6 font-family: helvetica, arial, sans-serif; 6 function reportHeight() {
7 font-size: 12px; 7 var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}) ;
8 overflow: hidden; 8 parent.postMessage(msg, "*");
9 } 9 }
10 10
11 a { 11 function frameLoaded() {
12 color:#0000CC; 12 var links = document.getElementsByTagName("A");
13 text-decoration: underline; 13 for (i = 0; i < links.length; i++) {
14 cursor: pointer; 14 var c = links[i].className;
15 } 15 if (c != "item_title" && c != "open_box") {
16 links[i].addEventListener("click", showStory);
17 }
18 }
19 window.addEventListener("message", messageHandler);
20 }
16 21
17 .open_box { 22 function showStory(event) {
18 display: block; 23 var href = event.currentTarget.href;
19 overflow: hidden; 24 parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
20 margin-right: 4px; 25 event.preventDefault();
21 margin-top: 2px; 26 }
22 height: 12px;
23 width: 12px;
24 float: left;
25 clear: left;
26 background-image: url(sprite_arrows.gif);
27 background-position: 0px -24px;
28 cursor: pointer;
29 }
30 27
31 .opened .open_box { 28 function messageHandler(event) {
32 background-position:-12px -24px; 29 reportHeight();
33 }
34
35 .item {
36 padding: 2px 0px;
37 }
38
39 .item_title {
40 display: block;
41 min-width: 300px;
42 padding-left: 15px;
43 cursor: pointer;
44 }
45
46 .item_desc {
47 min-width: 500px;
48 height: 0px;
49 display: block;
50 border: none;
51 padding: 0px;
52 margin: 0px;
53 -webkit-transition: height 0.2s ease-out;
54 }
55
56 #title {
57 display: block;
58 margin-left: auto;
59 }
60
61 .error {
62 white-space: nowrap;
63 color: red;
64 }
65
66 .more {
67 display: block;
68 text-align: right;
69 padding-top: 20px;
70 padding-right: 10px;
71 color: #88C;
72 }
73
74 </style>
75 <script id="iframe_script">
76 function reportHeight() {
77 var msg = JSON.stringify({type:"size", size:document.body.offsetHeight});
78 parent.postMessage(msg, "*");
79 }
80
81 function frameLoaded() {
82 var links = document.getElementsByTagName("A");
83 for (i = 0; i < links.length; i++) {
84 var class = links[i].className;
85 if (class != "item_title" && class != "open_box") {
86 links[i].addEventListener("click", showStory);
87 }
88 }
89 window.addEventListener("message", messageHandler);
90 }
91
92 function showStory(event) {
93 var href = event.currentTarget.href;
94 parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
95 event.preventDefault();
96 }
97
98 function messageHandler(event) {
99 reportHeight();
100 }
101
102 </script>
103 <script>
104 // Feed URL.
105 var feedUrl = 'http://news.google.com/?output=rss';
106
107 // The XMLHttpRequest object that tries to load and parse the feed.
108 var req;
109
110 function main() {
111 req = new XMLHttpRequest();
112 req.onload = handleResponse;
113 req.onerror = handleError;
114 req.open("GET", feedUrl, true);
115 req.send(null);
116 }
117
118 // Handles feed parsing errors.
119 function handleFeedParsingFailed(error) {
120 var feed = document.getElementById("feed");
121 feed.className = "error";
122 feed.innerText = "Error: " + error;
123 }
124
125 // Handles errors during the XMLHttpRequest.
126 function handleError() {
127 handleFeedParsingFailed('Failed to fetch RSS feed.');
128 }
129
130 // Handles parsing the feed data we got back from XMLHttpRequest.
131 function handleResponse() {
132 var doc = req.responseXML;
133 if (!doc) {
134 handleFeedParsingFailed("Not a valid feed.");
135 return;
136 }
137 buildPreview(doc);
138 }
139
140 // The maximum number of feed items to show in the preview.
141 var maxFeedItems = 5;
142
143 // Where the more stories link should navigate to.
144 var moreStoriesUrl;
145
146 function buildPreview(doc) {
147 // Get the link to the feed source.
148 var link = doc.getElementsByTagName("link");
149 var parentTag = link[0].parentNode.tagName;
150 if (parentTag != "item" && parentTag != "entry") {
151 moreStoriesUrl = link[0].textContent;
152 }
153
154 // Setup the title image.
155 var images = doc.getElementsByTagName("image");
156 var titleImg;
157 if (images.length != 0) {
158 var urls = images[0].getElementsByTagName("url");
159 if (urls.length != 0) {
160 titleImg = urls[0].textContent;
161 }
162 }
163 var img = document.getElementById("title");
164 // Listen for mouse and key events
165 if (titleImg) {
166 img.src = titleImg;
167 if (moreStoriesUrl) {
168 document.getElementById("title_a").addEventListener("click", » moreStories);
169 document.getElementById("title_a").addEventListener("keydown",
170 function(event) {
171 if (event.keyCode == 13) {
172 moreStories(event);
173 }});
174 }
175 } else {
176 img.style.display = "none";
177 }
178
179 // Construct the iframe's HTML.
180 var iframe_src = "<!doctype html><html><head><script>" +
181 document.getElementById("iframe_script").textContent + "<" +
182 "/script></head><body onload='frameLoaded();' " +
183 "style='padding:0px;margin:0px;'>";
184
185 var feed = document.getElementById("feed");
186 // Set ARIA role indicating the feed element has a tree structure
187 feed.setAttribute("role", "tree");
188
189 var entries = doc.getElementsByTagName('entry');
190 if (entries.length == 0) {
191 entries = doc.getElementsByTagName('item');
192 }
193 var count = Math.min(entries.length, maxFeedItems);
194 for (var i = 0; i < count; i++) {
195 item = entries.item(i);
196
197 // Grab the title for the feed item.
198 var itemTitle = item.getElementsByTagName('title')[0];
199 if (itemTitle) {
200 itemTitle = itemTitle.textContent;
201 } else {
202 itemTitle = "Unknown title";
203 }
204
205 // Grab the description.
206 var itemDesc = item.getElementsByTagName('description')[0];
207 if (!itemDesc) {
208 itemDesc = item.getElementsByTagName('summary')[0];
209 if (!itemDesc) {
210 itemDesc = item.getElementsByTagName('content')[0];
211 } 30 }
212 } 31 </script>
213 if (itemDesc) { 32 <script src="feed.js"></script>
214 itemDesc = itemDesc.childNodes[0].nodeValue; 33 </head>
215 } else { 34 <body>
216 itemDesc = ''; 35 <a id="title_a" tabIndex="0"><img id='title' alt="Google News logo"></a>
217 } 36 <div id="feed"></div>
218 37 </body>
219 var item = document.createElement("div");
220 item.className = "item";
221 var box = document.createElement("div");
222 box.className = "open_box";
223 box.addEventListener("click", showDesc);
224 // Disable focusing on box image separately from rest of tree item
225 box.tabIndex = -1;
226 item.appendChild(box);
227
228 var title = document.createElement("a");
229 title.className = "item_title";
230 // Give title an ID for use with ARIA
231 title.id = "item" + i;
232 title.innerText = itemTitle;
233 title.addEventListener("click", showDesc);
234 title.addEventListener("keydown", keyHandlerShowDesc);
235 // Update aria-activedescendant property in response to focus change
236 // within the tree
237 title.addEventListener("focus", function(event) {
238 feed.setAttribute(
239 "aria-activedescendant", this.id);
240 });
241 // Enable keyboard focus on the item title element
242 title.tabIndex = 0;
243 // Set ARIA role role indicating that the title element is a node in the
244 // tree structure
245 title.setAttribute("role", "treeitem");
246 // Set the ARIA state indicating this tree item is currently collapsed.
247 title.setAttribute("aria-expanded", "false");
248 // Set ARIA property indicating that all items are at the same hierarchical
249 // level (no nesting)
250 title.setAttribute("aria-level", "1");
251 item.appendChild(title);
252
253 var desc = document.createElement("iframe");
254 desc.scrolling = "no";
255 desc.className = "item_desc";
256 // Disable keyboard focus on elements in iFrames that have not been
257 // displayed yet
258 desc.tabIndex = -1;
259
260 item.appendChild(desc);
261 feed.appendChild(item);
262
263 // The story body is created as an iframe with a data: URL in order to
264 // isolate it from this page and protect against XSS. As a data URL, it
265 // has limited privileges and must communicate back using postMessage().
266 desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>";
267 }
268
269 if (moreStoriesUrl) {
270 var more = document.createElement("a");
271 more.className = "more";
272 more.innerText = "More stories \u00BB";
273 more.tabIndex = 0;
274 more.addEventListener("click", moreStories);
275 more.addEventListener("keydown", function(event) {
276 if (event.keyCode == 13) {
277 moreStories(event);
278 }});
279 feed.appendChild(more);
280 }
281 }
282
283 // Show |url| in a new tab.
284 function showUrl(url) {
285 // Only allow http and https URLs.
286 if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
287 return;
288 }
289 chrome.tabs.create({url: url});
290 }
291
292 function moreStories(event) {
293 showUrl(moreStoriesUrl);
294 }
295
296 function keyHandlerShowDesc(event) {
297 // Display content under heading when spacebar or right-arrow pressed
298 // Hide content when spacebar pressed again or left-arrow pressed
299 // Move to next heading when down-arrow pressed
300 // Move to previous heading when up-arrow pressed
301 if (event.keyCode == 32) {
302 showDesc(event);
303 } else if ((this.parentNode.className == "item opened") &&
304 (event.keyCode == 37)) {
305 showDesc(event);
306 } else if ((this.parentNode.className == "item") && (event.keyCode == 39)) {
307 showDesc(event);
308 } else if (event.keyCode == 40) {
309 if (this.parentNode.nextSibling) {
310 this.parentNode.nextSibling.children[1].focus();
311 }
312 } else if (event.keyCode == 38) {
313 if (this.parentNode.previousSibling) {
314 this.parentNode.previousSibling.children[1].focus();
315 }
316 }
317 }
318
319 function showDesc(event) {
320 var item = event.currentTarget.parentNode;
321 var items = document.getElementsByClassName("item");
322 for (var i = 0; i < items.length; i++) {
323 var iframe = items[i].getElementsByClassName("item_desc")[0];
324 if (items[i] == item && items[i].className == "item") {
325 items[i].className = "item opened";
326 iframe.contentWindow.postMessage("reportHeight", "*");
327 // Set the ARIA state indicating the tree item is currently expanded.
328 items[i].getElementsByClassName("item_title")[0].
329 setAttribute("aria-expanded", "true");
330 iframe.tabIndex = 0;
331 } else {
332 items[i].className = "item";
333 iframe.style.height = "0px";
334 // Set the ARIA state indicating the tree item is currently collapsed.
335 items[i].getElementsByClassName("item_title")[0].
336 setAttribute("aria-expanded", "false");
337 iframe.tabIndex = -1;
338 }
339 }
340 }
341
342 function iframeMessageHandler(e) {
343 // Only listen to messages from one of our own iframes.
344 var iframes = document.getElementsByTagName("IFRAME");
345 for (var i = 0; i < iframes.length; i++) {
346 if (iframes[i].contentWindow == e.source) {
347 var msg = JSON.parse(e.data);
348 if (msg) {
349 if (msg.type == "size") {
350 iframes[i].style.height = msg.size + "px";
351 } else if (msg.type == "show") {
352 var url = msg.url;
353 if (url.indexOf("http://news.google.com") == 0) {
354 // If the URL is a redirect URL, strip of the destination and go to
355 // that directly. This is necessary because the Google news
356 // redirector blocks use of the redirects in this case.
357 var index = url.indexOf("&url=");
358 if (index >= 0) {
359 url = url.substring(index + 5);
360 index = url.indexOf("&");
361 if (index >= 0)
362 url = url.substring(0, index);
363 }
364 }
365 showUrl(url);
366 }
367 }
368 return;
369 }
370 }
371 }
372
373 window.addEventListener("message", iframeMessageHandler);
374 </script>
375 </head>
376 <body onload="main();">
377 <a id="title_a" tabIndex="0"><img id='title' alt="Google News logo"></a>
378 <div id="feed"></div>
379 </body>
380 </html> 38 </html>
381 39
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698