function $(id) {return document.getElementById(id);} // ############### Mobile Device ################ if (window.screen.width < 769) { $('nav').style.display = 'none'; } $('menu-icon').onclick = function(){ $('nav').style.display = $('nav').style.display == 'none' ? 'block' : 'none'; }; //########## Main Page Alert Handler ############ // fadeIn animation special for alerts function fadeIns(el){ el.style.opacity = 0; (function fade() { var val = parseFloat(el.style.opacity); if (((val += 0.03) > 1) !== true) { el.style.opacity = val; var request = window.requestFrame('request'); request(fade); } })(); } var ac = $('AC'), dc = $('DC'), in_cur = $('in_cur'), out_cur = $('out_cur'), in_freq = $('in_freq'), out_freq = $('out_freq'), pwr = $('pwr'), bat_cap = $('bat_cap'), inner_temp = $('inner_temp'), battimeleft = $('bat_time_left'), // alarm = $('alarm'), sPower = $('sPower'), sBattery = $('sBattery'); var battempCtrlChecked; function dataFadeIn(){ var x = [ ac, dc, in_cur, out_cur, in_freq, out_freq, pwr, bat_cap, inner_temp, battimeleft, sPower, sBattery ]; for (var i = 0; i < x.length; i++){ fadeIns(x[i]); } } // Alarm colors var ALARM_RED = '#ff5050', ALARM_YELLOW = '#f0ad4e', ALARM_GREEN = '#33cc00'; //########## Settings Inform Boxes ############ function HTMLcreate(htmlStr) { var frag = document.createDocumentFragment(), temp = document.createElement('div'); temp.innerHTML = htmlStr; while (temp.firstChild) { frag.appendChild(temp.firstChild); } return frag; } // fade in animation function fadeIn(el, display){ el.style.opacity = 0; el.style.display = display || 'block'; (function fade() { var val = parseFloat(el.style.opacity); if (((val += 0.05) > 1) !== true) { el.style.opacity = val; var request = window.requestFrame('request'); request(fade); } })(); } //########## Settings Form ############ function formValidation(){ $('validation-box').innerHTML = ''; var read_community,write_community,managerIP,managerIP2,managerIP3,managerIP4,managerIP5, ipaddr, gw, mask, tn_port, syslog_port, syslog_server, wtl_ip1, wtl_ip2, wtl_ip3, wtl_ip4, wtl_ip5, ups_cell_min, ups_cell_max/*, ntpservip*/; read_community = $('read_community'); write_community = $('write_community'); managerIP = $('managerIP'); managerIP2 = $('managerIP2'); managerIP3 = $('managerIP3'); managerIP4 = $('managerIP4'); managerIP5 = $('managerIP5'); ipaddr = $('ipaddr'); gw = $('gw'); mask = $('mask'); tn_port = $('tn_port'); syslog_port = $('syslog_port'); syslog_server = $('syslog_server'); // ssh_port = $('ssh_port'); wtl_ip1 = $('wtl_ip1'); wtl_ip2 = $('wtl_ip2'); wtl_ip3 = $('wtl_ip3'); wtl_ip4 = $('wtl_ip4'); wtl_ip5 = $('wtl_ip5'); ups_cell_min = +$('ups_cell_min').children[0].value; ups_cell_max = +$('ups_cell_max').children[0].value; // ntpservip = $('ntpservip'); var flag = true; if (!$('dhcp').checked) { if(!ValidateIPaddress(ipaddr, ' IP-адрес устройства')) flag = false; if(!ValidateIPaddress(gw, ' IP-адрес шлюза')) flag = false; if(!ValidateIPaddress(mask, 'а Маска подсети')) flag = false; } if ($('tn_enabled').checked) { if(!ValidateNumber(tn_port, ' Порт Telnet')) flag = false; } if ($('syslog_enable').checked) { if(!ValidateNumber(syslog_port, ' Порт Syslog')) flag = false; if(!ValidateIPaddress(syslog_server, ' Сервер Syslog')) flag = false; } // if ($('ssh_enabled').checked) { // if(!ValidateNumber(ssh_port, ' Порт SSH')) flag = false; // } // if ($('ssh_enabled').checked && $('tn_enabled').checked) { // if (ssh_port.value == tn_port.value) { // var warn = document.createElement('li'); // warn.innerHTML = 'Одинаковые поты Telnet и SSH!'; // $('validation-box').appendChild(warn); // flag = false; // } // } if(ups_cell_min > ups_cell_max) { var warn = document.createElement('li'); warn.innerHTML = 'Минимальное напряжение на ячейке не может быть больше максимального!'; $('validation-box').appendChild(warn); flag = false; } if(!ValidateIPaddress(managerIP, ' Сервер SNMP 1')) flag = false; if(!ValidateAlphanumericPlus(read_community, 'Read Community')) flag = false; if(!ValidateAlphanumericPlus(write_community, 'Write Community')) flag = false; if(!ValidateIPaddress(managerIP2, ' Сервер SNMP 2')) flag = false; if(!ValidateIPaddress(managerIP3, ' Сервер SNMP 3')) flag = false; if(!ValidateIPaddress(managerIP4, ' Сервер SNMP 4')) flag = false; if(!ValidateIPaddress(managerIP5, ' Сервер SNMP 5')) flag = false; if(!ValidateCIDRIPaddress(wtl_ip1, ' Маска/IP-адреса 1 белого списка')) flag = false; if(!ValidateCIDRIPaddress(wtl_ip2, ' Маска/IP-адреса 2 белого списка')) flag = false; if(!ValidateCIDRIPaddress(wtl_ip3, ' Маска/IP-адреса 3 белого списка')) flag = false; if(!ValidateCIDRIPaddress(wtl_ip4, ' Маска/IP-адреса 4 белого списка')) flag = false; if(!ValidateCIDRIPaddress(wtl_ip5, ' Маска/IP-адреса 5 белого списка')) flag = false; if ($('ntp-inp') && !$('ntp-inp').disabled) { if(!ValidateIPaddress($('ntp-inp'), ' IP адрес NTP сервера')) flag = false; } return flag; } function ValidateIPaddress(ipaddress, z) { var warn = document.createElement('li'); warn.innerHTML = 'Неправильно задан' + z + '!'; if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress.value)) { return true; } $('validation-box').appendChild(warn); return false; } function ValidateCIDRIPaddress(ipaddress, z) { var warn = document.createElement('li'); warn.innerHTML = 'Неправильно задан' + z + '!'; if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/?([0-9]|[1-2][0-9]|3[0-2])$/.test(ipaddress.value) || !ipaddress.value) { return true; } $('validation-box').appendChild(warn); return false; } function ValidateNumber(n, z) { var warn = document.createElement('li'); warn.innerHTML = 'Неправильно задан' + z + '!'; if(/^-?[\d.]+(?:e-?\d+)?$/.test(n.value)) { return true; } $('validation-box').appendChild(warn); return false; } function ValidateAlphanumeric(uadd, z) { var warn = document.createElement('li'); var letter = /^[0-9a-zA-Z]+$/; warn.innerHTML = 'Поле ' + z + ' может содержать только латинские буквы и цифры'; if (letter.test(uadd.value)) {return true;} $('validation-box').appendChild(warn); return false; } function ValidateAlphanumericPlus(uadd, z) { var warn = document.createElement('li'); var letter = /^[0-9a-zA-Z\-_]+$/; warn.innerHTML = 'Поле ' + z + ' может содержать только латинские буквы, цифры и символы -_'; if (letter.test(uadd.value)) {return true;} $('validation-box').appendChild(warn); return false; } function validateUpload(oForm) { var file = oForm.elements.datafile.files[0]; var fnmreg = /^.{1,}\.crt$/g; if (file && fnmreg.test(file.name) ) { upload(file); } else { alert('Файл сертификата не указан или не валиден!'); } return false; } function submitForms() { if (confirm('Вы уверены что хотите применить настройки?')) { if ($('ntp-inp')) { $('ntpservip').options[3].value = $('ntp-inp').value; } if (formValidation()) { $('form1').submit(); } else{ $('validation-box').style.display = 'block'; } } } function upload(file) { var fl = new FormData(); fl.append('file', file); var xhr = new XMLHttpRequest(); xhr.open('POST', '/srv_crt_upload.cgi', true); // обработчик для закачки xhr.upload.onprogress = function(event) { var progress = Math.floor((event.loaded / event.total) * 100); console.log(progress + '%'); }; xhr.onload = xhr.onerror = function() { if (this.status == 200) { if (+xhr.responseText == '1') { alert('Успешно'); window.location.reload(); } else { alert('Ошибка установки сертификата'); } } else { alert('Ошибка ' + this.status); } }; xhr.send(fl); } function checkPWD(){ // $('checkUpdatePass').style.display = 'none'; $('count-wrap').style.display = 'block'; $('countdown').style.display = 'block'; countdown(); } function checkChangePWD(){ var user = $('changePasswordUser').value; var oldpass = $('oldpwd').value; var newpass = $('newpwd').value; var newpassrepeat = $('newpwdrepeat').value; var letter = /^[0-9a-zA-Z.,/\\\-_*#()[\]+:'"@!^%&?|${}`~<>]+$/; if (oldpass.length === 0 || newpass.length === 0 || newpassrepeat.length === 0){ alert('Поля не заполнены!'); } else if (newpass !== newpassrepeat){ alert('Поля с новым паролем не совпадают!'); $('oldpwd').value = ''; $('newpwd').value = ''; $('newpwdrepeat').value = ''; } else if (user === ''){ alert('Не выбран пользователь для которого необходимо сменить пароль!'); } else { if (letter.test(oldpass) && letter.test(newpass) && letter.test(newpassrepeat)) { loadXMLDoc('changepwd.cgi?username=' + encodeURIComponent(user) + '&oldpass=' + encodeURIComponent(oldpass) + '&newpass=' + encodeURIComponent(newpass), 'GET', function(){ alert(this.responseText); window.location.reload(); }); } else { alert('Пароль задан неправильно'); $('oldpwd').value = ''; $('newpwd').value = ''; $('newpwdrepeat').value = ''; } } } function timesetType(el) { if (el.selectedIndex === 0) { $('ntpservip_l').className += ' hidden'; $('ntpservip').className += ' hidden'; $('ntpservip').setAttribute('disabled', 'disabled'); if ($('ntp-inp')) { $('ntp-inp').className += ' hidden'; $('ntp-inp').setAttribute('disabled', 'disabled'); } $('lastsynctime_l').className += ' hidden'; $('lastsynctime').className += ' hidden'; // ----------------- $('date_l').className = 'col span_1_of_2'; $('date').className = 'form-control'; $('time_l').className = 'col span_1_of_2'; $('time').className = 'form-control'; $('date').removeAttribute('disabled'); $('time').removeAttribute('disabled'); } else { $('ntpservip_l').className = 'col span_1_of_2'; $('ntpservip').className = 'form-control'; $('ntpservip').removeAttribute('disabled'); if ($('ntp-inp')) { $('ntp-inp').className = 'form-control'; $('ntp-inp').removeAttribute('disabled'); } $('lastsynctime_l').className = 'col span_1_of_2'; $('lastsynctime').className = 'form-control'; // ------------- $('date_l').className += ' hidden'; $('date').className += ' hidden'; $('time_l').className += ' hidden'; $('time').className += ' hidden'; $('date').setAttribute('disabled', 'disabled'); $('time').setAttribute('disabled', 'disabled'); } } function countdown(rel) { var countDown = 10; setInterval(function () { if (countDown == 1 && rel === true) { location.reload(true); } else if (countDown == 1 && rel !== true){ window.location.href = 'http:' + window.location.origin.substring(window.location.protocol.length); } if (countDown > 0){countDown--;} $('count-number').innerHTML = countDown; return countDown; }, 1000); } function dhcpState() { if ($('dhcp').checked) { $('ipaddr').setAttribute('disabled', 'disabled'); $('gw').setAttribute('disabled', 'disabled'); $('mask').setAttribute('disabled', 'disabled'); } else { $('ipaddr').removeAttribute('disabled'); $('gw').removeAttribute('disabled'); $('mask').removeAttribute('disabled'); } } function telnetState() { if (!$('tn_enabled').checked) { $('tn_port').setAttribute('disabled', 'disabled'); } else { $('tn_port').removeAttribute('disabled'); } } function syslogState() { if (!$('syslog_enable').checked) { $('syslog_server').setAttribute('disabled', 'disabled'); $('syslog_port').setAttribute('disabled', 'disabled'); } else { $('syslog_server').removeAttribute('disabled'); $('syslog_port').removeAttribute('disabled'); } } // function sshState() { // if (!$('ssh_enabled').checked) { // $('ssh_port').setAttribute('disabled', 'disabled'); // } else { // $('ssh_port').removeAttribute('disabled'); // } // } //########## Info Form Validation ############ function infoValidation(){ var sysname, owner, sysLocation,comment; sysname = $('sysname').value, owner = $('owner').value, sysLocation = $('sysLocation').value, comment = $('comment').value; var flag = true; if(!ValidateAlphanumeric2(sysname, 'Название устройства')){flag = false;} if(!ValidateAlphanumeric2(owner, 'Владелец')){flag = false;} if(!ValidateAlphanumeric2(sysLocation, 'Местоположение')){flag = false;} if(!ValidateAlphanumeric2(comment, 'Комментарии')){flag = false;} return flag; } function ValidateAlphanumeric2(uadd, z) { var warn = document.createElement('li'); // var letter = /^[0-9a-zA-Z]+[^\u0430-\u044f\u0410-\u042f\u0451\u0401\?]+$/m; var letter = /^[0-9a-zA-Z.,/\-_*#()[\]+=;:'"@!^%&?|${}`~<>]+$/m; warn.innerHTML = 'Поле ' + z + ' может содержать только латинские буквы, цифры и символы .,/-_*#()[]+=;:\'"@!^%&?|${}`~<>'; if (letter.test(uadd) || !uadd) { return true; } $('validation-box').appendChild(warn); return false; } function submitInfo() { if (confirm('Вы уверены что хотите применить изменения?')) { if (infoValidation()) { $('SNMPinfo').submit(); // loadXMLDoc('info.cgi?owner='+ $('owner').value + '&sysLocation='+ $('location').value + '&comment='+ decodeURIComponent($('comment').value), 'GET', function(){ // console.log('Сохранено'); // }); } else { $('validation-box').style.display = 'block'; } } } function getJSON(url, successHandler, errorHandler) { var xhr; xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP'); xhr.open('GET', url, true); xhr.onreadystatechange = function () { var status; var data; if (xhr.readyState == 4) { status = xhr.status; if (status == 200) { data = JSON.parse(xhr.responseText); successHandler(data); } else { errorHandler(status); } } }; xhr.send(); } function updatepage(){ var loc = location.pathname.slice(1, -5); switch(loc){ case 'settings': setTimeout(settingsGET, 1000); break; case 'snmp': createSNMP('snmp_list'); break; case 'history': getPage($('currentpage').value); break; } } function getCGI(url) { var xmlhttp; var q; if (url == 'reset.cgi') { q = confirm('Вы уверены что хотите сбросить в заводские настройки?'); } if (url == 'reboot.cgi') { q = confirm('Вы уверены что хотите перезагрузить устройство?'); } if (url == 'update.cgi') { q = confirm('Вы уверены что хотите обновить прошивку устройства?'); } if (q) { if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new window.ActiveXObject('Microsoft.XMLHTTP'); } // xmlhttp.onreadystatechange = true; xmlhttp.open('GET', url, true); xmlhttp.send(); return true; } // else {alert(a);} } function Alarm(bitmask, num) { // Bit mask format DEC var answ = (bitmask & (1 << num)) >> num; return answ; } function setIcons(containerID, icnName) { $(containerID).innerHTML =''; var icons = typeof icnName === 'string' ? [icnName] : icnName; for (var i = 0; i < icons.length; i++) { var icnContainer = document.createElement('i'); icnContainer.innerHTML = Icons[icons[i]]['icn']; icnContainer.style.paddingLeft = '10px'; icnContainer.title = Icons[icons[i]]['title']; $(containerID).appendChild(icnContainer); } } function paramsRefresh() { getJSON('getJson.cgi'+'?'+Math.random(), function (data) { var alrm = +data.u_alarm; var ma = +data.m_alarm; var pstate = []; var bstate = []; var ups_bypass = Alarm(alrm, 5), ups_alarm = Alarm(alrm, 4) || Alarm(alrm, 7), ups_standby = Alarm(alrm, 3), ups_shutdown = Alarm(alrm, 1), bat_low = Alarm(alrm, 6), bat_test = Alarm(alrm, 2); // bat_exp = Alarm(ma, 6); // PPS $('AC').innerHTML = parseFloat(data.AC) + ' В'; $('AC').style.color = Alarm(alrm, 7) ? ALARM_RED : ALARM_GREEN; $('DC').innerHTML = parseFloat(data.DC) + ' В'; $('DC').style.color = Alarm(ma, 7) ? ALARM_RED : ALARM_GREEN; $('in_cur').innerHTML = parseFloat(data.in_cur) + ' А'; $('in_cur').style.color = Alarm(alrm, 7) ? ALARM_RED : ALARM_GREEN; $('out_cur').innerHTML = parseFloat(data.out_cur) + ' А'; $('out_cur').style.color = Alarm(ma, 7) ? ALARM_RED : ALARM_GREEN; $('in_freq').innerHTML = parseFloat(data.in_freq) + ' Гц'; $('in_freq').style.color = Alarm(alrm, 7) ? ALARM_RED : ALARM_GREEN; $('out_freq').innerHTML = parseFloat(data.out_freq) + ' Гц'; $('out_freq').style.color = Alarm(ma, 7) ? ALARM_RED : ALARM_GREEN; $('pwr').innerHTML = parseFloat(data.pwr) + ' %'; $('pwr').style.color = Alarm(ma, 0) ? ALARM_RED : ALARM_GREEN; $('pmode').innerHTML = data.pmode; // State ups_alarm ? pstate.push('exclamination') : pstate.push('normal'); // ups_standby ? pstate.push('clock') : null; ups_shutdown ? pstate.push('shutdown') : null; !Alarm(ma, 3) && !bat_low ? bstate.push('normal') : null; Alarm(ma, 3) ? bstate.push('exclamination') : null; bat_low ? bstate.push('batteryLow') : null; bat_test ? bstate.push('batTest') : null; setIcons('pstate_icons', pstate); setIcons('bstate_icons', bstate); // ACB $('bat_cap').innerHTML = parseFloat(data.bat_cap) + ' А·ч'; $('bat_volt').innerHTML = parseFloat(data.bat_volt) + ' В'; $('bat_volt').style.color = bat_low ? ALARM_RED : ALARM_GREEN; $('bat_rem_cap').innerHTML = parseFloat(data.bat_rem_cap) + ' %'; $('bat_rem_cap').style.color = bat_low ? ALARM_RED : ALARM_GREEN; $('inner_temp').innerHTML = parseFloat(data.inner_temp) + ' °C'; $('inner_temp').style.color = Alarm(ma, 1) || Alarm(ma, 5) ? ALARM_RED : ALARM_GREEN; $('bat_time_left').innerHTML = parseFloat(data.bat_time_left) + ' мин'; $('bat_time_left').style.color = bat_low ? ALARM_RED : ALARM_GREEN; // $('bat_exp').innerHTML = data.bat_exp; // $('bat_exp').style.color = bat_exp ? ALARM_RED : ALARM_GREEN; // checkState(); window.setCookie('netsettings_changed', data.netsettings_changed); window.setCookie('device-error', Alarm(ma, 2)); checkNotify(); setTimeout(paramsRefresh, 1000); }, function (status) { if (status !== 0){ alert('Не удалось получить данные.'); setTimeout(paramsRefresh, 15000); } }); } var mint; //########## History ############ var ctrl_inputs = [ 'h_param_', 'h_event_', 'h_datetime_' ]; function getPage(pn){ getJSON('history.cgi?page=' + pn, function(data){ $('history_data').textContent = ''; var n = data.page; $('currentpage').value = pn; $('pagelimit').innerHTML = data.pages; for (var i in n){ var tr = document.createElement('tr'); for (var num = 0; num < ctrl_inputs.length; num++) { var td = document.createElement('td'); td.innerHTML = n[i].split(';')[num]; td.id = ctrl_inputs[num] + i; tr.appendChild(td); } $('history_data').appendChild(tr); } window.setCookie('netsettings_changed', data.netsettings_changed); checkNotify(); clearTimeout(mint); mint = setTimeout(history_dataref, 5000); }, function(){ $('table').display = 'none'; $('content').innerHTML = '

