diff options
author | kurrik@chromium.org <kurrik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-15 06:31:08 +0000 |
---|---|---|
committer | kurrik@chromium.org <kurrik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-15 06:31:08 +0000 |
commit | 60a761c6a38e1311cd26be4afa8e253259dc4570 (patch) | |
tree | dc1c59aa2f847d6b88a85c7f57c724507fa900c4 | |
parent | 46648d3a6cac794efa4129f84c56562f32accef7 (diff) | |
download | chromium_src-60a761c6a38e1311cd26be4afa8e253259dc4570.zip chromium_src-60a761c6a38e1311cd26be4afa8e253259dc4570.tar.gz chromium_src-60a761c6a38e1311cd26be4afa8e253259dc4570.tar.bz2 |
Improvements to the Google News extension.
* Patch by anujb
BUG=None
TEST=None
TBR=kathyw
Review URL: http://codereview.chromium.org/3681008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66100 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 1486 insertions, 318 deletions
diff --git a/chrome/common/extensions/docs/examples/extensions/news.zip b/chrome/common/extensions/docs/examples/extensions/news.zip Binary files differdeleted file mode 100644 index cab4e3a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news.zip +++ /dev/null diff --git a/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json new file mode 100644 index 0000000..97e07c1 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json @@ -0,0 +1,102 @@ +{ + "extName": { + "message": "News Reader (by Google)" + }, + "extDesc": { + "message": "Displays the latest stories from Google News in a popup." + }, + "ext_default_title": { + "message": "Google News" + }, + + "1": { + "message": "Top Stories" + }, + "n": { + "message": "Nation" + }, + "w": { + "message": "World" + }, + "b": { + "message": "Business" + }, + "t": { + "message": "Science/Technology" + }, + "e": { + "message": "Entertainment" + }, + "s": { + "message": "Sports" + }, + "m": { + "message": "Health" + }, + "po": { + "message": "Most Popular" + }, + + "options": { + "message": "Options" + }, + "more_stories": { + "message": "More stories" + }, + + "direction": { + "message": "ltr" + }, + + "country": { + "message": "Country:" + }, + "topic": { + "message": "Topics:" + }, + "save": { + "message": "Save" + }, + "saveStatus": { + "message": "Options saved" + }, + "storyCount": { + "message": "Number of stories:" + }, + "newsOption": { + "message": "Google News Options" + }, + "customText": { + "message": "Custom Topics:" + }, + "maximumTopics": { + "message": "(Maximum $count$)", + "placeholders": { + "count": { + "content": "$1" + } + } + }, + "submitButton": { + "message": "Add" + }, + "deleteTitle": { + "message": "Delete" + }, + "invalidChars": { + "message": "Invalid character(s)" + }, + "noTopic": { + "message": "At least one Topic must be selected" + }, + + "fetchError": { + "message": "Error: Failed to fetch news stories." + }, + "wrongTopic": { + "message": "Error: Not a valid feed." + }, + "noStory": { + "message": "No story right now" + } +} diff --git a/chrome/common/extensions/docs/examples/extensions/news/css/feed.css b/chrome/common/extensions/docs/examples/extensions/news/css/feed.css new file mode 100644 index 0000000..49edf8f --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/css/feed.css @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. + * + * Sets style of different elements in pop-up page. + * + * Author: navneetg@google.com (Navneet Goel). + */ + +body { + font-family: arial, sans-serif; + font-size: 12px; + min-width: 500px; + overflow: visible; +} +a { + color: #0000CC; + cursor: pointer; + text-decoration: underline; +} +#noStories { + background-color: rgb(255, 238, 136); + font-size: 13px; + font-weight: bold; + margin-left: 140px; + margin-right: 140px; + text-align: center; +} +.open_box { + background-image: url(/images/sprite_arrows.gif); + background-position: 0px -24px; + clear: left; + cursor: pointer; + display: block; + height: 12px; + margin-top: 2px; + overflow: hidden; + width: 12px; + float: left; +} +.opened .open_box { + background-position: -12px -24px; +} +.item { + padding: 2px 0; +} +.item_title { + cursor: pointer; + display: block; + min-width: 300px; + padding: 0 0 0 17px; +} +.item_desc { + border: none; + display: block; + height: 0; + margin: 0; + min-width: 500px; + padding: 0; + -webkit-transition: height 0.2s ease-out; +} +#title { + display: block; +} +.error { + background-color: rgb(255, 238, 136); + font-size: 13px; + font-weight: bold; + margin-left: 125px; + margin-right: 125px; + text-align: center; + white-space: nowrap; +} +.more { + color: #88C; + display: block; + margin-left: 385px; + padding-right: 10px; + padding-top: 5px; + text-align: right; +} +.topicsLTR { + direction: ltr; + font-size: 13px; + padding-left: 5px; +} +.topicsRTL { + direction: rtl; + font-size: 13px; + padding-right: 5px; +} +body.rtl #feed { + direction: rtl; +} +body.rtl .open_box { + float: right; +} +body.rtl .item_title { + padding: 0 17px 0 0; +} diff --git a/chrome/common/extensions/docs/examples/extensions/news/css/options.css b/chrome/common/extensions/docs/examples/extensions/news/css/options.css new file mode 100644 index 0000000..91aff7e --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/css/options.css @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. + * + * Sets style of different elements in options page. + * + * Author: navneetg@google.com (Navneet Goel). + */ + +@CHARSET "UTF-8"; +body { + background-color: rgb(235, 239, 249); + font-family: arial , sans-serif; + font-size: 13px; +} +.suppr { + background-image: url(/images/delete-icon.png); + background-repeat: no-repeat; + cursor: pointer; + display: inline; + float: left; + height: 17px; + margin-top: 3px; + overflow: hidden; + width: 14px; +} +.checkBoxTopic { + float: left; + padding-left: 2px; + padding-top: 1px; +} +.checkBox { + float: left; +} +.boxAndTopic { + overflow: auto; + padding-bottom: 5px; +} +#invalid_status, #save_status { + background-color: rgb(255, 241, 168); + font-weight: bold; + margin-left: 10px; + opacity: 0; + padding-bottom: 3px; + padding-left: 7px; + padding-right: 7px; + padding-top: 3px; +} +#all_content { + background-color: white; + border-bottom-left-radius: 12px 12px; + border-bottom-right-radius: 12px 12px; + border-color: #B5C7DE; + border-style: solid; + border-top-left-radius: 12px 12px; + border-top-right-radius: 12px 12px; + border-width: 4px; + margin: 40px auto 20px; + padding: 12px; + width: 600px; +} +.col2 { + padding-left: 20px; +} +body.rtl .col1, body.rtl .col2 { + text-align: right; +} +body.rtl { + direction: rtl; +} +body.rtl .col2 { + padding-right: 20px; +} +body.rtl .checkBox, body.rtl .checkBoxTopic { + float: right; +} +body.rtl table.contentTable { + margin:0 55px 0 0; +} +body.rtl #save_div{ + margin: 0 220px 0 0; +} +body.rtl #countryList{ + margin:0 5px 0 0; +} +.col1 { + padding-top: 3px; + width: 115px; +} +.all_rows { + height: 35px; + vertical-align: top; +} +body.rtl .cusTopicsClass { + float: right; +} +.cusTopicsClass { + float: left; + width: 225px; +} +#save_div { + margin-left: 220px; +} +#countryList { + padding-left: 5px; +} +#logo { + font-size: 15px; + font-weight: bold; + text-align: center; +} +.noborder { + border: 0; + font-family: arial, sans-serif; + height: 15px; + outline: none; + overflow: hidden; + resize: none; + width:205px; +} diff --git a/chrome/common/extensions/docs/examples/extensions/news/feed.html b/chrome/common/extensions/docs/examples/extensions/news/feed.html deleted file mode 100644 index 6592a87..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/feed.html +++ /dev/null @@ -1,310 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<style> -body { - font-family: helvetica, arial, sans-serif; - font-size: 12px; - overflow: hidden; -} - -a { - color:#0000CC; - text-decoration: underline; - cursor: pointer; -} - -.open_box { - display: block; - overflow: hidden; - margin-right: 4px; - margin-top: 2px; - height: 12px; - width: 12px; - float: left; - clear: left; - background-image: url(sprite_arrows.gif); - background-position: 0px -24px; - cursor: pointer; -} - -.opened .open_box { - background-position:-12px -24px; -} - -.item { - padding: 2px 0px; -} - -.item_title { - display: block; - min-width: 300px; - padding-left: 15px; - cursor: pointer; -} - -.item_desc { - min-width: 500px; - height: 0px; - display: block; - border: none; - padding: 0px; - margin: 0px; - -webkit-transition: height 0.2s ease-out; -} - -#title { - display: block; - margin-left: auto; -} - -.error { - white-space: nowrap; - color: red; -} - -.more { - display: block; - text-align: right; - padding-top: 20px; - padding-right: 10px; - color: #88C; -} - -</style> -<script id="iframe_script"> -function reportHeight() { - var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}); - parent.postMessage(msg, "*"); -} - -function frameLoaded() { - var links = document.getElementsByTagName("A"); - for (i = 0; i < links.length; i++) { - var class = links[i].className; - if (class != "item_title" && class != "open_box") { - links[i].addEventListener("click", showStory); - } - } - window.addEventListener("message", messageHandler); -} - -function showStory(event) { - var href = event.currentTarget.href; - parent.postMessage(JSON.stringify({type:"show", url:href}), "*"); - event.preventDefault(); -} - -function messageHandler(event) { - reportHeight(); -} - -</script> -<script> -// Feed URL. -var feedUrl = 'http://news.google.com/?output=rss'; - -// The XMLHttpRequest object that tries to load and parse the feed. -var req; - -function main() { - req = new XMLHttpRequest(); - req.onload = handleResponse; - req.onerror = handleError; - req.open("GET", feedUrl, true); - req.send(null); -} - -// Handles feed parsing errors. -function handleFeedParsingFailed(error) { - var feed = document.getElementById("feed"); - feed.className = "error"; - feed.innerText = "Error: " + error; -} - -// Handles errors during the XMLHttpRequest. -function handleError() { - handleFeedParsingFailed('Failed to fetch RSS feed.'); -} - -// Handles parsing the feed data we got back from XMLHttpRequest. -function handleResponse() { - var doc = req.responseXML; - if (!doc) { - handleFeedParsingFailed("Not a valid feed."); - return; - } - buildPreview(doc); -} - -// The maximum number of feed items to show in the preview. -var maxFeedItems = 5; - -// Where the more stories link should navigate to. -var moreStoriesUrl; - -function buildPreview(doc) { - // Get the link to the feed source. - var link = doc.getElementsByTagName("link"); - var parentTag = link[0].parentNode.tagName; - if (parentTag != "item" && parentTag != "entry") { - moreStoriesUrl = link[0].textContent; - } - - // Setup the title image. - var images = doc.getElementsByTagName("image"); - var titleImg; - if (images.length != 0) { - var urls = images[0].getElementsByTagName("url"); - if (urls.length != 0) { - titleImg = urls[0].textContent; - } - } - var img = document.getElementById("title"); - if (titleImg) { - img.src = titleImg; - if (moreStoriesUrl) { - document.getElementById("title_a").addEventListener("click", moreStories); - } - } else { - img.style.display = "none"; - } - - // Construct the iframe's HTML. - var iframe_src = "<!doctype html><html><head><script>" + - document.getElementById("iframe_script").textContent + "<" + - "/script></head><body onload='frameLoaded();' " + - "style='padding:0px;margin:0px;'>"; - - var feed = document.getElementById("feed"); - var entries = doc.getElementsByTagName('entry'); - if (entries.length == 0) { - entries = doc.getElementsByTagName('item'); - } - var count = Math.min(entries.length, maxFeedItems); - for (var i = 0; i < count; i++) { - item = entries.item(i); - - // Grab the title for the feed item. - var itemTitle = item.getElementsByTagName('title')[0]; - if (itemTitle) { - itemTitle = itemTitle.textContent; - } else { - itemTitle = "Unknown title"; - } - - // Grab the description. - var itemDesc = item.getElementsByTagName('description')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('summary')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('content')[0]; - } - } - if (itemDesc) { - itemDesc = itemDesc.childNodes[0].nodeValue; - } else { - itemDesc = ''; - } - - var item = document.createElement("div"); - item.className = "item"; - var box = document.createElement("div"); - box.className = "open_box"; - box.addEventListener("click", showDesc); - item.appendChild(box); - - var title = document.createElement("a"); - title.className = "item_title"; - title.innerText = itemTitle; - title.addEventListener("click", showDesc); - item.appendChild(title); - - var desc = document.createElement("iframe"); - desc.scrolling = "no"; - desc.className = "item_desc"; - item.appendChild(desc); - feed.appendChild(item); - - // The story body is created as an iframe with a data: URL in order to - // isolate it from this page and protect against XSS. As a data URL, it - // has limited privileges and must communicate back using postMessage(). - desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>"; - } - - if (moreStoriesUrl) { - var more = document.createElement("a"); - more.className = "more"; - more.innerText = "More stories \u00BB"; - more.addEventListener("click", moreStories); - feed.appendChild(more); - } -} - -// Show |url| in a new tab. -function showUrl(url) { - // Only allow http and https URLs. - if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) { - return; - } - chrome.tabs.create({url: url}); -} - -function moreStories(event) { - showUrl(moreStoriesUrl); -} - -function showDesc(event) { - var item = event.currentTarget.parentNode; - var items = document.getElementsByClassName("item"); - for (var i = 0; i < items.length; i++) { - var iframe = items[i].getElementsByClassName("item_desc")[0]; - if (items[i] == item && items[i].className == "item") { - items[i].className = "item opened"; - iframe.contentWindow.postMessage("reportHeight", "*"); - } else { - items[i].className = "item"; - iframe.style.height = "0px"; - } - } -} - -function iframeMessageHandler(e) { - // Only listen to messages from one of our own iframes. - var iframes = document.getElementsByTagName("IFRAME"); - for (var i = 0; i < iframes.length; i++) { - if (iframes[i].contentWindow == e.source) { - var msg = JSON.parse(e.data); - if (msg) { - if (msg.type == "size") { - iframes[i].style.height = msg.size + "px"; - } else if (msg.type == "show") { - var url = msg.url; - if (url.indexOf("http://news.google.com") == 0) { - // If the URL is a redirect URL, strip of the destination and go to - // that directly. This is necessary because the Google news - // redirector blocks use of the redirects in this case. - var index = url.indexOf("&url="); - if (index >= 0) { - url = url.substring(index + 5); - index = url.indexOf("&"); - if (index >= 0) - url = url.substring(0, index); - } - } - showUrl(url); - } - } - return; - } - } -} - -window.addEventListener("message", iframeMessageHandler); -</script> -</head> -<body onload="main();"> -<a id="title_a"><img id='title'></a> -<div id="feed"></div> -</body> -</html> diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png b/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png Binary files differnew file mode 100644 index 0000000..c81c585 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png b/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png Binary files differnew file mode 100644 index 0000000..732b36e --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/fb.png b/chrome/common/extensions/docs/examples/extensions/news/images/fb.png Binary files differnew file mode 100644 index 0000000..b6cba93 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/images/fb.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/news.gif b/chrome/common/extensions/docs/examples/extensions/news/images/news.gif Binary files differnew file mode 100644 index 0000000..2d8df79 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/images/news.gif diff --git a/chrome/common/extensions/docs/examples/extensions/news/news_action.png b/chrome/common/extensions/docs/examples/extensions/news/images/news_action.png Binary files differindex 24b0ca7..24b0ca7 100644 --- a/chrome/common/extensions/docs/examples/extensions/news/news_action.png +++ b/chrome/common/extensions/docs/examples/extensions/news/images/news_action.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/news_icon.png b/chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png Binary files differindex 42da406..42da406 100644 --- a/chrome/common/extensions/docs/examples/extensions/news/news_icon.png +++ b/chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/sprite_arrows.gif b/chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif Binary files differindex 4560faf..4560faf 100644 --- a/chrome/common/extensions/docs/examples/extensions/news/sprite_arrows.gif +++ b/chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png b/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png Binary files differnew file mode 100644 index 0000000..111f3f4 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js new file mode 100644 index 0000000..f4cc99a --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js @@ -0,0 +1,388 @@ +/** + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. + */ + +/** + * @fileoverview This file retrieves news feed and shows news in pop-up + * page according to country, topics and no. of stories selected in the + * option page. + */ + +// Store value retrieved from locale. +var moreStoriesLocale = chrome.i18n.getMessage('more_stories') + ' \u00BB '; +var directionLocale = chrome.i18n.getMessage('direction'); + +// Feed URL. +var feedUrl = DEFAULT_NEWS_URL; + +//The XMLHttpRequest object that tries to load and parse the feed. +var req; + +/** + * Sends request to Google News server + */ +function main() { + req = new XMLHttpRequest(); + req.onload = handleResponse; + req.onerror = handleError; + req.open('GET', feedUrl, true); + req.send(null); +} + +/** + * Handles feed parsing errors. + * @param {String} error The localized error message. + */ +function handleFeedParsingFailed(error) { + var feed = $('feed'); + $('noStories').style.display = 'none'; + feed.className = 'error'; + feed.innerText = error; +} + +/** + * Handles errors during the XMLHttpRequest. + */ +function handleError() { + handleFeedParsingFailed(chrome.i18n.getMessage('fetchError')); + $('topics').style.display = 'none'; +} + +/** + * Parses the feed response. + */ +function handleResponse() { + var doc = req.responseXML; + if (!doc) { + handleFeedParsingFailed(chrome.i18n.getMessage('wrongTopic')); + var img = $('title'); + if(!img.src) { + img.src = "/images/news.gif"; + } + + document.querySelector('body').style.minHeight = 0; + return; + } + buildPreview(doc); +} + +// Stores no. of stories selected in options page. +var maxFeedItems = (window.localStorage.getItem('count')) ? + window.localStorage.getItem('count') : 5; + +// Where the more stories link should navigate to. +var moreStoriesUrl; + +/** + * Generates news iframe in pop-up page by parsing retrieved feed. + * @param {HTMLDocument} doc HTML Document received in feed. + */ +function buildPreview(doc) { + // Get the link to the feed source. + var link = doc.querySelector('link'); + var parentTag = link.parentNode.tagName; + if (parentTag != 'item' && parentTag != 'entry') { + moreStoriesUrl = link.textContent; + } + + // Setup the title image. + var image = doc.querySelector('image'); + var titleImg; + + // Stores whether language script is Right to Left or not for setting style + // of share buttons(Facebook, Twitter and Google Buzz) in iframe. + var isRtl = 'lTR'; + + if (image) { + var url = image.querySelector('url'); + if (url) { + titleImg = url.textContent; + + // Stores URL of title image to be shown on pop-up page. + var titleImgUrl = titleImg; + var pattern = /ar_/gi; + var result = titleImgUrl.match(pattern); + if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) { + isRtl = 'rTL'; + } + } + } + + var img = $('title'); + if (titleImg) { + img.src = titleImg; + if (moreStoriesUrl) { + $('title_a').addEventListener('click', moreStories); + } + } else { + img.style.display = 'none'; + } + + // Construct the iframe's HTML. + var iframe_src = '<!doctype html><html><head><script>' + + $('iframe_script').textContent + '<' + + '/script><style> ' + + '.rTL {margin-right: 102px; text-align: right;} ' + + '.lTR {margin-left: 102px; text-align: left;} ' + + '</style></head><body onload="frameLoaded();" ' + + 'style="padding:0px;margin:0px;">'; + + var feed = $('feed'); + feed.className = ''; + var entries = doc.getElementsByTagName('entry'); + if (entries.length == 0) { + entries = doc.getElementsByTagName('item'); + } + var count = Math.min(entries.length, maxFeedItems); + + // Stores required height by pop-up page. + var minHeight = 19; + minHeight = (minHeight * (count - 1)) + 100; + document.querySelector('body').style.minHeight = minHeight + 'px'; + $('feed').innerHTML = ''; + + for (var i = 0; i < count; i++) { + item = entries.item(i); + + // Grab the title for the feed item. + var itemTitle = item.querySelector('title'); + if (itemTitle) { + itemTitle = itemTitle.textContent; + } else { + itemTitle = 'Unknown title'; + } + + // Grab the description. + var itemDesc = item.querySelector('description'); + if (!itemDesc) { + itemDesc = item.querySelector('summary'); + if (!itemDesc) { + itemDesc = item.querySelector('content'); + } + } + if (itemDesc) { + itemDesc = itemDesc.childNodes[0].nodeValue; + + } else { + itemDesc = ''; + } + var itemLink = item.querySelector('link'); + if (itemLink) { + itemLink = itemLink.textContent; + } else { + itemLink = 'Unknown itemLink'; + } + var item = document.createElement('div'); + item.className = 'item'; + var box = document.createElement('div'); + box.className = 'open_box'; + box.addEventListener('click', showDesc); + item.appendChild(box); + + var title = document.createElement('a'); + title.className = 'item_title'; + title.innerText = itemTitle; + title.addEventListener('click', showDesc); + item.appendChild(title); + + var desc = document.createElement('iframe'); + desc.scrolling = 'no'; + desc.className = 'item_desc'; + item.appendChild(desc); + feed.appendChild(item); + + // Adds share buttons images(Facebook, Twitter and Google Buzz). + itemDesc += "<div class = '" + isRtl + "'>"; + itemDesc += "<a style='cursor: pointer' id='fb' " + + "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + + "<img src='" + chrome.extension.getURL('/images/fb.png') + "'/></a>"; + itemDesc += " <a style='cursor: pointer' id='twitter' " + + "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + + "<img src='" + chrome.extension.getURL('/images/twitter.png') + "'/></a>"; + itemDesc += " <a style='cursor: pointer' id='buzz' " + + "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + + "<img src='" + chrome.extension.getURL('/images/buzz.png') + "'/></a>"; + itemDesc += '</div>'; + + // The story body is created as an iframe with a data: URL in order to + // isolate it from this page and protect against XSS. As a data URL, it + // has limited privileges and must communicate back using postMessage(). + desc.src = 'data:text/html;charset=utf-8,' + iframe_src + itemDesc + + '</body></html>'; + } + if (moreStoriesUrl && entries.length != 0) { + var more = document.createElement('a'); + more.className = 'more'; + more.innerText = moreStoriesLocale; + more.addEventListener('click', moreStories); + feed.appendChild(more); + } + setStyleByLang(titleImgUrl); + + // Checks whether feed retrieved has news story or not. If not, then shows + // error message accordingly. + if (entries.length == 0) { + $('noStories').innerText = chrome.i18n.getMessage('noStory'); + $('noStories').style.display = 'block'; + } else { + $('noStories').style.display = 'none'; + } +} + +/** + * Show |url| in a new tab. + * @param {String} url The news URL. + */ +function showUrl(url) { + // Only allow http and https URLs. + if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) { + return; + } + chrome.tabs.create({url: url}); +} + +/** + * Redirects to Google news site for more stories. + * @param {Object} event Onclick event. + */ +function moreStories(event) { + showUrl(moreStoriesUrl); +} + +/** + * Shows description of the news when users clicks on news title. + * @param {Object} event Onclick event. + */ +function showDesc(event) { + var item_ = event.currentTarget.parentNode; + var items = document.getElementsByClassName('item'); + for (var i = 0, item; item = items[i]; i++) { + var iframe = item.querySelector('.item_desc'); + if (item == item_ && item.className == 'item') { + item.className = 'item opened'; + iframe.contentWindow.postMessage('reportHeight', '*'); + } else { + item.className = 'item'; + iframe.style.height = '0px'; + } + } +} + +/** + * Handles messages between different iframes and sets the display of iframe. + * @param {Object} e Onmessage event. + */ +function iframeMessageHandler(e) { + var iframes = document.getElementsByTagName('IFRAME'); + for (var i = 0, iframe; iframe = iframes[i]; i++) { + if (iframe.contentWindow == e.source) { + var msg = JSON.parse(e.data); + if (msg) { + if (msg.type == 'size') { + iframe.style.height = msg.size + 'px'; + } else if (msg.type == 'show') { + var url = msg.url; + if (url.indexOf('http://news.google.com') == 0) { + // If the URL is a redirect URL, strip of the destination and go to + // that directly. This is necessary because the Google news + // redirector blocks use of the redirects in this case. + var index = url.indexOf('&url='); + if (index >= 0) { + url = url.substring(index + 5); + index = url.indexOf('&'); + if (index >= 0) + url = url.substring(0, index); + } + } + showUrl(url); + } + } + return; + } + } +} + +/** + * Saves last viewed topic by user in local storage on unload of pop-up page. + */ +function saveLastTopic() { + var topicVal = $('topics').value; + window.localStorage.setItem('lastTopic', topicVal); +} + +/** + * Sets the URL according to selected topic(or default topic), then retrieves + * feed and sets pop-up page. + */ +function getNewsByTitle() { + var country = window.localStorage.getItem('country'); + country = (country == 'noCountry' || !country) ? '' : country; + + // Sets direction of topics showed under dropdown in pop-up page according + // to set language in browser. + $('topics').className = (directionLocale == 'rtl') ? 'topicsRTL' : + 'topicsLTR'; + + var topicVal = $('topics').value; + + // Sets Feed URL in case of custom topic selected. + var keywords = JSON.parse(window.localStorage.getItem('keywords')); + var isFound = false; + if (keywords) { + for (i = 0; i < keywords.length; i++) { + if (topicVal == keywords[i]) { + isFound = true; + feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country + '&q=' + topicVal + + '&hl=' + country; + break; + } + } + } + if (!isFound) { + feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country + + '&topic=' + topicVal; + } + main(); +} + +/** + * Shows topic list retrieved from local storage(if any),else shows + * default topics list. + */ +function getTopics() { + var topics = JSON.parse(window.localStorage.getItem('topics')); + var keywords = JSON.parse(window.localStorage.getItem('keywords')); + var element = $('topics'); + + // Sets all topics as default list if no list is found from local storage. + if (!topics && !keywords) { + topics = [' ','n','w','b','t','e','s','m','po']; + } + + if (topics) { + for (var i = 0; i < (topics.length); i++) { + var val = (topics[i] == ' ') ? '1' : topics[i]; + element.options[element.options.length] = new Option( + chrome.i18n.getMessage(val), topics[i]); + } + } + + // Shows custom topics in list(if any). + if (keywords) { + for (i = 0; i < (keywords.length); i++) { + element.options[element.options.length] = new Option(keywords[i], + keywords[i]); + } + } + + $('option_link').innerText = chrome.i18n.getMessage('options'); + + var topicVal = window.localStorage.getItem('lastTopic'); + if (topicVal) { + $('topics').value = topicVal; + } +} + +window.addEventListener('message', iframeMessageHandler); diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js new file mode 100644 index 0000000..5324a8b --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js @@ -0,0 +1,395 @@ +/** + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. + */ + +/** + * @fileoverview Includes the country selection, topics selection and + * selection of no. of news stories to be shown. Include default settings also. + * @author navneetg@google.com (Navneet Goel). + */ + +/** + * Stores number of selected topics on the options page. + */ +var checkCount = 0; + +/** + * Stores maximum count of custom topics. + */ +var MAX_CUS_TOPICS = 10; + +/** + * Stores temporary added custom topics which are not yet saved. + */ +var tempCusTopics = []; + +/** + * Checks whether ENTER key is pressed or not. + */ +function addCustomTopic() { + if (window.event.keyCode == 13) { + addCusTopic(); + } +} + +/** + * Retrieves and sets last saved country from local storage(if found), + * else sets country retrieved from feed. + */ +function setCountry() { + var country = window.localStorage.getItem('country'); + + // If country is not found in localstorage or default value is selected in + // drop down menu. + if ((!country) || country == 'noCountry') { + // XMLHttpRequest object that tries to load the feed for the purpose of + // retrieving the country value out of feed. + var req = new XMLHttpRequest(); + req.onload = handleResponse; + req.onerror = handleError; + req.open('GET', DEFAULT_NEWS_URL, true); + req.send(null); + + // Sets country to default Country in dropdown menu. + function handleError() { + $('countryList').value = 'noCountry'; + }; + + // Handles parsing the feed data got back from XMLHttpRequest. + function handleResponse() { + // Feed document retrieved from URL. + var doc = req.responseXML; + if (!doc) { + handleError(); + return; + } + var imageLink = doc.querySelector('image link'); + if (imageLink) { + // Stores link to set value of country. + var newsUrl = imageLink.textContent; + } + + // Stores country value + $('countryList').value = newsUrl.substring(newsUrl.indexOf('&ned=') + 5, + newsUrl.indexOf('&hl=')); + }; + } else { + $('countryList').value = country; + } +} + +/** + * Displays various messages to user based on user input. + * @param {String} id Id of status element. + * @param {Number} timeOut Timeout value of message shown. + * @param {String} message Message to be shown. + */ +function showUserMessages(id, timeOut, message) { + $(id).style.setProperty('-webkit-transition', + 'opacity 0s ease-in'); + $(id).style.opacity = 1; + $(id).innerText = chrome.i18n.getMessage(message); + window.setTimeout(function() { + $(id).style.setProperty( + '-webkit-transition', 'opacity' + timeOut + 's ease-in'); + $(id).style.opacity = 0; + }, 1E3 + ); +} + +/** + * Sets options page CSS according to the browser language(if found), else sets + * to default locale. + */ +function setOptionPageCSS() { + if (chrome.i18n.getMessage('direction') == 'rtl') { + document.querySelector('body').className = 'rtl'; + } +} + +/** + * Initializes the options page by retrieving country, topics and count of + * stories from local storage if present, else sets to default settings. + */ +function initialize() { + setOptionPageCSS(); + setCountry(); + setCountAndTopicList(); + setLocalizedTopicList(); + + // Adds a custom topic on press of Enter key. + $('newKeyword').onkeypress = addCustomTopic; +} + +/** + * Retrieves locale values from locale file. + */ +function setLocalizedTopicList() { + var getI18nMsg = chrome.i18n.getMessage; + + $('top').innerText = getI18nMsg('1'); + $('nation').innerText = getI18nMsg('n'); + $('world').innerText = getI18nMsg('w'); + $('business').innerText = getI18nMsg('b'); + $('science').innerText = getI18nMsg('t'); + $('entertainment').innerText = getI18nMsg('e'); + $('sports').innerText = getI18nMsg('s'); + $('health').innerText = getI18nMsg('m'); + $('most').innerText = getI18nMsg('po'); + $('select_country').innerText = getI18nMsg('country'); + $('topic').innerText = getI18nMsg('topic'); + $('save_button').innerText = getI18nMsg('save'); + $('story_count').innerText = getI18nMsg('storyCount'); + $('logo').innerHTML = $('logo').innerHTML + getI18nMsg('newsOption'); + $('custom_text').innerHTML = getI18nMsg('customText') + '<br/>' + + getI18nMsg('maximumTopics',[MAX_CUS_TOPICS]); + $('submit_button').value = getI18nMsg('submitButton'); +} + +/** + * Sets topic list and number of stories retrieved from localstorage(if any) + * otherwise sets to default. + */ +function setCountAndTopicList() { + var topicLists = document.getElementsByClassName('checkBox'); + + // Retrieves topics list from localStorage. + var topics = JSON.parse(window.localStorage.getItem('topics')); + + // Runs if retrieved topic list from local storage contains topics. + if (topics) { + for (var x = 0, topicList; topicList = topicLists[x]; x++) { + + // Saves whether checkbox is checked or not. + var isPresent = false; + for (var y = 0; y < topics.length; y++) { + if (topics[y] == topicList.value) { + topicList.checked = true; + isPresent = true; + checkCount++; + break; + } + } + if (!isPresent) { + topicList.checked = false; + } + } + } + + // Retrieves list of custom topics from localstorage(if any) and shows it + // in option page. + var keywords = JSON.parse(window.localStorage.getItem('keywords')); + if (keywords) { + + // Template to store custom topics in a table. + var template = []; + var title = chrome.i18n.getMessage('deleteTitle'); + for (var i = 0; i < keywords.length; i++) { + checkCount++; + + template.push('<tr style = "height: 22px;">'); + template.push('<td id = "keyword_value" class = "cusTopicsClass">'); + template.push('<textarea class="noborder" readonly>'); + template.push(keywords[i]); + template.push('</textarea>'); + template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); + template.push('title="'); + template.push(title); + template.push('">'); + template.push('</td>'); + template.push('</tr>'); + } + $('custom_topics').innerHTML = template.join(''); + if (keywords.length == MAX_CUS_TOPICS) { + $('submit_button').disabled = true; + $('newKeyword').readOnly = 'readonly'; + } + } + // Check all checkboxes(default settings) if no custom topic list and + // checkbox topic list from local storage is found. + if (!keywords && !topics) { + for (var x = 0, topicList; topicList = topicLists[x]; x++) { + topicList.checked = true; + checkCount++; + } + } + + // Retrieves saved value of number of stories. + var count = window.localStorage.getItem('count'); + + // Sets number of stories in dropdown. + if (count) { + $('storyCount').value = count; + } +} + +/** + * Saves checked topic list(if any), Custom topics(if any), number of + * stories and country value in local storage. + */ +function saveTopicsCountry() { + var country = $('countryList').value; + var topicLists = document.getElementsByClassName('checkBox'); + + // Contains selected number of stories. + var count = $('storyCount').value; + + // Stores checked topics list. + var topicArr = []; + for (var i = 0, topicList; topicList = topicLists[i]; i++) { + if (topicList.checked) { + topicArr.push(topicList.value); + } + } + var keywords = JSON.parse(window.localStorage.getItem('keywords')); + + // Saves custom topics to local storage(if any). + if (tempCusTopics.length > 0) { + if (keywords) { + keywords = keywords.concat(tempCusTopics); + window.localStorage.setItem('keywords', JSON.stringify(keywords)); + } else { + window.localStorage.setItem('keywords', JSON.stringify(tempCusTopics)); + } + tempCusTopics.splice(0, tempCusTopics.length); + } + + // Saves checkbox topics(if any). + if (topicArr.length > 0) { + window.localStorage.setItem('topics', JSON.stringify(topicArr)); + } else { + window.localStorage.removeItem('topics'); + } + + window.localStorage.setItem('count', count); + window.localStorage.setItem('country', country); + + showUserMessages('save_status', 0.5, 'saveStatus'); + $('save_button').disabled = true; +} + +/** + * Disables the save button on options page if no topic is selected by the user. + * @param {String} id Id of checkbox checked or unchecked. + */ +function manageCheckCount(id) { + checkCount = ($(id).checked) ? (checkCount + 1) : (checkCount - 1); + $('save_button').disabled = (checkCount == 0) ? true : false; +} + +/** + * Enables save button if at least one topic is selected. + */ +function enableSaveButton() { + if (checkCount != 0) { + $('save_button').disabled = false; + } +} + +/** + * Adds new entered custom topic. + */ +function addCusTopic() { + // Retrieves custom topic list from local storage(if any), else create new + // array list. + var keywords = JSON.parse(window.localStorage.getItem('keywords') || "[]"); + + // Adds topic only if total number of added custom topics are less than 10. + if (keywords.length + tempCusTopics.length <= (MAX_CUS_TOPICS - 1)) { + + // Stores new entered value in input textbox. + var val = $('newKeyword').value; + if (val) { + val = val.trim(); + if (val.length > 0) { + var pattern = /,/g; + + // Runs if comma(,) is not present in topic entered. + if (val.match(pattern) == null) { + checkCount++; + tempCusTopics.push(val); + + // Template to store custom topics in a table. + var template = []; + var title = chrome.i18n.getMessage('deleteTitle'); + + template.push('<tr style = "height: 22px;">'); + template.push('<td id = "keyword_value" class = "cusTopicsClass">'); + template.push('<textarea class="noborder" readonly>'); + template.push(val); + template.push('</textarea>'); + template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); + template.push('title="'); + template.push(title); + template.push('">'); + template.push('</td>'); + template.push('</tr>'); + + $('custom_topics').innerHTML += template.join(''); + enableSaveButton(); + } else { + showUserMessages('invalid_status', 2.5, 'invalidChars'); + } + } + $('newKeyword').value = ''; + } + } + + if ((keywords.length + tempCusTopics.length) == (MAX_CUS_TOPICS)) { + $('submit_button').disabled = true; + $('newKeyword').readOnly = 'readonly'; + } +} + +/** + * Delete custom topic whenever users click on delete icon. + * @param {HTMLTableColElement} obj HTML table column element to be deleted. + */ +function delCusTopic(obj) { + // Deletes only if total number of topics are greater than 1, else shows + // error message. + if (checkCount > 1) { + var value; + + // Extract custom topic value. + value = obj.parentNode.querySelector('.cusTopicsClass textarea').value; + + // Removes custom topic element from UI. + $('custom_topics').removeChild(obj.parentNode); + + // Removes custom topic element either from temporary array(if topic is + // not yet saved) or from saved topic list and saves new list to + // local storage. + var flag = 0; + for (var i = 0; i < tempCusTopics.length; i++) { + if (tempCusTopics[i] == value) { + tempCusTopics.splice(i, 1); + flag = 1; + break; + } + } + + if (flag == 0) { + var keywords = JSON.parse(window.localStorage.getItem('keywords')); + for (i = 0; i < keywords.length; i++) { + if (keywords[i] == value) { + keywords.splice(i, 1); + break; + } + } + if (keywords.length > 0) { + window.localStorage.setItem('keywords', JSON.stringify(keywords)); + } else { + window.localStorage.removeItem('keywords'); + } + } + + checkCount--; + $('submit_button').disabled = false; + } else { + showUserMessages('save_status', 2.5, 'noTopic'); + } + $('newKeyword').readOnly = false; +} diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js new file mode 100644 index 0000000..f8e3880 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. + */ + +/** + * @fileoverview Defines the constants and most commonly used functions. + * @author navneetg@google.com (Navneet Goel). + */ + +/** + * Default feed news URL. + */ +var DEFAULT_NEWS_URL = 'http://news.google.com/news?output=rss'; + +/** + * Image URL of Israel country. + */ +var ISRAEL_IMAGE_URL = 'http://www.gstatic.com/news/img/logo/iw_il/news.gif'; + +/** + * Alias for getElementById. + * @param {String} elementId Element id of the HTML element to be fetched. + * @return {Element} Element corresponding to the element id. + */ +function $(elementId) { + return document.getElementById(elementId); +} diff --git a/chrome/common/extensions/docs/examples/extensions/news/manifest.json b/chrome/common/extensions/docs/examples/extensions/news/manifest.json index f0c7e0e..cff6f2e 100644 --- a/chrome/common/extensions/docs/examples/extensions/news/manifest.json +++ b/chrome/common/extensions/docs/examples/extensions/news/manifest.json @@ -1,15 +1,18 @@ { - "name": "News Reader", - "version": "1.1", - "description": "Displays the first 5 items from the 'Google News - top news' RSS feed in a popup.", - "icons": { "128": "news_icon.png" }, + "name": "__MSG_extName__", + "version": "2.0", + "description": "__MSG_extDesc__", + "icons": { "128": "images/news_icon.png" }, + "default_locale":"en", "browser_action": { - "default_title": "Google News", - "default_icon": "news_action.png", - "popup": "feed.html" + "default_title": "__MSG_ext_default_title__", + "default_icon": "images/news_action.png", + "popup": "views/feed.html" }, "permissions": [ "tabs", "http://news.google.com/*" - ] + ], + "options_page": "views/options.html", + "background_page": "views/background.html" } diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/background.html b/chrome/common/extensions/docs/examples/extensions/news/views/background.html new file mode 100644 index 0000000..c97e977 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/views/background.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<!-- + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> + +<!-- +@fileoverview Contains script for running at the background to open up the +options page when the extension is reloaded. +--> + +<html> + <body> + <script> + //Retrieves value from local storage(if found). + var newsFlag = window.localStorage.getItem('newsFlag'); + + //Runs if extension installation is done. + if(!newsFlag) { + var optionsPageURL = chrome.extension.getURL('/views/options.html'); + chrome.tabs.create({url: optionsPageURL}); + window.localStorage.setItem('newsFlag','1'); + } + </script> + </body> +</html> diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/feed.html b/chrome/common/extensions/docs/examples/extensions/news/views/feed.html new file mode 100644 index 0000000..43d147b --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/views/feed.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<!-- + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> + +<!-- +@fileoverview This file serves as the pop-up page for showing news +according to the settings saved in options page otherwise shows default +settings. +@author navneetg@google.com (Navneet Goel). +--> + +<html> +<head> +<script src = "/javascript/util.js"></script> +<link rel = "stylesheet" href = "/css/feed.css"/> + +<script id = "iframe_script"> + +/** + * Facebook share URL. + */ +var FB_SHARE_URL = "http://www.facebook.com/sharer.php?u="; + +/** + * Twitter share URL. + */ +var TWITTER_SHARE_URL = "http://twitter.com/share?&url="; + +/** + * Buzz share URL. + */ +var BUZZ_SHARE_URL = "http://www.google.com/buzz/post?&url="; + +/** + * Opens new window either of facebook, twitter or google buzz. + * @param {String} id Specifies whether to share news on Facebook, Google Buzz + * or Twitter. + * @param {String} url Contains URL of the News to be shared. + */ +function openNewsShareWindow(id, url) { + var newsUrl = url.substring(url.indexOf('&url=') + 5); + var openUrl; + switch (id) { + case 'fb': + openUrl = FB_SHARE_URL; + break; + case 'buzz': + openUrl = BUZZ_SHARE_URL; + break; + case 'twitter': + openUrl = TWITTER_SHARE_URL; + break; + } + window.open(openUrl + newsUrl, '_blank', + 'resizable=0,scrollbars=0,width=690,height=415'); +} + +/** + * Checks language in image url retrieved from feed and sets style of + * title and openbox in pop-up page(if url is found), otherwise sets + * to default styling. + */ +function setStyleByLang(titleImgUrl) { + var openBoxes = document.getElementsByClassName('open_box'); + var itemTitles = document.getElementsByClassName('item_title'); + + if (titleImgUrl != 'NULL') { + var pattern = /ar_/gi; + var result = titleImgUrl.match(pattern); + if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) { + document.querySelector('body').className = 'rtl'; + } + } +} + +/** + * Reports the height. + */ +function reportHeight() { + var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}); + parent.postMessage(msg, "*"); +} + +/** + * Initialize the iframe body. + */ +function frameLoaded() { + var links = document.getElementsByTagName("A"); + for (var i = 0, link; link = links[i]; i++) { + var class = link.className; + if (class != "item_title" && class != "open_box") { + link.addEventListener("click", showStory); + } + } + window.addEventListener("message", messageHandler); +} + +/** + * Redirects to Google news site according to clicked URL. + * @param {Object} event Onclick event. + */ +function showStory(event) { + var href = event.currentTarget.href; + parent.postMessage(JSON.stringify({type:"show", url:href}), "*"); + event.preventDefault(); +} + +/** + * Handles message. + * @param {Object} event Onmessage event. + */ +function messageHandler(event) { + reportHeight(); +} +</script> +<script src = "/javascript/feed.js"></script> +</head> + +<body onload = "getTopics();getNewsByTitle();" onunload = "saveLastTopic();"> + +<div style = "margin-bottom: 15px;"> + <div style = "float: right;"> + <div style = "float: right; font-size: 11px"> + <a id = "option_link" onclick = "chrome.tabs.create({url: '/views/options.html', selected: true})"> + </a> + </div> + <div style = "margin-top: 27px"> + <select id = "topics" onchange = "getNewsByTitle();" style = "display: inline;"> + </select> + </div> + </div> + <a id = "title_a"> + <img id = "title" style = "padding-top: 5px;"> + </a> +</div> + +<div id = "feed"> +</div> + +<div id = "noStories"> +</div> +</body> +</html> diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/options.html b/chrome/common/extensions/docs/examples/extensions/news/views/options.html new file mode 100644 index 0000000..6bf99b3 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/news/views/options.html @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<!-- + * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> + +<!-- +@fileoverview This file serves as the option page of the extension for +customizing the settings such as setting country, topics and number of +news stories to be shown. +@author navneetg@google.com (Navneet Goel). +--> + +<html> + <head> + <script src = "/javascript/util.js"></script> + <meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8"> + <link rel = "stylesheet" href = "/css/options.css"/> + <script src = "/javascript/options.js"></script> + </head> + <body onload = "initialize();"> + <div id = "all_content"> + <div id = "logo"> + <img id = "title_image" src = "/images/news.gif"/> + <br/> + </div> + <br/><br/> + + <table class = "contentTable" style = "margin-left: 55px;" width = "96%"> + <tr class = "all_rows"> + <td class = "col1"><b id = "select_country"></b></td> + <td class = "col2"> + <select id = "countryList" onchange = "enableSaveButton();"> + <option value = "noCountry">-Select-</option> + <option value = "es_ar">Argentina</option> + <option value = "au">Australia</option> + <option value = "nl_be">België</option> + <option value = "fr_be">Belgique</option> + <option value = "en_bw">Botswana</option> + <option value = "pt-BR_br">Brasil</option> + <option value = "ca">Canada English</option> + <option value = "fr_ca">Canada Français</option> + <option value = "cs_cz">Česká republika</option> + <option value = "es_cl">Chile</option> + <option value = "es_co">Colombia</option> + <option value = "es_cu">Cuba</option> + <option value = "de">Deutschland</option> + <option value = "es">España</option> + <option value = "es_us">Estados Unidos</option> + <option value = "en_et">Ethiopia</option> + <option value = "fr">France</option> + <option value = "en_gh">Ghana</option> + <option value = "in">India</option> + <option value = "en_ie">Ireland</option> + <option value = "en_il">Israel English</option> + <option value = "it">Italia</option> + <option value = "en_ke">Kenya</option> + <option value = "hu_hu">Magyarország</option> + <option value = "en_my">Malaysia</option> + <option value = "es_mx">México</option> + <option value = "en_na">Namibia</option> + <option value = "nl_nl">Nederland</option> + <option value = "nz">New Zealand</option> + <option value = "en_ng">Nigeria</option> + <option value = "no_no">Norge</option> + <option value = "de_at">Österreich</option> + <option value = "en_pk">Pakistan</option> + <option value = "es_pe">Perú</option> + <option value = "en_ph">Philippines</option> + <option value = "pl_pl">Polska</option> + <option value = "pt-PT_pt">Portugal</option> + <option value = "de_ch">Schweiz</option> + <option value = "fr_sn">Sénégal</option> + <option value = "en_sg">Singapore</option> + <option value = "en_za">South Africa</option> + <option value = "fr_ch">Suisse</option> + <option value = "sv_se">Sverige</option> + <option value = "en_tz">Tanzania</option> + <option value = "tr_tr">Türkiye</option> + <option value = "uk">U.K.</option> + <option value = "us">U.S.</option> + <option value = "en_ug">Uganda</option> + <option value = "es_ve">Venezuela</option> + <option value = "vi_vn">Việt Nam (Vietnam)</option> + <option value = "en_zw">Zimbabwe</option> + <option value = "el_gr">Ελλάδα (Greece)</option> + <option value = "ru_ru">Россия (Russia)</option> + <option value = "ru_ua">Украина / русский (Ukraine)</option> + <option value = "uk_ua">Україна / українська (Ukraine)</option> + <option value = "iw_il">ישראל (Israel)</option> + <option value = "ar_ae">الإمارات (UAE)</option> + <option value = "ar_sa">السعودية (KSA)</option> + <option value = "ar_me">العالم العربي (Arabic)</option> + <option value = "ar_lb">لبنان (Lebanon)</option> + <option value = "ar_eg">مصر (Egypt)</option> + <option value = "hi_in">हिन्दी (India)</option> + <option value = "ta_in">தமிழ்(India)</option> + <option value = "te_in">తెలుగు (India)</option> + <option value = "ml_in">മലയാളം (India)</option> + <option value = "kr">한국 (Korea)</option> + <option value = "cn">中国版 (China)</option> + <option value = "tw">台灣版 (Taiwan)</option> + <option value = "jp">日本 (Japan)</option> + <option value = "hk">香港版 (Hong Kong)</option> + </select> + </td> + </tr> + <tr class = "all_rows"> + <td class = "col1"><b id = "story_count"></b></td> + <td class = "col2"> + <select id = "storyCount" style = "padding-left: 3px;" onchange = "enableSaveButton();"> + <option value = "1">1</option> + <option value = "2">2</option> + <option value = "3">3</option> + <option value = "4">4</option> + <option value = "5" selected = "selected">5</option> + <option value = "6">6</option> + <option value = "7">7</option> + <option value = "8">8</option> + <option value = "9">9</option> + <option value = "10">10</option> + </select> + </td> + </tr> + <tr class = "all_rows"> + <td class = "col1"> + <div id = "topic" style = "font-weight: bold;"></div> + </td> + <td class = "col2"> + <div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = " " id = "check11" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "top"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "n" id = "check13" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "nation"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "w" id = "check14" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "world"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "b" id = "check15" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "business"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "t" id = "check16" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "science"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "e" id = "check17" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "entertainment"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "s" id = "check18" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "sports"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "m" id = "check19" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "health"></div><br/></div> + <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "po" id = "check20" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "most"></div><br/></div> + </div> + </td> + </tr> + <tr class = "all_rows"> + <td class = "col1"> + <div id = "custom_text" style = "font-weight: bold;"></div> + </td> + <td class = "col2"> + <input id = "newKeyword" type = "text" maxlength = "20" style = "width: 205px;"> + <input id = "submit_button" type = "submit" onclick = "addCusTopic()" style = "width: 45px;"> + <span id = "invalid_status"></span> + <table> + <tbody id = "custom_topics"></tbody> + </table> + </td> + </tr> + </table> + <br/> + <div id = "save_div"> + <button id = "save_button" type = "button" disabled = "disabled" onclick = "saveTopicsCountry()" style = "width: 80px;"> + </button> + <span id = "save_status"></span> + </div> + </div> + </body> +</html> |