tazpanel view lib/tazpanel.js @ rev 522
network.cgi: share Wi-Fi networks via QR codes
author | Aleksej Bobylev <al.bobylev@gmail.com> |
---|---|
date | Fri Aug 07 02:33:24 2015 +0300 (2015-08-07) |
parents | aaf630cf6a8b |
children | 5323427d34b9 |
line source
2 // Hide Loading panel
3 function hideLoading() {
4 var loading = document.getElementById("loading");
5 // If element presents on page
6 if (loading) loading.style.display='none';
7 }
8 // Attach event handler
9 window.onload = hideLoading;
13 // Confirm page loading break
14 function confirmExit() {
15 return document.getElementById('confirmBreak').innerText;
16 }
17 // Attach event handler
18 window.onbeforeunload = confirmExit;
22 // Set light or dark color theme
23 function setColorTheme() {
24 // Goal: to produce pages that fit the user's defined look and feel, and
25 // may be more accessible as the current user settings (contrast color
26 // schemes, big font sizes, etc.)
27 // Realization in the CSS2:
28 // http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
29 // We can use colors from user's color theme to mimic plain desktop application.
30 //
31 // Alas, nowadays it not works. Webkit-based browser returns hard-coded values,
32 // with exception of these two:
33 // * ButtonText - text on push buttons.
34 // * CaptionText - text in caption, size box, and scrollbar arrow box.
35 //
36 // When user changes color theme, browser re-draws page, so all input elements
37 // (buttons, checkboxes, radiobuttons, drop-down lists, scrollbars, text inputs)
38 // automagically fits user-defined theme. We need to change web document's
39 // colors manually. We can't ask for exact user defined colors for document's
40 // background in any way, we can only imagine if it dark or light.
41 // So, plan is follows:
42 // We use 'ButtonText' color for base document's color, and calculate if it
43 // dark or light. If color of button's text is dark, then color of button's body
44 // is light, and we define entire web document as light; and vice versa.
46 // Get 'ButtonText' color value (as current text's color of body)
47 var body = document.getElementsByTagName('body')[0];
48 var bodyColor = window.getComputedStyle(body, null).color;
49 console.info("Set bodyColor: %s", bodyColor);
51 // Returned value must be in format like "rgb(212, 212, 212)" or "rgba(192, 68, 1, 0)"
52 if (bodyColor.indexOf("rgb") != -1) {
53 // Make array with color components
54 var results = bodyColor.match(/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})/);
56 // Calculate luminance (brightness) in range 0..1
57 if (results && results.length >= 3) {
58 r = parseInt(results[1], 10);
59 g = parseInt(results[2], 10);
60 b = parseInt(results[3], 10);
61 min = Math.min(r, g, b); max = Math.max(r, g, b);
62 }
63 var luminance = (min + max) / 2 / 255;
65 // Set class for body
66 body.classList.add( (luminance > 0.5) ? 'dark' : 'light');
67 }
68 // Now we can use cascade styles for any elements lying on light or dark body:
69 // .light h2 { color: #222; }
70 // .dark h2 { color: #CCC; }
71 // Also we can use semi-transparent colors in some cases:
72 // body footer { color: rgba(128, 128, 128, 0.5); }
73 }
77 // Set base font size
78 function setBaseFont() {
79 // Goal: to have on page the same font sizes as in user's system.
80 // User input elements changed its font size automatically, so we can read
81 // font size from (hidden) button and apply this size to document's body.
82 // All other sizes will be relative, and will grow or shrink automatically.
84 // Get document's body
85 var body = document.getElementsByTagName('body')[0];
87 // Make button in the hidden DOM
88 var hiddenButton = document.createElement('BUTTON');
90 // Move button away from look
91 hiddenButton.style.setProperty('position', 'absolute', 1);
92 hiddenButton.style.setProperty('left', '0', 1);
94 // Add some text to button
95 hiddenButton.appendChild(document.createTextNode("SliTaz"));
97 // Add button to DOM
98 body.appendChild(hiddenButton);
100 // Focus to button (it will get colored outline!)
101 hiddenButton.focus();
103 // Get button's style
104 var buttonStyle = getComputedStyle(hiddenButton, null);
106 // Copy styles from button to body
107 with (body.style) {
108 fontFamily = buttonStyle.fontFamily;
109 fontSize = buttonStyle.fontSize;
110 fontWeight = 'normal';
111 }
113 //body.style.color = buttonStyle.outlineColor;
115 console.info('Set fontFamily: %s, fontSize: %s', body.style.fontFamily, body.style.fontSize);
116 console.info('Theme color: %s', buttonStyle.outlineColor);
117 // Remove button from hidden DOM
118 body.removeChild(hiddenButton);
119 }
123 //
124 function dupTableHead() {
125 if (! document.getElementById('head2')) return
126 var tableHead = document.createElement("TABLE");
127 with (tableHead) {
128 innerHTML = '<thead>' + document.getElementById('head2').innerHTML + '</thead>'
129 setAttribute("id", "head1h");
130 setAttribute("class", "zebra pkglist");
131 }
133 document.body.appendChild(tableHead);
134 }
138 //
139 function scrollHandler(){
140 toolbar = document.getElementById('toolbar');
141 paddingTop = toolbar.offsetTop + toolbar.offsetHeight;
142 paddingTopPx = paddingTop + 'px';
144 headerOffset = document.getElementById('head1').offsetTop;
145 windowScrolled = document.body.scrollTop;
146 if ((headerOffset - windowScrolled) < paddingTop)
147 {
148 // document.getElementById('miscinfo1').innerText = '<';
149 var head1h = document.getElementById('head1h');
150 var head1 = document.getElementById('head1');
152 with (head1h.style) {
153 setProperty('top', paddingTopPx, 1);
154 setProperty('display', 'table', 1);
155 setProperty('left', head1.offsetLeft + 'px', 1);
156 setProperty('width', head1.offsetWidth + 'px', 1);
157 }
159 // document.getElementById('miscinfo1').innerText = '(' + toopop +')P^' + paddingTop + 'L' + head1h.offsetLeft + ':W' + head1h.offsetWidth + ':H' + head1h.offsetHeight + ':T' + head1h.clientTop +',' + head1h.offsetTop;
161 }
162 else
163 {
164 //document.getElementById('miscinfo1').innerText = '>';
165 document.getElementById('head1h').style.display = 'none';
166 }
168 tHeadTr = document.getElementById('head1h').children[0].children[0];
169 tHeadTrO = document.getElementById('head1').children[0].children[0];
170 tHeadTr.children[0].style.setProperty('width', tHeadTrO.children[0].offsetWidth -1 + 'px', 1);
171 tHeadTr.children[1].style.setProperty('width', tHeadTrO.children[1].offsetWidth -1 + 'px', 1);
172 tHeadTr.children[2].style.setProperty('width', tHeadTrO.children[2].offsetWidth -1 + 'px', 1);
173 //tHeadTr.children[3].style.setProperty('width', tHeadTrO.children[3].offsetWidth -1 + 'px', 1);
175 }
179 // Handler for History scroller for Terminal
180 function keydownHandler(e) {
181 // Get code for pressed key
182 var evt = e ? e:event;
183 var keyCode = evt.keyCode;
185 // If pressed "up" or "down"
186 if (keyCode==38 || keyCode==40) {
187 // Local storage used as global variables storage
188 // Get current position in the History, and History size
189 //var cur_hist = window.localStorage.getItem("cur_hist");
190 //var max_hist = window.localStorage.getItem("max_hist");
191 switch(keyCode) {
192 case 38:
193 // "up" key pressed; decrement and normalize position
194 cur_hist--; if (cur_hist < 0) cur_hist = 0;
195 break;
196 case 40:
197 // "down" key pressed; increment and normalize position
198 cur_hist++; if (cur_hist > max_hist) cur_hist = max_hist;
199 break;
200 }
201 // Element "cmd" is a text input, put History element there
202 var cmd = document.getElementById('typeField');
203 cmd.focus();
204 cmd.innerText = ash_history[cur_hist];
206 var hint = ''
207 if (cur_hist < max_hist) hint = '[' + cur_hist + '/' + (max_hist - 1) + '] ';
208 document.getElementById('num_hist').innerText = hint;
210 //window.localStorage.setItem('cur_hist', cur_hist);
211 return false
212 }
213 if (keyCode==13) {
214 document.getElementById('cmd').value=document.getElementById('typeField').innerText;
215 document.getElementById('term').submit();
216 return false
217 }
218 return true
219 }
223 // Add hover effect for menu
224 function menuAddHover() {
225 var toolbarMenu = document.getElementById('toolbarMenu');
226 toolbarMenu.className = 'hover';
228 menus = toolbarMenu.getElementsByTagName('li');
229 for (i = 0; i < menus.length; i++)
230 menus[i].blur();
232 toolbarMenu.focus();
233 toolbarMenu.onblur = menuRmHover;
234 console.log('Add finished');
235 }
237 // Remove hover effect for menu
238 function menuRmHover() {
239 var toolbarMenu = document.getElementById('toolbarMenu');
240 toolbarMenu.className = 'nohover';
242 menus = toolbarMenu.getElementsByTagName('li');
243 for (i = 0; i < menus.length; i++)
244 menus[i].onclick = menuAddHover;
246 console.log('Rm finished');
247 }
250 // Close main menu
251 function closeMenu() {
252 document.getElementById('noMenu').style.display = 'none';
253 closeItem(itemOpened);
254 menuIsClosed = true;
255 //console.log('Menu closed');
256 }
257 // Open main menu
258 function openMenu() {
259 //console.log('openMenu')
260 document.getElementById('noMenu').style.display = 'block';
261 menuIsClosed = false;
262 }
263 // Open main menu item
264 function openItem(el) {
265 if (itemOpened != el) {
266 if (itemOpened)
267 closeItem(itemOpened);
268 el.children[1].className = 'opened';
269 el.focus();
270 itemOpened = el;
271 menuIsClosed = false; openMenu();
272 //console.log('Opened %s', el.tabIndex);
273 //console.log('Menu opened (open)');
274 }
275 }
276 // Close main menu item
277 function closeItem(el) {
278 //console.log('<closeItem: "%s">', el)
279 thisMenu = el.children[1];
280 if (thisMenu.className == 'opened') {
281 thisMenu.className = 'closed';
282 el.blur();
283 itemOpened = ''
284 //console.log('Closed %s', el.tabIndex);
285 }
286 }
288 itemOpened = '';
289 menuIsClosed = true;
291 // Add event handler
292 function addMenuHandlers() {
293 menus = document.getElementById('toolbarMenu').children;
294 for (i = 0; i < menus.length; i++) {
295 menus[i].firstElementChild.onclick = function() {menuItemClick(this)};
296 menus[i].firstElementChild.onmouseover = function() {menuItemHover(this)};
297 menus[i].onblur = function() {menuItemBlur(this)};
298 }
300 // Close menu when click outside menu
301 document.getElementById('noMenu').onclick = closeMenu;
302 }
304 function menuItemClick(el) {
305 topItem = el.parentElement;
306 thisMenu = topItem.children[1];
307 //console.log('Clicked %s class %s', topItem.tabIndex, thisMenu.className);
308 if (thisMenu.className == 'opened') {
309 closeItem(topItem);
310 menuIsClosed = true; closeMenu();
311 //console.log('Menu closed (click)');
312 }
313 else {
314 openItem(topItem);
315 menuIsClosed = false; openMenu();
316 //console.log('Menu opened (click)');
317 }
318 }
320 function menuItemHover(el) {
321 hoverElem = el.parentElement;
322 //console.log('Hovered %s', hoverElem.tabIndex);
323 if (! menuIsClosed) {
324 closeItem(itemOpened);
325 openItem(hoverElem);
326 }
327 }
328 function menuItemBlur(el) {
329 elem = el; //.parentElement;
330 //console.log('Blurred %s', elem.tabIndex);
331 //closeItem(elem);
332 //menuIsClosed = true;
333 //console.log('Menu closed (blur)');
334 }
338 //
339 // AJAX code for dynamic requests
340 //
342 // Global status of the AJAX loader
343 // Increment ajaxLoader on the start, decrement on the finish,
344 // Show it if value > 0
345 ajaxLoader = 0
347 function ajax(cgiUrl, command, ajaxOut) {
348 // (0) show AJAX loader
349 ajaxLoader++
351 // (1) create object for server request
352 var req = new XMLHttpRequest();
354 // (2) show request status
355 var statusElem = document.getElementById('ajaxStatus');
357 req.onreadystatechange = function() {
358 // onreadystatechange activates on server answer receiving
360 if (req.readyState == XMLHttpRequest.DONE) {
361 // if request done
362 ajaxLoader--
363 if (ajaxLoader == 0) {
365 statusbar('')
367 if (req.statusText == 'OK') {
368 statusElem.innerHTML = '<span data-img="ok"></span>'
369 } else {
370 statusElem.innerHTML = '<span data-img="delete">' +
371 req.statusText + '</span>' // show status (Not Found, ...)
372 }
373 } else {
374 statusElem.innerHTML = '<span data-img="clock"></span>'
375 }
377 // if status 200 (ОК) - show answer to user
378 if (req.status == 200)
379 document.getElementById(ajaxOut).innerHTML = req.responseText;
380 // here we can add "else" with request errors processing
381 }
382 }
384 // (3) set request address
385 req.open('POST', cgiUrl, true);
387 // (4) request object is ready
388 req.send(command); // send request
390 // (5)
391 statusElem.innerHTML = '<span data-img="clock"></span>'
392 }
396 //
397 // Load configuration for new and stored networks
398 //
400 function loadcfg(essid, bssid, keyType) {
401 // looking for stored network
402 for (i = 0; i < networks.length; i++) {
403 if (networks[i].ssid == essid) break;
404 if (typeof networks[i].bssid != 'undefined') {
405 if (networks[i].bssid == bssid) {
406 essid = networks[i].ssid;
407 break;
408 }
409 }
410 }
411 document.getElementById('essid').value = essid;
412 document.getElementById('keyType').value = keyType;
414 password = document.getElementById('password')
415 password.value = '';
416 if (typeof networks[i] != 'undefined') {
417 if (typeof networks[i].psk != 'undefined')
418 password.value = networks[i].psk;
419 else if (typeof networks[i].wep_key0 != 'undefined')
420 password.value = networks[i].wep_key0;
421 else if (typeof networks[i].password != 'undefined')
422 password.value = networks[i].password;
423 }
425 // Not used yet
426 document.getElementById('bssid').value = '';
428 wifiSettingsChange();
429 }
432 //
433 // Toggle all checkboxes on a page
434 //
436 function checkBoxes() {
437 var inputs = document.getElementsByTagName('input');
438 for (var i = 0; i < inputs.length; i++) {
439 if (inputs[i].type && inputs[i].type == 'checkbox') {
440 inputs[i].checked = !inputs[i].checked;
441 countSelPkgs(inputs[i]);
442 }
443 }
444 }
447 //
448 // Count selected packages on the packages list
449 //
451 function countSelPkgs(el) {
452 countSelectedSpan = document.getElementById('countSelected');
453 countSelected = countSelectedSpan.innerText;
454 if (countSelected == '') countSelected = 0;
456 element = (el.type == 'change' ? this : el);
458 if (element.checked)
459 countSelected++;
460 else
461 countSelected--;
463 countSelectedSpan.innerText = countSelected;
465 // Disable buttons when no one package selected
466 panelButtons = document.getElementsByName('do');
467 disabledState = (countSelected == 0) ? true : false;
468 for (var i = panelButtons.length - 1; i >= 0; i--) {
469 panelButtons[i].disabled = disabledState;
470 };
471 }
473 // Attach event handler
474 function setCountSelPkgs() {
475 // The change event does not bubble to the form container
476 pkglist = document.getElementById('pkglist');
477 if (pkglist) {
478 var checkboxes = pkglist.getElementsByTagName('input');
479 for (i = 0; i < checkboxes.length; i++) {
480 checkboxes[i].onchange = countSelPkgs;
481 }
482 }
483 // Disable buttons when no one package selected by default
484 panelButtons = document.getElementsByName('do');
485 for (var i = panelButtons.length - 1; i >= 0; i--) {
486 panelButtons[i].disabled = true;
487 };
488 }
491 //
492 // Improving packages by the community effort.
493 //
495 function improveAction() {
496 improveType = document.getElementById('improveType');
497 improveText = document.getElementById('improveText');
499 if (improveType.value == '')
500 improveText.value = '';
501 else
502 improveText.value = document.getElementById(improveType.value).innerText;
503 }
506 //
507 // Edit and save files "in place"
508 //
510 function editFile() {
511 document.getElementById('edit_button').style.display = 'none';
512 document.getElementById('save_button').style.display = '';
514 with(document.getElementById('fileContent')) {
515 contentEditable = true;
516 onkeydown = insertTab;
517 focus();
518 }
519 }
521 function saveFile(file, fileTitle) {
522 var newArea = document.createElement('TEXTAREA');
523 with(newArea) {
524 name = 'content';
525 textContent = document.getElementById('fileContent').textContent;
526 }
528 var newTitle = document.createElement('INPUT');
529 with(newTitle) {
530 name = 'title';
531 value = fileTitle;
532 }
534 var newForm = document.createElement('FORM');
535 with(newForm) {
536 appendChild(newArea);
537 appendChild(newTitle);
538 method = 'post';
539 action = "?file=" + file;
540 submit();
541 }
542 }
544 function insertTab(e) {
545 var evt = e ? e:event;
546 if (evt.keyCode == 9) {
547 evt.preventDefault();
548 }
549 }
552 //
553 // Show info in the status bar
554 //
556 function statusbar(status, ticker) {
557 var ds = document.getElementById('defaultStatus');
558 var sb = document.getElementById('statusBar');
559 var as = document.getElementById('ajaxStatus');
561 if (status == '') {
562 // show default status (SliTaz copyright and license)
563 sb.style.display = 'none'; ds.style.display = ''; as.innerHTML = '';
564 } else {
565 // show requested status (rich HTML supported)
566 ds.style.display = 'none'; sb.innerHTML = status; sb.style.display = '';
567 // show optional ticker
568 if (ticker != '') {
569 as.innerHTML = '<span data-img="clock"></span>';
570 }
571 }
572 }
576 /**
577 * Class manipulation from http://www.openjs.com/scripts/dom/class_manipulation.php
578 */
580 function hasClass(ele,cls) {
581 return document.getElementById(ele).className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
582 }
584 function addClass(ele,cls) {
585 if (!this.hasClass(ele,cls))
586 document.getElementById(ele).className += " " + cls;
587 }
589 function removeClass(ele,cls) {
590 if (hasClass(ele,cls)) {
591 var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
592 document.getElementById(ele).className = document.getElementById(ele).className.replace(reg,' ');
593 }
594 }
599 //http://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily
601 // left: 37, up: 38, right: 39, down: 40,
602 // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
603 var keys = [32, 33, 34, 35, 36, 37, 38, 39, 40];
605 function preventDefault(e) {
606 e = e || window.event;
607 if (e.preventDefault)
608 e.preventDefault();
609 e.returnValue = false;
610 }
612 function keydown(e) {
613 for (var i = keys.length; i--;) {
614 if (e.keyCode === keys[i]) {
615 preventDefault(e);
616 return;
617 }
618 }
619 }
621 function wheel(e) {
622 preventDefault(e);
623 }
625 function scrolling(command) {
626 if (command == 'disable') {
627 if (window.addEventListener) {
628 window.addEventListener('DOMMouseScroll', wheel, false); }
629 window.onmousewheel = document.onmousewheel = document.ontouchmove = wheel;
630 document.onkeydown = keydown;
631 } else {
632 if (window.removeEventListener) {
633 window.removeEventListener('DOMMouseScroll', wheel, false); }
634 window.onmousewheel = document.onmousewheel = document.onkeydown = document.ontouchmove = null;
635 }
636 }
641 /**
642 * Show/hide popups
643 */
645 function popup(name, action) {
646 if (action == 'show') {
647 scrolling('disable');
648 document.getElementById('toolbar').style.zIndex = '0';
649 removeClass('shader', 'hidden');
650 removeClass(name, 'hidden');
651 } else {
652 addClass(name, 'hidden');
653 addClass('shader', 'hidden');
654 scrolling('enable');
655 document.getElementById('toolbar').style.zIndex = '10';
656 }
657 }