Журнал событий

'+ '
'+ '
Ошибка
'+ '

Данные отсутствуют.

'+ '
'; }); } function history_dataref() { var pn = parseInt($('currentpage').value); getJSON('history.cgi?page=' + pn, function(data) { var p = data.page; for (var j in p) { for (var num = 0; num < ctrl_inputs.length; num++) { $(ctrl_inputs[num] + j).innerHTML = p[j].split(';')[num]; } $('pagelimit').innerHTML = data.pages; } clearTimeout(mint); mint = setTimeout(history_dataref, 5000); }); } function nextPage(){ var next = parseInt($('currentpage').value); if (next < parseInt($('pagelimit').textContent)) { next = next + 1; getPage(next); } } function prevPage(){ var prev = parseInt($('currentpage').value); if (prev != 1) { prev = prev - 1; getPage(prev); } } //########## UPS History ############ var ups_inputs = [ { id: 'h_inputv_', unit: ' В', parse: 'float' }, { id: 'h_inputfv_', unit: ' В', parse: 'float' }, { id: 'h_outputv_', unit: ' В', parse: 'float' }, { id: 'h_outputc_', unit: '%', parse: 'float' }, { id: 'h_inputf_', unit: ' Гц', parse: 'float' }, { id: 'h_batv_', unit: ' В', parse: 'float' }, { id: 'h_temp_', unit: ' °C', parse: 'float' }, { id: 'h_status_', unit: '', parse: 'string' }, { id: 'h_time_', unit: '', parse: 'string' } ]; function getUPSPage(pn){ getJSON('ups_history.cgi?page=' + pn, function(data){ $('history_data').textContent = ''; var n = data.page; $('currentpage').value = pn; $('pagelimit').innerHTML = data.pages; for (var i in n){ var tr = document.createElement('tr'); for (var num = 0; num < ups_inputs.length; num++) { var td = document.createElement('td'); td.innerHTML = ups_inputs[num].parse === 'float' ? parseFloat(n[i].split(';')[num]) + ups_inputs[num].unit : n[i].split(';')[num] + ups_inputs[num].unit; td.id = ups_inputs[num].id + i; tr.appendChild(td); } $('history_data').appendChild(tr); } window.setCookie('netsettings_changed', data.netsettings_changed); checkNotify(); clearTimeout(mint); mint = setTimeout(ups_history_dataref, 5000); }, function(){ $('table').display = 'none'; $('content').innerHTML = '

