Home | History | Annotate | Download | only in javascript
      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