1 /** 2 * Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this 3 * source code is governed by a BSD-style license that can be found in the 4 * LICENSE file. 5 */ 6 7 /** 8 * @fileoverview Includes the country selection, topics selection and 9 * selection of no. of news stories to be shown. Include default settings also. 10 * @author navneetg (at) google.com (Navneet Goel). 11 */ 12 13 /** 14 * Stores number of selected topics on the options page. 15 */ 16 var checkCount = 0; 17 18 /** 19 * Stores maximum count of custom topics. 20 */ 21 var MAX_CUS_TOPICS = 10; 22 23 /** 24 * Stores temporary added custom topics which are not yet saved. 25 */ 26 var tempCusTopics = []; 27 28 /** 29 * Checks whether ENTER key is pressed or not. 30 */ 31 function addCustomTopic() { 32 if (window.event.keyCode == 13) { 33 addCusTopic(); 34 } 35 } 36 37 /** 38 * Retrieves and sets last saved country from local storage(if found), 39 * else sets country retrieved from feed. 40 */ 41 function setCountry() { 42 var country = window.localStorage.getItem('country'); 43 44 // If country is not found in localstorage or default value is selected in 45 // drop down menu. 46 if ((!country) || country == 'noCountry') { 47 // XMLHttpRequest object that tries to load the feed for the purpose of 48 // retrieving the country value out of feed. 49 var req = new XMLHttpRequest(); 50 req.onload = handleResponse; 51 req.onerror = handleError; 52 req.open('GET', DEFAULT_NEWS_URL, true); 53 req.send(null); 54 55 // Sets country to default Country in dropdown menu. 56 function handleError() { 57 $('countryList').value = 'noCountry'; 58 }; 59 60 // Handles parsing the feed data got back from XMLHttpRequest. 61 function handleResponse() { 62 // Feed document retrieved from URL. 63 var doc = req.responseXML; 64 if (!doc) { 65 handleError(); 66 return; 67 } 68 var imageLink = doc.querySelector('image link'); 69 if (imageLink) { 70 // Stores link to set value of country. 71 var newsUrl = imageLink.textContent; 72 } 73 74 // Stores country value 75 $('countryList').value = newsUrl.substring(newsUrl.indexOf('&ned=') + 5, 76 newsUrl.indexOf('&hl=')); 77 }; 78 } else { 79 $('countryList').value = country; 80 } 81 } 82 83 /** 84 * Displays various messages to user based on user input. 85 * @param {String} id Id of status element. 86 * @param {Number} timeOut Timeout value of message shown. 87 * @param {String} message Message to be shown. 88 */ 89 function showUserMessages(id, timeOut, message) { 90 $(id).style.setProperty('-webkit-transition', 91 'opacity 0s ease-in'); 92 $(id).style.opacity = 1; 93 $(id).innerText = chrome.i18n.getMessage(message); 94 window.setTimeout(function() { 95 $(id).style.setProperty( 96 '-webkit-transition', 'opacity' + timeOut + 's ease-in'); 97 $(id).style.opacity = 0; 98 }, 1E3 99 ); 100 } 101 102 /** 103 * Sets options page CSS according to the browser language(if found), else sets 104 * to default locale. 105 */ 106 function setOptionPageCSS() { 107 if (chrome.i18n.getMessage('direction') == 'rtl') { 108 document.querySelector('body').className = 'rtl'; 109 } 110 } 111 112 /** 113 * Initializes the options page by retrieving country, topics and count of 114 * stories from local storage if present, else sets to default settings. 115 */ 116 function initialize() { 117 setOptionPageCSS(); 118 setCountry(); 119 setCountAndTopicList(); 120 setLocalizedTopicList(); 121 122 // Adds a custom topic on press of Enter key. 123 $('newKeyword').onkeypress = addCustomTopic; 124 } 125 126 /** 127 * Retrieves locale values from locale file. 128 */ 129 function setLocalizedTopicList() { 130 var getI18nMsg = chrome.i18n.getMessage; 131 132 $('top').innerText = getI18nMsg('1'); 133 $('nation').innerText = getI18nMsg('n'); 134 $('world').innerText = getI18nMsg('w'); 135 $('business').innerText = getI18nMsg('b'); 136 $('science').innerText = getI18nMsg('t'); 137 $('entertainment').innerText = getI18nMsg('e'); 138 $('sports').innerText = getI18nMsg('s'); 139 $('health').innerText = getI18nMsg('m'); 140 $('most').innerText = getI18nMsg('po'); 141 $('select_country').innerText = getI18nMsg('country'); 142 $('topic').innerText = getI18nMsg('topic'); 143 $('save_button').innerText = getI18nMsg('save'); 144 $('story_count').innerText = getI18nMsg('storyCount'); 145 $('logo').innerHTML = $('logo').innerHTML + getI18nMsg('newsOption'); 146 $('custom_text').innerHTML = getI18nMsg('customText') + '<br/>' + 147 getI18nMsg('maximumTopics',[MAX_CUS_TOPICS]); 148 $('submit_button').value = getI18nMsg('submitButton'); 149 } 150 151 /** 152 * Sets topic list and number of stories retrieved from localstorage(if any) 153 * otherwise sets to default. 154 */ 155 function setCountAndTopicList() { 156 var topicLists = document.getElementsByClassName('checkBox'); 157 158 // Retrieves topics list from localStorage. 159 var topics = JSON.parse(window.localStorage.getItem('topics')); 160 161 // Runs if retrieved topic list from local storage contains topics. 162 if (topics) { 163 for (var x = 0, topicList; topicList = topicLists[x]; x++) { 164 165 // Saves whether checkbox is checked or not. 166 var isPresent = false; 167 for (var y = 0; y < topics.length; y++) { 168 if (topics[y] == topicList.value) { 169 topicList.checked = true; 170 isPresent = true; 171 checkCount++; 172 break; 173 } 174 } 175 if (!isPresent) { 176 topicList.checked = false; 177 } 178 } 179 } 180 181 // Retrieves list of custom topics from localstorage(if any) and shows it 182 // in option page. 183 var keywords = JSON.parse(window.localStorage.getItem('keywords')); 184 if (keywords) { 185 186 // Template to store custom topics in a table. 187 var template = []; 188 var title = chrome.i18n.getMessage('deleteTitle'); 189 for (var i = 0; i < keywords.length; i++) { 190 checkCount++; 191 192 template.push('<tr style = "height: 22px;">'); 193 template.push('<td id = "keyword_value" class = "cusTopicsClass">'); 194 template.push('<textarea class="noborder" readonly>'); 195 template.push(keywords[i]); 196 template.push('</textarea>'); 197 template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); 198 template.push('title="'); 199 template.push(title); 200 template.push('">'); 201 template.push('</td>'); 202 template.push('</tr>'); 203 } 204 $('custom_topics').innerHTML = template.join(''); 205 if (keywords.length == MAX_CUS_TOPICS) { 206 $('submit_button').disabled = true; 207 $('newKeyword').readOnly = 'readonly'; 208 } 209 } 210 // Check all checkboxes(default settings) if no custom topic list and 211 // checkbox topic list from local storage is found. 212 if (!keywords && !topics) { 213 for (var x = 0, topicList; topicList = topicLists[x]; x++) { 214 topicList.checked = true; 215 checkCount++; 216 } 217 } 218 219 // Retrieves saved value of number of stories. 220 var count = window.localStorage.getItem('count'); 221 222 // Sets number of stories in dropdown. 223 if (count) { 224 $('storyCount').value = count; 225 } 226 } 227 228 /** 229 * Saves checked topic list(if any), Custom topics(if any), number of 230 * stories and country value in local storage. 231 */ 232 function saveTopicsCountry() { 233 var country = $('countryList').value; 234 var topicLists = document.getElementsByClassName('checkBox'); 235 236 // Contains selected number of stories. 237 var count = $('storyCount').value; 238 239 // Stores checked topics list. 240 var topicArr = []; 241 for (var i = 0, topicList; topicList = topicLists[i]; i++) { 242 if (topicList.checked) { 243 topicArr.push(topicList.value); 244 } 245 } 246 var keywords = JSON.parse(window.localStorage.getItem('keywords')); 247 248 // Saves custom topics to local storage(if any). 249 if (tempCusTopics.length > 0) { 250 if (keywords) { 251 keywords = keywords.concat(tempCusTopics); 252 window.localStorage.setItem('keywords', JSON.stringify(keywords)); 253 } else { 254 window.localStorage.setItem('keywords', JSON.stringify(tempCusTopics)); 255 } 256 tempCusTopics.splice(0, tempCusTopics.length); 257 } 258 259 // Saves checkbox topics(if any). 260 if (topicArr.length > 0) { 261 window.localStorage.setItem('topics', JSON.stringify(topicArr)); 262 } else { 263 window.localStorage.removeItem('topics'); 264 } 265 266 window.localStorage.setItem('count', count); 267 window.localStorage.setItem('country', country); 268 269 showUserMessages('save_status', 0.5, 'saveStatus'); 270 $('save_button').disabled = true; 271 } 272 273 /** 274 * Disables the save button on options page if no topic is selected by the user. 275 * @param {String} id Id of checkbox checked or unchecked. 276 */ 277 function manageCheckCount(id) { 278 checkCount = ($(id).checked) ? (checkCount + 1) : (checkCount - 1); 279 $('save_button').disabled = (checkCount == 0) ? true : false; 280 } 281 282 /** 283 * Enables save button if at least one topic is selected. 284 */ 285 function enableSaveButton() { 286 if (checkCount != 0) { 287 $('save_button').disabled = false; 288 } 289 } 290 291 /** 292 * Adds new entered custom topic. 293 */ 294 function addCusTopic() { 295 // Retrieves custom topic list from local storage(if any), else create new 296 // array list. 297 var keywords = JSON.parse(window.localStorage.getItem('keywords') || "[]"); 298 299 // Adds topic only if total number of added custom topics are less than 10. 300 if (keywords.length + tempCusTopics.length <= (MAX_CUS_TOPICS - 1)) { 301 302 // Stores new entered value in input textbox. 303 var val = $('newKeyword').value; 304 if (val) { 305 val = val.trim(); 306 if (val.length > 0) { 307 var pattern = /,/g; 308 309 // Runs if comma(,) is not present in topic entered. 310 if (val.match(pattern) == null) { 311 checkCount++; 312 tempCusTopics.push(val); 313 314 // Template to store custom topics in a table. 315 var template = []; 316 var title = chrome.i18n.getMessage('deleteTitle'); 317 318 template.push('<tr style = "height: 22px;">'); 319 template.push('<td id = "keyword_value" class = "cusTopicsClass">'); 320 template.push('<textarea class="noborder" readonly>'); 321 template.push(val); 322 template.push('</textarea>'); 323 template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); 324 template.push('title="'); 325 template.push(title); 326 template.push('">'); 327 template.push('</td>'); 328 template.push('</tr>'); 329 330 $('custom_topics').innerHTML += template.join(''); 331 enableSaveButton(); 332 } else { 333 showUserMessages('invalid_status', 2.5, 'invalidChars'); 334 } 335 } 336 $('newKeyword').value = ''; 337 } 338 } 339 340 if ((keywords.length + tempCusTopics.length) == (MAX_CUS_TOPICS)) { 341 $('submit_button').disabled = true; 342 $('newKeyword').readOnly = 'readonly'; 343 } 344 } 345 346 /** 347 * Delete custom topic whenever users click on delete icon. 348 * @param {HTMLTableColElement} obj HTML table column element to be deleted. 349 */ 350 function delCusTopic(obj) { 351 // Deletes only if total number of topics are greater than 1, else shows 352 // error message. 353 if (checkCount > 1) { 354 var value; 355 356 // Extract custom topic value. 357 value = obj.parentNode.querySelector('.cusTopicsClass textarea').value; 358 359 // Removes custom topic element from UI. 360 $('custom_topics').removeChild(obj.parentNode); 361 362 // Removes custom topic element either from temporary array(if topic is 363 // not yet saved) or from saved topic list and saves new list to 364 // local storage. 365 var flag = 0; 366 for (var i = 0; i < tempCusTopics.length; i++) { 367 if (tempCusTopics[i] == value) { 368 tempCusTopics.splice(i, 1); 369 flag = 1; 370 break; 371 } 372 } 373 374 if (flag == 0) { 375 var keywords = JSON.parse(window.localStorage.getItem('keywords')); 376 for (i = 0; i < keywords.length; i++) { 377 if (keywords[i] == value) { 378 keywords.splice(i, 1); 379 break; 380 } 381 } 382 if (keywords.length > 0) { 383 window.localStorage.setItem('keywords', JSON.stringify(keywords)); 384 } else { 385 window.localStorage.removeItem('keywords'); 386 } 387 } 388 389 checkCount--; 390 $('submit_button').disabled = false; 391 } else { 392 showUserMessages('save_status', 2.5, 'noTopic'); 393 } 394 $('newKeyword').readOnly = false; 395 } 396