Журнал событий

'+ '
'+ '
Ошибка
'+ '

Данные отсутствуют.

'+ '
'; }); } function ups_history_dataref() { var pn = parseInt($('currentpage').value); getJSON('ups_history.cgi?page=' + pn, function(data) { var p = data.page; for (var j in p) { for (var num = 0; num < ups_inputs.length; num++) { $(ups_inputs[num].id + j).innerHTML = ups_inputs[num].parse === 'float' ? parseFloat(p[j].split(';')[num]) + ups_inputs[num].unit : p[j].split(';')[num] + ups_inputs[num].unit; } $('pagelimit').innerHTML = data.pages; } clearTimeout(mint); mint = setTimeout(ups_history_dataref, 5000); }); } function nextUPSPage(){ var next = parseInt($('currentpage').value); if (next < parseInt($('pagelimit').textContent)) { next = next + 1; getUPSPage(next); } } function prevUPSPage(){ var prev = parseInt($('currentpage').value); if (prev != 1) { prev = prev - 1; getUPSPage(prev); } } function utf8_decode (s) { var bb = '', c = 0; for (var i = 0; i < s.length; i++) { c = s.charCodeAt(i); if (c > 127) { if (c > 1024) { if (c == 1025) { c = 1016; } else if (c == 1105) { c = 1032; } bb += String.fromCharCode(c - 848); } } else { bb += s.charAt(i); } } return bb; } function msieversion() { var ua = window.navigator.userAgent; var msie = ua.indexOf('MSIE '); if (msie != -1 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) /*If IE, return version number*/ return true; return false; } function blobLoad(requestUrl, fileName, buttonID){ if(isMobile.iOS()){ alert('На данном устройстве сохранение не доступно.'); return false; } var old = $(buttonID).children[0].textContent; var pgFlag = 'Обработка'; var pgFlagLen = pgFlag.length; var d = new Date(); var fName; if (fileName === 'settings.dat') { fName = fileName; } else { fName = d.getDate()+'_'+(d.getMonth()+1)+'_'+d.getHours()+d.getMinutes() + '_' + fileName; } var xhr = new XMLHttpRequest(); var fURL = requestUrl.split('.').pop() == 'cgi' ? requestUrl+'?' : requestUrl+'&'; xhr.open('GET', fURL+'_='+ new Date().getTime()); xhr.responseType = 'blob'; $(buttonID).setAttribute('disabled', 'disabled'); xhr.addEventListener('load', function(){ $(buttonID).children[1].style.width = 0; $(buttonID).children[0].textContent = old; $(buttonID).removeAttribute('disabled'); }); xhr.onload = function(){ if (this.status === 200) { var blob = this.response; if(msieversion()){ if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, fName); } else { var IEwindow = window.open(requestUrl); } } else { var objectUrl = URL.createObjectURL(blob); var uri = objectUrl; var link = document.createElement('a'); link.href = uri; link.style = 'visibility:hidden'; link.download = fName; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } }; xhr.onprogress = function(event) { $(buttonID).children[0].textContent = parseInt((event.loaded / event.total) * 100) + '%'; $(buttonID).children[1].style.width = parseInt((event.loaded / event.total) * 100) + '%'; }; xhr.send(); } var isMobile = { Android: function() { return navigator.userAgent.match(/Android/i); }, BlackBerry: function() { return navigator.userAgent.match(/BlackBerry/i); }, iOS: function() { return navigator.userAgent.match(/iPhone|iPad|iPod/i); }, Opera: function() { return navigator.userAgent.match(/Opera Mini/i); }, Windows: function() { return navigator.userAgent.match(/IEMobile/i); }, any: function() { return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); } }; function checkOther(ele) { if (ele.selectedIndex == 3) { var newInput = document.createElement('input'); newInput.type = 'text'; newInput.className = 'form-control'; newInput.id = 'ntp-inp'; newInput.value = ntpservipValue; newInput.style.marginTop = '10px'; ele.parentNode.insertBefore(newInput, ele.nextSibling); } else if ($('ntp-inp')) { var d = $('ntp-inp'); ele.parentNode.removeChild(d); } } // ################################################################################ function fillTempRange(id, min, max) { var obj = $(id); for (var i = min; i <= max; i++) { var opt = document.createElement('option'); opt.value = i; opt.text = i; obj.appendChild(opt); } } function settingsGET(){ getJSON('settings.cgi', function(data) { //SNMP params // $('managerIP').value = data.managerIP; $('read_community').value = data.read_community; $('write_community').value = data.write_community; $('managerIP2').value = data.managerIP2; $('managerIP3').value = data.managerIP3; $('managerIP4').value = data.managerIP4; $('managerIP5').value = data.managerIP5; // Syslog $('syslog_enable').checked = data.syslog_enable; $('syslog_server').value = data.syslog_server; $('syslog_port').value = data.syslog_port; // FTP $('ftp_server').value = data.ftp_server; $('ftp_port').value = data.ftp_port; $('ftp_login').value = data.ftp_login; $('ftp_password').value = data.ftp_password; $('ftp_path').value = data.ftp_path; // Network params $('ipaddr').value = data.ipaddr; $('gw').value = data.gw; $('mask').value = data.mask; $('dhcp').checked = data.dhcp; // Alarms fillTempRange('temp_high', 40, 80); fillTempRange('temp_low', -40, 0); fillTempRange('loadvolt_high', 60, 120); fillTempRange('mainvolt_low', 110, 200); fillTempRange('mainvolt_high', 220, 250); fillTempRange('mainvolt_in_low', 110, 200); fillTempRange('mainvolt_in_high', 220, 250); $('temp_high').value = data.temp_high; $('temp_low').value = data.temp_low; temp_hist = new SpinBox('temp_hist', { 'name':'temp_hist','minimum':0.5,'maximum':2.0,'step':0.1,'decimals':1, 'value': data.temp_hist }); $('loadvolt_high').value = data.loadvolt_high; loadvolt_hist = new SpinBox('loadvolt_hist', { 'name':'loadvolt_hist','minimum':0.5,'maximum':2.0,'step':0.1,'decimals':1, 'value': data.loadvolt_hist }); $('mainvolt_low').value = data.mainvolt_low; $('mainvolt_high').value = data.mainvolt_high; mainvolt_hist = new SpinBox('mainvolt_hist', { 'name':'mainvolt_hist','minimum':10,'maximum':30,'step':1, 'value': data.mainvolt_hist }); $('mainvolt_in_low').value = data.mainvolt_in_low; $('mainvolt_in_high').value = data.mainvolt_in_high; mainvolt_in_hist = new SpinBox('mainvolt_in_hist', { 'name':'mainvolt_in_hist','minimum':5,'maximum':30,'step':1, 'value': data.mainvolt_in_hist }); // Whitelist $('wtl_ip1').value = data.wtl_ip1; $('wtl_ip2').value = data.wtl_ip2; $('wtl_ip3').value = data.wtl_ip3; $('wtl_ip4').value = data.wtl_ip4; $('wtl_ip5').value = data.wtl_ip5; $('tn_enabled').checked = data.tn_enabled; $('tn_port').value = data.tn_port; // $('ssh_enabled').checked = data.ssh_enabled; // $('ssh_port').value = data.ssh_port; // $("bat_prod").value = data.bat_prod; ups_max_power = new SpinBox('ups_max_power', { 'value': data.ups_max_power, 'name':'ups_max_power', 'minimum':400, 'maximum':10000, 'step':50 }); ups_cell_min = new SpinBox('ups_cell_min', { 'value': data.ups_cell_min, 'name':'ups_cell_min', 'minimum':0, 'maximum':3.0, 'decimals':2, 'step':0.01 }); ups_cell_max = new SpinBox('ups_cell_max', { 'value': data.ups_cell_max, 'name':'ups_cell_max', 'minimum':0, 'maximum':3.0, 'decimals':2, 'step':0.01 }); // bat_exp = new SpinBox('bat_exp', { // 'value': data.bat_exp, // 'name':'bat_exp', // 'minimum':1, // 'maximum':10, // 'step':1 // }); bat_cap = new SpinBox('bat_cap', { 'value': data.bat_cap, 'name':'bat_cap', 'minimum':1, 'maximum':200, 'step':1 }); bat_charge = new SpinBox('bat_charge', { 'value': data.bat_charge, 'name':'bat_charge', 'minimum':12, 'maximum':240, 'step':12 }); // sshState(); // DateTime if (data.ntpservip != $('ntpservip').options[0].value && data.ntpservip != $('ntpservip').options[1].value && data.ntpservip != $('ntpservip').options[2].value ) { var newInput = document.createElement('input'); newInput.type = 'text'; newInput.className = 'form-control'; newInput.id = 'ntp-inp'; newInput.style.marginTop = '10px'; $('ntpservip').options[3].selected = 'selected'; $('ntpservip').options[3].value = data.ntpservip; $('ntpservip').parentNode.insertBefore(newInput, $('ntpservip').nextSibling); window.ntpservipValue = data.ntpservip; newInput.value = window.ntpservipValue; } else { window.ntpservipValue = data.ntpservip; $('ntpservip').value = window.ntpservipValue; } $('utc').value = data.utc; $('date').value = data.date; $('time').value = data.time; $('lastsynctime').value = data.lastsynctime; $('ntp').value = data.ntp; dhcpState(); telnetState(); syslogState(); timesetType($('ntp')); ftpSettings(); window.setCookie('netsettings_changed', data.netsettings_changed); checkNotify(); }, function() { alert('Не удалось получить данные.'); }); } function ftpSettings() { var modal = $('dev_update_method'); modal.onchange = ftpSettings; if (modal.value == 'manual') { $('ftp_settings').style.display = 'none'; $('start_fw_update').onclick = function() { if( confirm('Перевести контроллер в режим обновления ПО?') ){ $('ftpFWDownload').style.display = 'none'; loadXMLDoc('fw_update.cgi', 'GET'); checkPWD(); } }; } else { $('ftp_settings').style.display = 'block'; $('start_fw_update').onclick = function() { if (!/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test($('ftp_server').value)) { return alert('Не верный формат IP-адреса сервера'); } if(isNaN(parseInt($('ftp_port').value)) || parseInt($('ftp_port').value) > 65535) { return alert('Не верный формат порта сервера'); } if(!/^[0-9a-zA-Z.,/\-_*#()[\]+=;:'"@!^%&?|${}`~<>]+$/.test($('ftp_login').value)) { return alert('Логин может содержать только цифры, латинские буквы и и спец. символы .,/-_*#()[]+=;:\'\\"@!^%&?|${}`~<>'); } if($('ftp_password').value.length > 0 && !/^[0-9a-zA-Z.,/\-_*#()[\]+=;:'"@!^%&?|${}`~<>]+$/.test($('ftp_password').value)) { return alert('Пароль может содержать только цифры, латинские буквы и и спец. символы .,/-_*#()[]+=;:\'\\"@!^%&?|${}`~<>'); } var f1 = new FormData(document.forms.ftp_settings); var fArr = []; f1.forEach( function(a, b) { fArr.push(b+'='+a); }); loadXMLDoc('ftp_fw_update.cgi', 'POST', function() { ftpDownloadState(); }, fArr.join('&')); }; } } function ftpDownloadState() { $('ftpFWDownload').style.display = 'none'; if(!$('wb1')){ var warnbox = document.createElement('div'); warnbox.className = 'warn-box'; warnbox.id = 'wb1'; warnbox.style.display = 'none'; warnbox.innerHTML = '

Внимание! Идет процесс обновления ПО, просьба не перезагружать и не закрывать страницу.

'; var downloaded = document.createElement('p'); downloaded.id = 'ftpdld'; warnbox.appendChild(downloaded); $('count-wrap').appendChild(warnbox); } loadXMLDoc('fw_dl_state.cgi', 'GET', function() { var downloaded = $('ftpdld'); if ( isNaN(parseInt(this.responseText)) ) { $('wb1').style.display = 'none'; $('ftpFWDownload').style.display = 'block'; alert(this.responseText); } else if (parseInt(this.responseText) === 0) { $('wb1').style.display = 'block'; if ( downloaded.innerHTML.length > 33 || downloaded.innerHTML.length < 30) { downloaded.innerHTML = 'Подготовка к загрузке файла ПО'; } else { downloaded.innerHTML += '.'; } setTimeout(ftpDownloadState, 200); } else { $('wb1').style.display = 'block'; if (parseInt(this.responseText) < 95) { downloaded.innerHTML = 'Загружено: '+ this.responseText + '%'; setTimeout(ftpDownloadState, 200); } else { downloaded.innerHTML = 'Контроллер перезагрузится через 60 сек'; decrTimer(); } } }); } function decrTimer() { var dl_text = $('ftpdld').innerText.split(' '); if ( +dl_text[3] > 0) { +dl_text[3]--; $('ftpdld').innerHTML = dl_text.join(' '); setTimeout(decrTimer, 1000); } else { window.location.href = '/'; } } function batTest(options) { this.options = (options ? options : {}); if (this.options.time) { if (typeof this.options.time !== 'number' && this.options.time > 99) { return alert('Ошибка заданного времени'); } } var str = ''; for (var option in options) { str += option + '=' + options[option] + '&'; } str = str.slice(0, -1); var url = 'bat_test.cgi'; loadXMLDoc(url + '?' + str, 'GET', function(){ this.responseText ? alert(this.responseText) : null; }); } function UPSPowerOff(options) { this.options = (options ? options : {}); if (typeof this.options.after !== 'number' && this.options.after > 9999) { return alert('Ошибка заданного времени отключения'); } var str = ''; for (var option in options) { str += option + '=' + options[option] + '&'; } str = str.slice(0, -1); var url = 'ups_power.cgi'; loadXMLDoc(url + '?' + str, 'GET', function(){ this.responseText ? alert(this.responseText) : null; }); } var apply_settings = new NotificationBox('apply-settings', { 'message': 'Внимание, для применения сетевых настроек необходимо их подтвердить. Иначе они будут сброшены в течение 10 минут.', 'bgcolor':'#ffcc00', 'textcolor': '#333', 'url': 'confirm.cgi', 'show': window.getCookie('role') < 2 }); var device_error = new NotificationBox('device-error', { 'message': 'Внимание, связь с ИБП не установлена!', 'bgcolor':'#ec0035', 'textcolor': '#fff' }); // ################################################################################ function infoGet() { getJSON('info.cgi', function(data) { // Cotroller Info $('uptime').innerHTML = data.uptime; $('model').innerHTML = data.model; $('prodate').innerHTML = data.prodate; $('fwversion').innerHTML = data.fwversion; $('macaddr').innerHTML = data.macaddr; $('serno').innerHTML = data.serno; $('ups_fwversion').innerHTML = data.ups_fwversion; $('ups_sn').innerHTML = data.ups_sn; $('ups_model').innerHTML = data.ups_model; var info_labels = { sysname: ['Название устройства', data.sysname, 19], owner: ['Владелец', data.owner, 49], sysLocation:['Местоположение', data.sysLocation, 109], comment: ['Комментарии', data.comment, 109] }; for (var i in info_labels) { var row = document.createElement('tr'); var label = document.createElement('td'); label.innerHTML = info_labels[i][0]; var val = document.createElement('td'); val.id = i+'_wr'; if (getCookie('role') <= 1) { var inp = document.createElement('input'); inp.type = 'text'; inp.id = i; inp.name = i; inp.className = 'form-control'; inp.maxLength = info_labels[i][2]; inp.value = info_labels[i][1]; val.appendChild(inp); } else { val.innerHTML = info_labels[i][1]; } row.appendChild(label); row.appendChild(val); $('ctrl_info').appendChild(row); } if (getCookie('role') <= 1) { var sbmt = document.createElement('button'); sbmt.className = 'btn btn-primary-inverted'; sbmt.type = 'button'; sbmt.setAttribute('onclick', 'submitInfo(); return false;'); sbmt.innerHTML = 'Сохранить'; $('SNMPinfo').appendChild(sbmt); } window.setCookie('netsettings_changed', data.netsettings_changed); checkNotify(); }, function() { alert('Не удалось получить данные.'); }); } // ################################################################################ /* SpinBox.js Implements a spin box interface for a text field Created by Stephen Morley - http://code.stephenmorley.org/ - and released under the terms of the CC0 1.0 Universal legal code: http://creativecommons.org/publicdomain/zero/1.0/legalcode */ /* Creates a spin box. The parameter is: * * container - either the DOM node to contain the spin box or the ID of the node * options - an object containing various parameters; this optional parameter * defaults to the empty object * * The options object may contain the following keys: * * className - a class name to apply to the container; the class name with the * suffixes 'Up' and 'Down' will be applied to the up and down * buttons. The default value is 'spinBox'. * value - the initial value for the spin box. The default is 0 (subject to * restrictions on the minimum and maximum value) if the input * element did not already exist, or the existing value if the input * element did already exist. * step - the value by which to increment or decrement the value. The * default value is 1. * minimum - the minimum allowed value. The default is not to have a minimum * value. * maximum - the maximum allowed value. The default is not to have a maximum * value. * decimals - the number of decimal places allowed. The default is 0. * name - input name attribute. * * Note that the minimum, maximum, and decimal places restrictions are enforced * for values set by the spin box, but a value outside of these restrictions may * be typed by the user. */ function SpinBox(container, options) { // fetch the DOM node if a string was supplied if (typeof container == 'string') { container = document.getElementById(container); container.innerHTML = ''; } // store the options and set the default values this.options = (options ? options : {}); if (!('className' in this.options)) this.options.className = 'spinBox'; if (!('step' in this.options)) this.options.step = 1; if (!('decimals' in this.options)) this.options.decimals = 0; // check whether the input field should be created var inputs = container.getElementsByTagName('input'); if (inputs.length === 0) { // create the input node this.input = document.createElement('input'); this.input.setAttribute('minimum', this.options.minimum); this.input.setAttribute('maximum', this.options.maximum); this.setValue('value' in this.options ? this.options.value : 0); this.setName('name' in this.options ? this.options.name : ''); container.appendChild(this.input); } else { // store a reference to the input node this.input = inputs[0]; this.setValue(this.options.value ? this.options.value : this.input.value); } // create the up button var upButton = document.createElement('span'); upButton.appendChild(document.createElement('span')); upButton.innerHTML = '+'; container.appendChild(upButton); // create the down button var downButton = document.createElement('span'); downButton.appendChild(document.createElement('span')); downButton.innerHTML = '-'; container.appendChild(downButton); // apply the classes container.className += ' ' + this.options.className; upButton.className = this.options.className + 'Up'; downButton.className = this.options.className + 'Down'; // add the listeners this.addEventListener(this.input, 'mousewheel', this.handleMouseWheel, [], true); this.addEventListener(this.input, 'DOMMouseScroll', this.handleMouseWheel, [], true); this.addEventListener(this.input, 'keydown', this.handleKeyDown, [], true); this.addEventListener(this.input, 'keypress', this.handleKeyPress, [], true); this.addEventListener(this.input, 'keyup', this.stop); this.addEventListener(this.input, 'blur', this.loseFocus); this.addEventListener(upButton, 'mousedown', this.start, [true]); this.addEventListener(upButton, 'mouseup', this.stop); this.addEventListener(upButton, 'mouseout', this.stop); this.addEventListener(downButton, 'mousedown', this.start, [false]); this.addEventListener(downButton, 'mouseup', this.stop); this.addEventListener(downButton, 'mouseout', this.stop); } /* Returns the current value. This will be a number, or the value NaN if the * current contents of the input field do not start with a valid number. */ SpinBox.prototype.getValue = function () { // parse and return the value return parseFloat(this.input.value); }; SpinBox.prototype.loseFocus = function () { if ('minimum' in this.options && this.input.value < this.options.minimum) this.input.value = this.options.minimum.toFixed(this.options.decimals ? this.options.decimals : 0); if ('maximum' in this.options && this.input.value > this.options.maximum) this.input.value = this.options.maximum.toFixed(this.options.decimals ? this.options.decimals : 0); }; SpinBox.prototype.setName = function (name) { // asign input name this.input.name = name; }; /* Sets the value. Restrictions on the minimum and maximum value are enforced. * The parameter is: * * value - the value */ SpinBox.prototype.setValue = function (value) { // ensure the value is within the permitted range if ('minimum' in this.options) value = Math.max(this.options.minimum, value); if ('maximum' in this.options) value = Math.min(this.options.maximum, value); // store the sign var sign = (value < 0 ? '-' : ''); value = Math.abs(value); // determine the multiplier for rounding var multiplier = Math.pow(10, this.options.decimals); // split the value in to integer and fractional parts value = Math.round(value * multiplier); var integer = (value - value % multiplier) / multiplier; var fractional = '' + value % multiplier; // add leading zeros to the fractional part while (fractional.length < this.options.decimals) { fractional = '0' + fractional; } // set the value this.input.value = sign + integer + (this.options.decimals > 0 ? '.' + fractional : ''); // check whether the browser can dispatch events if ('dispatchEvent' in this.input){ // create the event try{ var event = new Event('change', {bubbles : true, cancelable : true}); }catch (e){ var event = document.createEvent('Event'); event.initEvent('change', true, true); } // dispatch the event this.input.dispatchEvent(event); } }; /* Adds an event listener to a node. The event listener is bound to the current * value of 'this'. The parameters are: * * node - the node * event - the event name * listener - the listener functions * parameters - an array of additional parameters to pass to the listener; * these are placed after the event parameter * allowDefault - true if the default action should not be prevented */ SpinBox.prototype.addEventListener = function ( node, event, listener, parameters, allowDefault) { // store a reference to the 'this' object var thisObject = this; // create the bound listener function boundListener(e) { // get the event if it is not supplied if (!e) e = window.event; // call the listener listener.apply(thisObject, [e].concat(parameters)); // prevent the default action if necessary if (!allowDefault) { if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } } } // add the event listener if (node.addEventListener) { node.addEventListener(event, boundListener, false); } else { node.attachEvent('on' + event, boundListener); } }; /* Handles a mouse wheel event by updating the value if the field is active. The * parameter is: * * e - the event object */ SpinBox.prototype.handleMouseWheel = function (e) { // check whether the field is active if (document.activeElement == this.input) { // update the value if (e.wheelDelta) { this.start(e, e.wheelDelta > 1); } else if (e.detail) { this.start(e, e.detail < 1); } this.stop(); // prevent the default action if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } } }; /* Handles a key down event by starting updating if appropriate. The parameter * is: * * e - the event object */ SpinBox.prototype.handleKeyDown = function (e) { // if the up or down keys were pressed, start updating if (e.keyCode == 38) this.start(e, true); if (e.keyCode == 40) this.start(e, false); }; /* Handles a key press event by filtering out invalid characters. The parameter * is: * * e - the event object */ SpinBox.prototype.handleKeyPress = function (e) { // determine the character code var charCode = ('charCode' in e ? e.charCode : e.keyCode); // allow special key presses if (charCode === 0 || e.altKey || e.ctrlKey || e.metaKey) return; // allow a minus sign if the value can be negative if (charCode == 45 && (!('minimum' in this.options) || this.options.minimum < 0)) { return; } // allow a decimal point if the value may contain decimals if (charCode == 46 && this.options.decimals > 0) return; // allow digits if (charCode >= 48 && charCode <= 57) return; // prevent the default action if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } }; /* Starts updating the value. The parameters are: * * e - the event object * up - true to increment the value, false to decrement the value */ SpinBox.prototype.start = function (e, up) { // if the field is disabled or we are already updating, return immediately if (this.input.disabled || 'timeout' in this) return; // set the update step this.updateStep = (up ? this.options.step : -this.options.step); // initialise the timeout delay this.timeoutDelay = 500; // update the value this.update(); }; // Stops update the value. SpinBox.prototype.stop = function () { // clear the timeout if it exists if ('timeout' in this) { window.clearTimeout(this.timeout); delete this.timeout; } }; // Updates the value. SpinBox.prototype.update = function () { // determine the current value var value = parseFloat(this.input.value); if (isNaN(value)) value = 0; // update the value this.setValue(value + this.updateStep); // reduce the delay this.timeoutDelay = Math.max(20, Math.floor(this.timeoutDelay * 0.9)); // call this function again var thisObject = this; this.timeout = window.setTimeout(function () { thisObject.update(); }, this.timeoutDelay); }; /* This code is from Dynamic Web Coding at dyn-web.com Copyright 2009-12 by Sharon Paine See Terms of Use at www.dyn-web.com/business/terms.php regarding conditions under which you may use this code. This notice must be retained in the code as is! */ // DYN_WEB is namespace used for code from dyn-web.com // replacing previous use of dw_ prefix for object names var DYN_WEB = DYN_WEB || {}; DYN_WEB.Event = { add: document.addEventListener ? function (obj, etype, fp, cap) { cap = cap || false; obj.addEventListener(etype, fp, cap); } : function (obj, etype, fp) { obj.attachEvent('on' + etype, fp); }, remove: document.removeEventListener ? function (obj, etype, fp, cap) { cap = cap || false; obj.removeEventListener(etype, fp, cap); } : function (obj, etype, fp) { obj.detachEvent('on' + etype, fp); }, DOMit: function (e) { e = e ? e : window.event; if (!e.target) e.target = e.srcElement; if (!e.preventDefault) e.preventDefault = function () { e.returnValue = false; return false; }; if (!e.stopPropagation) e.stopPropagation = function () { e.cancelBubble = true; }; return e; }, getTarget: function (e) { e = dw_Event.DOMit(e); var tgt = e.target; if (tgt.nodeType != 1) tgt = tgt.parentNode; return tgt; } }; DYN_WEB.Cookie = { set: function (name, value, days, path, domain, secure) { var date, expires; if (typeof days == 'number') { date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = date.toGMTString(); } document.cookie = name + '=' + encodeURIComponent(value) + ( (expires) ? '; expires=' + expires : '' ) + ( (path) ? '; path=' + path : '' ) + ( (domain) ? '; domain=' + domain : '' ) + ( (secure) ? '; secure' : ''); }, get: function (name) { var c, cookies = document.cookie.split(/;\s/g); for (var i = 0; cookies[i]; i++) { c = cookies[i]; if (c.indexOf(name + '=') === 0) { return decodeURIComponent(c.slice(name.length + 1, c.length)); } } return null; }, del: function (name, path, domain) { if (dw_Cookie.get(name)) { document.cookie = name + '=' + ( (path) ? '; path=' + path : '' ) + ( (domain) ? '; domain=' + domain : '' ) + '; expires=Thu, 01-Jan-70 00:00:01 GMT'; } } }; if (!DYN_WEB.Util) { DYN_WEB.Util = { // add props of Obj2 to Obj1 augment: function (Obj1, Obj2) { var prop; for (prop in Obj2) { if (Obj2.hasOwnProperty(prop) && !Obj1[prop]) { Obj1[prop] = Obj2[prop]; } } }, $: function (id) { return document.getElementById(id); } }; } DYN_WEB.Tabs = (function () { // obj holds props: id, useCookies, etc. function Constr(obj) { this.useCookies = obj.useCookies; this.before_hide = obj.before_hide || function () {}; this.on_activate = obj.on_activate || function () {}; this.on_init = obj.on_init || function () {}; Constr.col[obj.id] = this; Constr.init(obj.id); } Constr.col = {}; Constr.prototype = { current: null // id of currently active pane }; return Constr; })(); (function () { var Ut = DYN_WEB.Util, Ev = DYN_WEB.Event, Cookie = DYN_WEB.Cookie, Tabs = DYN_WEB.Tabs; Ut.augment(Tabs, { // static props/methods for DYN_WEB.Tabs setup: function () { var obj, settings = []; if (Tabs.hasBrowserSupport()) { for (var i = 0; obj = arguments[i]; i++) { if (obj.css) { Ut.writeStyleSheet(obj.css); } settings[i] = obj; // save to pass to constructor onload } Ev.add(window, 'load', function () { for (var i = 0; settings[i]; i++) { new Tabs(settings[i]); } }); } }, hasBrowserSupport: function () { if (document.getElementById && document.getElementsByTagName && typeof decodeURI !== 'undefined' && (document.addEventListener || document.attachEvent)) { return true; } return false; }, init: function (tabsetId) { var _this = Tabs.col[tabsetId], links = Tabs.getTabs(tabsetId), // code uses hash in tab links but tabs can also link to other pages // so compare current location to link's href loc = Ut.getURLtoHash(location), lnk, pg, paneId, pane, sel, dflt, cur, c, q, hash; q = Ut.getValueFromQueryString(tabsetId); if (_this.useCookies) { c = Tabs.checkCookie(tabsetId); } // tab in query string or cookie? sel = q ? q : c ? c : null; // add ids and event handlers to links ... for (var i = 0; lnk = links[i]; i++) { paneId = '', pane = ''; // reset pg = Ut.getURLtoHash(lnk); hash = Ut.getHash(lnk); if (lnk.hash && (loc == pg)) { // has hash and points to current page paneId = hash; lnk.id = tabsetId + '__' + paneId; // double underscore between } // if tab associated with tabpane, set up onclick fn if (paneId) { try { pane = Ut.$(paneId); } catch (err) { // showClicked fn throws } // first tab/pane is default if (!dflt) { dflt = paneId; } // if set active in markup, hold as current if (pane && Ut.hasClass(lnk, 'activeTab') && Ut.hasClass(pane, 'activePane')) { _this.current = cur = paneId; } // to pass paneId, tabsetId to showClicked... Ev.add(lnk, 'click', function (paneId, tabsetId) { return function (e) { Tabs.showClicked(e, paneId, tabsetId); }; }(paneId, tabsetId)); } } // check if tab and pane for sel if (sel && (lnk = Ut.$(tabsetId + '__' + sel)) && (pane = Ut.$(sel))) { if (cur && cur !== sel) { Tabs.hideCurrent(tabsetId, cur); } Ut.addClass(lnk, 'activeTab'); Ut.addClass(pane, 'activePane'); _this.current = sel; } else if (!cur && dflt) { Ut.addClass(Ut.$(tabsetId + '__' + dflt), 'activeTab'); Ut.addClass(Ut.$(dflt), 'activePane'); _this.current = dflt; } _this.on_init(); }, getTabs: function (id) { var set = Ut.$(id), list, links; if (!set) { throw new Error('No element matching tabset id found.'); return []; } list = Ut.getElementsByClassName('tabnavs', 'ul', set); if (list.length === 0) { throw new Error('No tabnavs were found in the tabset.'); return []; } links = list[0].getElementsByTagName('a'); return links; }, showClicked: function (e, paneId, tabsetId) { var tabId = tabsetId + '__' + paneId; var _this = Tabs.col[tabsetId]; _this.before_hide(tabId, paneId, tabsetId); Tabs.hideCurrent(tabsetId, _this.current); Ut.addClass(Ut.$(tabId), 'activeTab'); try { Ut.addClass(Ut.$(paneId), 'activePane'); } catch (err) { throw new Error('showClicked can\'t find pane associated with tab. Check tab hash and pane id.'); return false; } _this.current = paneId; if (_this.useCookies) { Tabs.setCookie(tabsetId, paneId); } _this.on_activate(tabId, paneId, tabsetId); if (e) { Ev.DOMit(e); e.preventDefault(); } return false; }, hideCurrent: function (tabsetId, cur) { var tab = Ut.$(tabsetId + '__' + cur), pane = Ut.$(cur); Ut.removeClass(tab, 'activeTab'); Ut.removeClass(pane, 'activePane'); }, checkCookie: function (tabsetId) { var c, cookies, tab_cookies = Cookie.get('dw_Tabs'); if (tab_cookies) { cookies = tab_cookies.split(','); for (var i = 0; cookies[i]; i++) { c = cookies[i]; if (c.indexOf(tabsetId + ':') === 0) { return decodeURI(c.slice(tabsetId.length + 1, c.length)); } } } return null; }, setCookie: function (tabsetId, paneId) { // format for cookies (multiple tabsets supported): dw_Tabs=tabsetId:paneId,tabsetId:paneId; var new_tab_cookies = '', cookies, tab_cookies = Cookie.get('dw_Tabs'); if (tab_cookies) { cookies = tab_cookies.split(','); for (var i = 0; cookies[i]; i++) { if (cookies[i].indexOf(tabsetId + ':') === 0) { cookies[i] = tabsetId + ':' + paneId; new_tab_cookies = cookies.join(','); break; } } if (!new_tab_cookies) { // if no match for this tabsetId new_tab_cookies = tab_cookies + ',' + tabsetId + ':' + paneId; } } else { // no dw_Tabs set yet new_tab_cookies = tabsetId + ':' + paneId; } Cookie.set('dw_Tabs', new_tab_cookies, null, '/'); } }); })(); // util (function () { var Ut = DYN_WEB.Util; // add methods to DYN_WEB.Util Ut.augment(Ut, { trim: function (str) { if (String.prototype.trim) { return str.trim(); // ECMAScript 5 } else { var re = /^\s+|\s+$/g; return str.replace(re, ''); } }, normalizeString: function (str) { var re = /\s\s+/g; return Ut.trim(str).replace(re, ' '); }, hasClass: function (el, cl) { var re = new RegExp('\\b' + cl + '\\b', 'i'); if (re.test(el.className)) { return true; } return false; }, addClass: function (el, cl) { if (!Ut.hasClass(el, cl)) { el.className = Ut.trim(el.className + ' ' + cl); } }, removeClass: function (el, cl) { el.className = Ut.normalizeString(el.className.replace(cl, ' ')); }, getElementsByClassName: function (sClass, sTag, oCont) { oCont = oCont ? oCont : document; if (oCont.getElementsByClassName) { return oCont.getElementsByClassName(sClass); // html5 } else { sTag = sTag || '*'; var result = [], re = new RegExp('\\b' + sClass + '\\b', 'i'), list = oCont.getElementsByTagName(sTag); for (var i = 0; list[i]; i++) { if (re.test(list[i].className)) result.push(list[i]); } return result; } }, // obj: link or window.location getValueFromQueryString: function (name, obj) { obj = obj ? obj : window.location; var pairs, set; if (obj.search && obj.search.indexOf(name != -1)) { pairs = obj.search.slice(1).split('&'); // name/value pairs for (var i = 0; pairs[i]; i++) { set = pairs[i].split('='); // Check each pair for match on name if (set[0] == name && set[1]) { return set[1]; } } } return ''; }, getURLtoHash: function (obj) { obj = obj ? obj : window.location; var href = obj.href, pt = href.indexOf('#'), url = (pt != -1) ? href.slice(0, pt) : href; // remove hash from href return url; }, getHash: function (obj) { obj = obj ? obj : window.location; var hash = ''; if (obj.hash) { // some browsers say true if just #, some '' (ff) hash = obj.hash.slice(1); } return hash; }, // Alternate functions are available that use DOM methods instead of document.write writeStyleSheet: function (file, bScreen) { var screen = (bScreen !== false) ? '" media="screen" />\n' : '"/>\n'; document.write('\n' : '>'; document.write('\n