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@google.com (Navneet Goel).
11 */
12
13/**
14 * Stores number of selected topics on the options page.
15 */
16var checkCount = 0;
17
18/**
19 * Stores maximum count of custom topics.
20 */
21var MAX_CUS_TOPICS = 10;
22
23/**
24 * Stores temporary added custom topics which are not yet saved.
25 */
26var tempCusTopics = [];
27
28/**
29 * Checks whether ENTER key is pressed or not.
30 */
31function 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 */
41function 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 */
89function 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 */
106function 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 */
116function 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 */
129function 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 */
155function 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 */
232function 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 */
277function 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 */
285function enableSaveButton() {
286  if (checkCount != 0) {
287    $('save_button').disabled = false;
288  }
289}
290
291/**
292 * Adds new entered custom topic.
293 */
294function 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 */
350function 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