- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / examples / extensions / talking_alarm_clock / popup.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var blankClockImage;
6 var blankClockAnim1Image;
7 var blankClockAnim2Image;
8 var animationTimer;
9 var currentClockImage;
10 var port;
11
12 function updateEnabledStatus(alarm) {
13   var enabled = $('a' + alarm + '_on').checked;
14   $('a' + alarm + '_tt').disabled = !enabled;
15   $('a' + alarm + '_ampm').disabled = !enabled;
16   var valid = true;
17   try {
18     var tt = $('a' + alarm + '_tt').value;
19     var ampm = $('a' + alarm + '_ampm').selectedIndex;
20     parseTime(tt, ampm);
21   } catch (x) {
22     valid = false;
23   }
24   if (valid) {
25     $('a' + alarm + '_wrap').removeAttribute('aria-invalid');
26   } else {
27     $('a' + alarm + '_wrap').setAttribute('aria-invalid', 'true');
28   }
29   if (enabled) {
30     $('a' + alarm + '_wrap').classList.remove('disabled');
31   } else {
32     $('a' + alarm + '_wrap').classList.add('disabled');
33   }
34 }
35
36 function loadAllImages() {
37   var loadCount = 0;
38   var img = new Image();
39   img.onload = function() {
40     blankClockImage = img;
41     currentClockImage = blankClockImage;
42     drawClock();
43   };
44   img.src = 'blank-clock-150.png';
45
46   // These will finish loading before they're needed, no need
47   // for an onload handler.
48   blankClockAnim1Image = new Image();
49   blankClockAnim1Image.src = 'blank-clock-ring1-150.png';
50   blankClockAnim2Image = new Image();
51   blankClockAnim2Image.src = 'blank-clock-ring2-150.png';
52 }
53
54 function drawClock(hh, mm, ss) {
55   if (hh == undefined || mm == undefined) {
56     var d = new Date();
57     hh = d.getHours();
58     mm = d.getMinutes();
59     ss = d.getSeconds() + 0.001 * d.getMilliseconds();
60   }
61
62   if (!currentClockImage) {
63     loadAllImages();
64     return;
65   }
66
67   var ctx = $('clock').getContext('2d');
68   ctx.drawImage(currentClockImage, 0, 0);
69
70   // Move the hour by the fraction of the minute
71   hh = (hh % 12) + (mm / 60);
72
73   // Move the minute by the fraction of the second
74   mm += (ss / 60);
75
76   var hourAngle = Math.PI * hh / 6;
77   var hourX = Math.sin(hourAngle);
78   var hourY = -Math.cos(hourAngle);
79   var minAngle = Math.PI * mm / 30;
80   var minX = Math.sin(minAngle);
81   var minY = -Math.cos(minAngle);
82   var secAngle = Math.PI * ss / 30;
83   var secX = Math.sin(secAngle);
84   var secY = -Math.cos(secAngle);
85
86   var cx = 75;
87   var cy = 77;
88
89   ctx.lineWidth = 5;
90   ctx.strokeStyle = '#ffffff';
91   ctx.globalAlpha = 0.5;
92   ctx.beginPath();
93   ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY);
94   ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY);
95   ctx.stroke();
96   ctx.beginPath();
97   ctx.moveTo(cx - 8 * minX, cy - 8 * minY);
98   ctx.lineTo(cx + 35 * minX, cy + 33 * minY);
99   ctx.stroke();
100
101   ctx.lineWidth = 3;
102   ctx.strokeStyle = '#696969';
103   ctx.globalAlpha = 1.0;
104   ctx.beginPath();
105   ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY);
106   ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY);
107   ctx.stroke();
108   ctx.beginPath();
109   ctx.moveTo(cx - 8 * minX, cy - 8 * minY);
110   ctx.lineTo(cx + 35 * minX, cy + 33 * minY);
111   ctx.stroke();
112
113   ctx.lineWidth = 1;
114   ctx.strokeStyle = '#990000';
115   ctx.globalAlpha = 1.0;
116   ctx.beginPath();
117   ctx.moveTo(cx - 4 * secX, cy - 4 * secY);
118   ctx.lineTo(cx + 40 * secX, cy + 40 * secY);
119   ctx.stroke();
120 }
121
122 function updateCurrentTime() {
123   var now = new Date();
124   var hh = now.getHours();
125   var mm = now.getMinutes();
126   var ss = now.getSeconds();
127   var str = '';
128   if (hh % 12 == 0) {
129     str += '12';
130   } else {
131     str += (hh % 12);
132   }
133   str += ':';
134   if (mm >= 10) {
135     str += mm;
136   } else {
137     str += '0' + mm;
138   }
139   str += ':';
140   if (ss >= 10) {
141     str += ss;
142   } else {
143     str += '0' + ss;
144   }
145   if (hh >= 12) {
146     str += " PM";
147   } else {
148     str += " AM";
149   }
150   $('current_time').innerText = str;
151 }
152
153 // Override from common.js
154 window.stopAlarmAnimation = function() {
155   window.clearTimeout(animationTimer);
156   currentClockImage = blankClockImage;
157   drawClock();
158   isAnimating = false;
159 };
160
161 // Override from common.js
162 window.displayAlarmAnimation = function() {
163   isAnimating = true;
164   var rings = 100;
165   function ring() {
166     if (rings == 0) {
167       stopAlarmAnimation();
168       return;
169     }
170     currentClockImage = (rings % 2 == 0)?
171                         blankClockAnim1Image:
172                         blankClockAnim2Image;
173     drawClock();
174     rings--;
175     animationTimer = window.setTimeout(ring, 50);
176   }
177   ring();
178 };
179
180 function addOutlineStyleListeners() {
181   document.addEventListener('click', function(evt) {
182     document.body.classList.add('nooutline');
183     return true;
184   }, true);
185   document.addEventListener('keydown', function(evt) {
186     document.body.classList.remove('nooutline');
187     return true;
188   }, true);
189 }
190
191 function load() {
192   try {
193     port = chrome.runtime.connect();
194     port.onMessage.addListener(function(msg) {
195       if (msg.cmd == 'anim') {
196         displayAlarmAnimation();
197       }
198     });
199   } catch (e) {
200   }
201
202   addOutlineStyleListeners();
203
204   stopAll();
205   drawClock();
206   setInterval(drawClock, 100);
207
208   updateCurrentTime();
209   setInterval(updateCurrentTime, 250);
210
211   function updateTime(timeElement) {
212     if (!parseTime(timeElement.value)) {
213       return false;
214     }
215
216     timeElement.valueAsNumber =
217         timeElement.valueAsNumber % (12 * 60 * 60 * 1000);
218     if (timeElement.valueAsNumber < (1 * 60 * 60 * 1000))
219       timeElement.valueAsNumber += (12 * 60 * 60 * 1000);
220     return true;
221   }
222
223   $('clock').addEventListener('click', function(evt) {
224     if (isPlaying || isSpeaking || isAnimating) {
225       stopAll();
226     } else {
227       ringAlarmWithCurrentTime();
228     }
229   }, false);
230   $('clock').addEventListener('keydown', function(evt) {
231     if (evt.keyCode == 13 || evt.keyCode == 32) {
232       if (isPlaying || isSpeaking || isAnimating) {
233         stopAll();
234       } else {
235         ringAlarmWithCurrentTime();
236       }
237     }
238   }, false);
239
240   // Alarm 1
241
242   var a1_tt = localStorage['a1_tt'] || DEFAULT_A1_TT;
243   $('a1_tt').value = a1_tt;
244   $('a1_tt').addEventListener('input', function(evt) {
245     updateEnabledStatus(1);
246     if (!updateTime($('a1_tt'))) {
247       evt.stopPropagation();
248       return false;
249     }
250     localStorage['a1_tt'] = $('a1_tt').value;
251     updateEnabledStatus(1);
252     return true;
253   }, false);
254   $('a1_tt').addEventListener('change', function(evt) {
255     if ($('a1_tt').value.length == 4 &&
256         parseTime('0' + $('a1_tt').value)) {
257       $('a1_tt').value = '0' + $('a1_tt').value;
258     }
259     if (!updateTime($('a1_tt'))) {
260       evt.stopPropagation();
261       return false;
262     }
263     localStorage['a1_tt'] = $('a1_tt').value;
264     updateEnabledStatus(1);
265     return true;
266   }, false);
267
268   var a1_on = (localStorage['a1_on'] == 'true');
269   $('a1_on').checked = a1_on;
270   $('a1_on').addEventListener('change', function(evt) {
271     window.setTimeout(function() {
272       localStorage['a1_on'] = $('a1_on').checked;
273       updateEnabledStatus(1);
274     }, 0);
275   }, false);
276
277   var a1_ampm = localStorage['a1_ampm'] || DEFAULT_A1_AMPM;
278   $('a1_ampm').selectedIndex = a1_ampm;
279   $('a1_ampm').addEventListener('change', function(evt) {
280     localStorage['a1_ampm'] = $('a1_ampm').selectedIndex;
281   }, false);
282
283   updateEnabledStatus(1);
284
285   // Alarm 2
286
287   var a2_tt = localStorage['a2_tt'] || DEFAULT_A2_TT;
288   $('a2_tt').value = a2_tt;
289   $('a2_tt').addEventListener('input', function(evt) {
290     updateEnabledStatus(2);
291     if (!updateTime($('a2_tt'))) {
292       evt.stopPropagation();
293       return false;
294     }
295     localStorage['a2_tt'] = $('a2_tt').value;
296     updateEnabledStatus(2);
297     return true;
298   }, false);
299   $('a2_tt').addEventListener('change', function(evt) {
300     if ($('a2_tt').value.length == 4 &&
301         parseTime('0' + $('a2_tt').value)) {
302       $('a2_tt').value = '0' + $('a2_tt').value;
303     }
304     if (!updateTime($('a2_tt'))) {
305       evt.stopPropagation();
306       return false;
307     }
308     localStorage['a2_tt'] = $('a2_tt').value;
309     updateEnabledStatus(2);
310     return true;
311   }, false);
312
313   var a2_on = (localStorage['a2_on'] == 'true');
314   $('a2_on').checked = a2_on;
315   $('a2_on').addEventListener('change', function(evt) {
316     window.setTimeout(function() {
317       localStorage['a2_on'] = $('a2_on').checked;
318       updateEnabledStatus(2);
319     }, 0);
320   }, false);
321
322   var a2_ampm = localStorage['a2_ampm'] || DEFAULT_A2_AMPM;
323   $('a2_ampm').selectedIndex = a2_ampm;
324   $('a2_ampm').addEventListener('change', function(evt) {
325     localStorage['a2_ampm'] = $('a2_ampm').selectedIndex;
326   }, false);
327
328   updateEnabledStatus(2);
329
330   // Phrase
331
332   var phrase = localStorage['phrase'] || DEFAULT_PHRASE;
333   $('phrase').value = phrase;
334   $('phrase').addEventListener('change', function(evt) {
335     localStorage['phrase'] = $('phrase').value;
336   }, false);
337
338   // Speech parameters
339
340   var rateElement = $('rate');
341   var volumeElement = $('volume');
342   var rate = localStorage['rate'] || DEFAULT_RATE;
343   var volume = localStorage['volume'] || DEFAULT_VOLUME;
344   rateElement.value = rate;
345   volumeElement.value = volume;
346   function listener(evt) {
347     rate = rateElement.value;
348     localStorage['rate'] = rate;
349     volume = volumeElement.value;
350     localStorage['volume'] = volume;
351   }
352   rateElement.addEventListener('keyup', listener, false);
353   volumeElement.addEventListener('keyup', listener, false);
354   rateElement.addEventListener('mouseup', listener, false);
355   volumeElement.addEventListener('mouseup', listener, false);
356
357   var sound = $('sound');
358   var currentSound = localStorage['sound'] || DEFAULT_SOUND;
359   for (var i = 0; i < sound.options.length; i++) {
360     if (sound.options[i].value == currentSound) {
361       sound.selectedIndex = i;
362       break;
363     }
364   }
365   localStorage['sound'] = sound.options[sound.selectedIndex].value;
366   sound.addEventListener('change', function() {
367     localStorage['sound'] = sound.options[sound.selectedIndex].value;
368   }, false);
369
370   var playSoundButton = $('playsound');
371   playSoundButton.addEventListener('click', function(evt) {
372     playSound(false);
373   });
374
375   var playSpeechButton = $('playspeech');
376   playSpeechButton.addEventListener('click', function(evt) {
377     speakPhraseWithCurrentTime();
378   });
379
380   var voice = $('voice');
381   var voiceArray = [];
382   if (chrome && chrome.tts) {
383     chrome.tts.getVoices(function(va) {
384       voiceArray = va;
385       for (var i = 0; i < voiceArray.length; i++) {
386         var opt = document.createElement('option');
387         var name = voiceArray[i].voiceName;
388         if (name == localStorage['voice']) {
389           opt.setAttribute('selected', '');
390         }
391         opt.setAttribute('value', name);
392         opt.innerText = voiceArray[i].voiceName;
393         voice.appendChild(opt);
394       }
395     });
396   }
397   voice.addEventListener('change', function() {
398     var i = voice.selectedIndex;
399     localStorage['voice'] = voiceArray[i].voiceName;
400   }, false);
401 }
402
403 document.addEventListener('DOMContentLoaded', load);