1 // Copyright (c) 2011 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.
6 // Network status constants.
7 const StatusConnected = 'connected';
8 const StatusDisconnected = 'disconnected';
9 const StatusConnecting = 'connecting';
10 const StatusError = 'error';
12 const NetworkOther = 'other';
14 // Setup css canvas 'spinner-circle'
18 var ctx = document.getCSSCanvasContext('2d', 'spinner-circle', 2 * r, 2 * r);
20 ctx.lineWidth = lineWidth;
21 ctx.lineCap = 'round';
22 ctx.lineJoin = 'round';
24 ctx.strokeStyle = '#4e73c7';
26 ctx.moveTo(lineWidth / 2, r - lineWidth / 2);
27 ctx.arc(r, r, r - lineWidth / 2, Math.PI, Math.PI * 3 / 2);
32 * Sends "connect" using the 'action' WebUI message.
34 function sendConnect(index, passphrase, identity, auto_connect) {
40 auto_connect ? '1' : '0']);
43 var networkMenuItemProto = (function() {
44 var networkMenuItem = cr.doc.createElement('div');
45 networkMenuItem.innerHTML = '<div class="network-menu-item">' +
46 '<div class="network-label-icon">' +
47 '<div class="network-label"></div>' +
48 '<div class="network-icon hidden"></div>' +
50 '<div class="network-status hidden"></div>' +
51 '<div class="hidden"></div>' +
53 return networkMenuItem;
56 var NetworkMenuItem = cr.ui.define(function() {
57 return networkMenuItemProto.cloneNode(true);
60 NetworkMenuItem.prototype = {
61 __proto__: MenuItem.prototype,
65 autoConnectCheckbox: null,
72 return this.firstElementChild.firstElementChild.firstElementChild;
80 return this.label_.nextElementSibling;
84 * The status area element.
88 return this.firstElementChild.firstElementChild.nextElementSibling;
92 * The action area container element.
96 return this.status_.nextElementSibling;
100 * Set status message.
101 * @param {string} message The message to display in status area.
104 setStatus_: function(message) {
106 this.status_.textContent = message;
107 this.status_.classList.remove('hidden');
109 this.status_.classList.add('hidden');
115 * @param {string} icon Source url for the icon image.
118 setIcon_: function(icon) {
120 this.icon_.style.backgroundImage = 'url(' + icon + ')';
121 this.icon_.classList.remove('hidden');
123 this.icon_.classList.add('hidden');
131 handleConnect_ : function(e) {
132 var index = this.menu_.getMenuItemIndexOf(this);
133 if (this.ssidEdit && this.passwordEdit) {
134 if (this.ssidEdit.value) {
136 this.passwordEdit.value,
138 this.autoConnectCheckbox.checked);
140 } else if (this.passwordEdit) {
141 if (this.passwordEdit.value) {
143 this.passwordEdit.value, '', this.autoConnectCheckbox.checked);
146 if (this.attrs.remembered) {
147 sendConnect(index, this.attrs.passphrase, '', this.attrs.auto_connect);
149 sendConnect(index, '', '', this.autoConnectCheckbox.checked);
155 * Handle keydown event in ssid edit.
158 handleSsidEditKeydown_: function(e) {
159 if (e.target == this.ssidEdit &&
160 e.keyIdentifier == 'Enter') {
161 this.passwordEdit.focus();
166 * Handle keydown event in password edit.
169 handlePassEditKeydown_: function(e) {
170 if (e.target == this.passwordEdit &&
171 e.keyIdentifier == 'Enter') {
172 this.handleConnect_();
177 * Returns whether action area is visible.
180 isActionVisible_: function() {
181 return !this.action_.classList.contains('hidden');
185 * Show/hide action area.
188 showAction_: function(show) {
189 var visible = this.isActionVisible_();
190 if (show && !visible) {
191 this.action_.classList.remove('hidden');
192 } else if (!show && visible) {
193 this.action_.classList.add('hidden');
198 * Add network name edit to action area.
201 addSsidEdit_: function() {
202 this.ssidEdit = this.ownerDocument.createElement('input');
203 this.ssidEdit.type = 'text';
204 this.ssidEdit.placeholder = localStrings.getString('ssid_prompt');
205 this.ssidEdit.pattern = '^\\S+$';
206 this.ssidEdit.addEventListener('keydown',
207 this.handleSsidEditKeydown_.bind(this));
209 var box = this.ownerDocument.createElement('div');
210 box.appendChild(this.ssidEdit);
211 this.action_.appendChild(box);
215 * Add password edit to action area.
218 addPasswordEdit_: function() {
219 this.passwordEdit = this.ownerDocument.createElement('input');
220 this.passwordEdit.type = 'password';
221 this.passwordEdit.placeholder = localStrings.getString('pass_prompt');
222 this.passwordEdit.pattern = '^\\S+$';
223 this.passwordEdit.addEventListener('keydown',
224 this.handlePassEditKeydown_.bind(this));
226 var box = this.ownerDocument.createElement('div');
227 box.appendChild(this.passwordEdit);
228 this.action_.appendChild(box);
232 * Add auto-connect this network check box to action area.
235 addAutoConnectCheckbox_: function() {
236 this.autoConnectCheckbox = this.ownerDocument.createElement('input');
237 this.autoConnectCheckbox.type = 'checkbox';
238 this.autoConnectCheckbox.checked = this.attrs.auto_connect;
240 var autoConnectSpan = this.ownerDocument.createElement('span');
241 autoConnectSpan.textContent =
242 localStrings.getString('auto_connect_this_network');
244 var autoConnectLabel = this.ownerDocument.createElement('label');
245 autoConnectLabel.appendChild(this.autoConnectCheckbox);
246 autoConnectLabel.appendChild(autoConnectSpan);
248 this.action_.appendChild(autoConnectLabel);
252 * Internal method to initiailze the MenuItem.
255 initMenuItem_: function() {
256 // *TODO: eliminate code duplication with menu.js
257 // MenuItem.prototype.initMenuItem_();
258 var attrs = this.attrs;
259 this.classList.add(attrs.type);
260 this.menu_.addHandlers(this, this);
262 //////// NetworkMenuItem specific code:
263 // TODO: Handle specific types of network, connecting icon.
264 this.label_.textContent = attrs.label;
266 if (attrs.network_type == NetworkOther) {
268 this.addPasswordEdit_();
269 this.addAutoConnectCheckbox_();
270 } else if (attrs.status && attrs.status != 'unknown') {
271 if (attrs.status == StatusConnected) {
272 this.setStatus_(attrs.ip_address);
273 } else if (attrs.status == StatusConnecting) {
274 this.setStatus_(attrs.message);
276 this.icon_.classList.add('spinner');
277 this.icon_.classList.remove('hidden');
278 } else if (attrs.status == StatusError) {
279 this.setStatus_(attrs.message);
280 this.setIcon_('chrome://theme/IDR_WARNING');
282 var button = this.ownerDocument.createElement('button');
283 button.textContent = localStrings.getString('reconnect');
284 button.addEventListener('click', this.handleConnect_.bind(this));
285 var box = this.ownerDocument.createElement('div');
286 box.appendChild(button);
287 this.action_.appendChild(box);
289 this.showAction_(true);
292 if (attrs.need_passphrase) {
293 this.addPasswordEdit_();
296 this.addAutoConnectCheckbox_();
298 //////// End NetworkMenuItem specifi code
301 this.label_.style.font = attrs.font;
303 var baseFont = attrs.font.replace(/bold/, '').replace(/italic/, '');
304 this.status_.style.font = baseFont;
305 this.action_.style.font = baseFont;
310 activate: function() {
311 // Close action area and connect if it is visible.
312 if (this.isActionVisible_()) {
313 this.showAction_(false);
314 this.handleConnect_();
318 // Show action area for encrypted network and 'other' network.
319 if ((this.attrs.network_type == NetworkOther ||
320 this.attrs.status == StatusDisconnected) &&
321 this.attrs.need_passphrase &&
322 !this.isActionVisible_()) {
323 this.showAction_(true);
327 MenuItem.prototype.activate.call(this);
332 var NetworkMenu = cr.ui.define('div');
334 NetworkMenu.prototype = {
335 __proto__: Menu.prototype,
338 createMenuItem: function(attrs) {
339 if (attrs.type == 'command') {
340 return new NetworkMenuItem();
342 return new MenuItem();
347 onClick_: function(event, item) {
348 // If item is a NetworkMenuItem, it must have at least one of the following.
349 if (item.autoConnectCheckbox || item.ssidEdit || item.passwordEdit) {
350 // Ignore clicks other than on the NetworkMenuItem itself.
351 if (event.target == item.autoConnectCheckbox ||
352 event.target == item.autoConnectCheckbox.nextElementSibling ||
353 event.target == item.ssidEdit ||
354 event.target == item.passwordEdit) {
359 Menu.prototype.onClick_.call(this, event, item);