2024-10-09 12:59:47 +08:00

998 lines
26 KiB
HTML

<%+header%>
<script>
class ModemConfig {
constructor(cfg_id,title){
this.cfg_id = cfg_id;
this.init_view = false;
this.cbi_map = document.querySelector('.cbi-map');
this.fieldset = this.create_fieldset(title);
this.cbi_map.appendChild(this.fieldset);
}
update(){
console.log("update");
}
pause(){
console.log("pause");
}
get_config(){
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "qmodem", "modem_ctrl")%>',
{
"cfg": this.cfg_id,
"action": this.get_action
},
(x, data) => {
this.config = data[this.config_name];
if (this.cb_get) {
this.cb_get(data);
}
}
);
}
set_config(config){
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "qmodem", "modem_ctrl")%>',
{
"cfg": this.cfg_id,
"action": this.set_action,
"params": JSON.stringify(config)
},
(x, data) => {
this.config = data[this.config_name];
if (this.cb_set) {
this.cb_set(data);
}
}
);
}
create_fieldset(title){
var fieldset = document.createElement('fieldset');
fieldset.className = "cbi-section";
var legend = document.createElement('legend');
legend.innerHTML = title;
fieldset.appendChild(legend);
return fieldset;
}
createInput(name,value){
var input = document.createElement('input');
input.type = "text";
input.name = name;
input.value = value;
return input;
}
createBTN(name,cb){
var btn = document.createElement('input');
btn.type = "button";
btn.value = name;
btn.addEventListener('click',cb);
return btn;
}
createRadio(name,value){
var radio = document.createElement('input');
radio.type = "radio";
radio.name = name;
radio.value = value;
return radio;
}
createCheckbox(value){
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.value = value;
return checkbox;
}
createTable(){
let table,tbody;
table = document.createElement('table');
table.classList.add("cbi-section-table");
table.classList.add("table");
tbody = document.createElement('tbody');
table.appendChild(tbody);
return table;
}
createDroplist(dict){
var select = document.createElement('select');
for (let key in dict) {
var option = document.createElement('option');
option.value = key;
option.innerHTML = dict[key];
select.appendChild(option);
}
return select;
}
createTD(innerHTML){
var td = document.createElement('td');
td.classList.add("cbi-section-table-cell");
td.classList.add("td");
td.classList.add("left");
if (innerHTML) {
td.innerHTML = innerHTML;
}
return td;
}
createTH(innerHTML){
var th = document.createElement('th');
th.classList.add("cbi-section-table-cell");
th.classList.add("th");
if (innerHTML) {
th.innerHTML = innerHTML;
}
return th;
}
createTR(){
var tr = document.createElement('tr');
tr.classList.add("cbi-section-table-row");
tr.classList.add("tr");
return tr;
}
createTRHeader(){
var tr = document.createElement('div');
tr.classList.add("tr");
tr.classList.add("cbi-section-table-titles");
tr.classList.add("anonymous");
return tr;
}
init_table(){
var table = this.createTable();
this.fieldset.appendChild(table);
this.tbody = table.querySelector('tbody');
}
hide(){
this.fieldset.style.display = "none";
this.pause();
}
show(){
this.fieldset.style.display = "block";
this.update();
}
}
//锁频功能
class Lockband extends ModemConfig{
constructor(cfg_id){
super(cfg_id,"<%:Lock Band%>");
this.config_name = "lockband";
this.get_action = "get_lockband";
this.set_action = "set_lockband";
this.lockband_config = {};
this.checkboxes = {};
this.available_bandid = {};
this.band_class_map = {};
this.init_table();
this.cb_get = (data) => {
this.render();
}
this.cb_set = (data) => {
this.get_config();
}
this.get_config();
}
set lock(config){
var band_class = config.band_class;
var band_id = config.band_id;
if (!this.lockband_config[band_class].includes(band_id)){
this.lockband_config[band_class].push(band_id)
}
this.checkboxes[band_class][band_id].checked = true;
}
set unlock(config){
var band_class = config.band_class;
var band_id = config.band_id;
this.lockband_config[band_class] = this.lockband_config[band_class].filter(x => x != band_id);
//set checkbox
this.checkboxes[band_class][band_id].checked = false;
}
createCheckbox(band_class,band_name,band_id){
let checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.className = "cbi-input-checkbox";
checkbox.value = band_id;
checkbox.setAttribute("display-band",band_name);
checkbox.addEventListener("change",() => {
if (checkbox.checked){
this.lock = { "band_class": band_class, "band_id": band_id };
}
else{
this.unlock = { "band_class": band_class, "band_id": band_id };
}
});
this.checkboxes[band_class][band_id] = checkbox;
if (this.lockband_config[band_class].includes(band_id)) {
this.lock = { "band_class": band_class, "band_id": band_id };
}
}
createcheckboxes(band_class){
var band = this.config[band_class];
var available_band = band.available_band;
var lock_band = band.lock_band;
this.lockband_config[band_class] = lock_band;
if ( available_band.length == 0) {
return;
}
if (this.checkboxes[band_class] == undefined) {
this.checkboxes[band_class] = {};
}
if (this.available_bandid[band_class] == undefined) {
this.available_bandid[band_class] = [];
}
for (let band_cfg of available_band) {
let band_name = band_cfg.band_name;
let band_id = band_cfg.band_id;
if (this.available_bandid[band_class].includes(band_id) == false) {
this.available_bandid[band_class].push(band_id);
}
this.createCheckbox(band_class,band_name,band_id);
}
}
submit(band_class)
{
var sorted = this.lockband_config[band_class].sort();
var config = '';
for (let band_id of sorted) {
config += band_id + ",";
}
var lockband_cfg = {
"band_class": band_class,
"lock_band": config.slice(0,-1)
}
var cfg_string = JSON.stringify(lockband_cfg);
this.set_config(cfg_string);
}
select_all(band_class){
//if all selected, then unselect all
let lockall = this.lockband_config[band_class].length != this.available_bandid[band_class].length;
for (let band_id of this.available_bandid[band_class]) {
if (lockall) {
this.lock = { "band_class": band_class, "band_id": band_id };
}
else{
this.unlock = { "band_class": band_class, "band_id": band_id };
}
}
}
render() {
for (let band_class in this.band_class_map){
if (this.config[band_class] == undefined) {
this.band_class_map[band_class].header.style.display = "none";
this.band_class_map[band_class].tr.style.display = "none";
this.band_class_map[band_class].select_all_btn.style.display = "none";
this.band_class_map[band_class].submit_btn.style.display = "none";
}
else{
this.band_class_map[band_class].header.style.display = "";
this.band_class_map[band_class].tr.style.display = "";
this.band_class_map[band_class].select_all_btn.style.display = "";
this.band_class_map[band_class].submit_btn
}
}
for (let band_class in this.config) {
let header, tr, td, select_all_btn, submit_btn;
this.createcheckboxes(band_class);
if (this.band_class_map[band_class] == undefined)
{
this.createBandTable(band_class);
}
header = this.band_class_map[band_class].header;
tr = this.band_class_map[band_class].tr;
select_all_btn = this.band_class_map[band_class].select_all_btn;
submit_btn = this.band_class_map[band_class].submit_btn
td = document.createElement('td');
td.classList.add("cbi-section-table-cell");
td.classList.add("td")
td.style.display = "flex";
td.style.flexWrap = "wrap";
//clear tr
while (tr.firstChild) {
tr.removeChild(tr.firstChild);
}
tr.appendChild(td);
for (let checkbox in this.checkboxes[band_class]) {
let display_value = this.checkboxes[band_class][checkbox].getAttribute("display-band");
let span = document.createElement('span');
span.innerHTML = display_value;
td.appendChild(this.checkboxes[band_class][checkbox]);
td.appendChild(span);
}
}
}
createBandTable(band_class){
let tr_header, th, tr, td, select_all_btn, submit_btn;
tr_header = document.createElement('div');
tr_header.className = "tr cbi-section-table-titles anonymous";
th = document.createElement('div');
th.className = "th cbi-section-table-cell";
th.innerHTML = band_class;
tr_header.appendChild(th);
tr = document.createElement('tr');
tr.className = "tr cbi-section-table-row";
select_all_btn = this.createBTN("<%:Select All%>", () => {
this.select_all(band_class);
});
submit_btn = this.createBTN("<%:Submit%>", () => {
this.submit(band_class);
});
this.band_class_map[band_class] = {
"header": tr_header,
"tr": tr,
"select_all_btn": select_all_btn,
"submit_btn": submit_btn
}
this.tbody.appendChild(tr_header);
this.tbody.appendChild(tr);
this.tbody.appendChild(select_all_btn);
this.tbody.appendChild(submit_btn);
}
update() {
console.log(JSON.stringify(this.lockband_config));
console.log(JSON.stringify(this.available_bandid));
console.log(JSON.stringify(this.band_class_map));
console.log(JSON.stringify(this.config));
this.get_config();
}
}
class RatPrefer extends ModemConfig {
constructor(cfg_id){
super(cfg_id,"<%:Rat Prefer%>");
this.config_name = "network_prefer";
this.get_action = "get_network_prefer";
this.set_action = "set_network_prefer";
this.selected_rat = [];
this.available_rat = [];
this.init_table();
this.create_submit_btn();
}
cb_get(data){
//clear selected_rat
this.selected_rat = [];
//clear available_rat
this.available_rat = [];
for (let key in this.config){
if (this.config[key] == 1) {
this.selected_rat.push(key);
}
this.available_rat.push(key);
}
this.render_checkbox();
this.render_current_mode();
}
cb_set(data){
this.get_config();
}
render_current_mode(){
let selected_mode = []
for (let rat in this.config) {
if (this.config[rat] == 1) {
selected_mode.push(rat);
}
}
this.current_mode = selected_mode.join(',');
this.current_mode_td.innerHTML = this.current_mode;
}
render_checkbox(){
if (this.init_view == false) {
this.init_ele();
this.init_view = true;
}
this.createCheckboxes();
}
create_submit_btn(){
var submit_btn = this.createBTN("<%:Submit%>",() => {
this.submit();
});
this.fieldset.appendChild(submit_btn);
}
createCheckbox(rat){
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.value = rat;
checkbox.addEventListener('change',() => {
if (checkbox.checked) {
this.selected_rat.push(rat);
}
else{
this.selected_rat = this.selected_rat.filter(x => x != rat);
}
});
return checkbox;
}
createCheckboxes(){
//clear select_td
while (this.select_td.firstChild) {
this.select_td.removeChild(this.select_td.firstChild);
}
var network_prefer = this.config;
for (let rat of this.available_rat) {
var checkbox = this.createCheckbox(rat);
if (this.selected_rat.includes(rat)) {
checkbox.checked = true;
}
var span = document.createElement('span');
span.innerHTML = rat;
this.select_td.appendChild(checkbox);
this.select_td.appendChild(span);
}
}
update(){
this.get_config();
}
submit(){
this.set_config(JSON.stringify(this.selected_rat));
}
init_ele(){
var header_tr,current_mode_th,select_th,setting_tr,current_mode_td,select_td;
header_tr = this.createTRHeader();
current_mode_th = this.createTH("<%:Current Mode%>");
select_th = this.createTH("<%:Setting%>");
setting_tr = this.createTR();
current_mode_td = this.createTD();
select_td = this.createTD();
header_tr.appendChild(current_mode_th);
header_tr.appendChild(select_th);
setting_tr.appendChild(current_mode_td);
setting_tr.appendChild(select_td);
this.tbody.appendChild(header_tr);
this.tbody.appendChild(setting_tr);
this.current_mode_td = current_mode_td;
this.select_td = select_td;
}
}
class DialMode extends ModemConfig {
constructor(cfg_id){
super(cfg_id,"<%:Dial Mode%>");
this.config_name = "mode";
this.get_action = "get_mode";
this.set_action = "set_mode";
this.avalibale_mode = [];
this.selected_mode = null;
this.init_table();
this.td_map = {
"current_mode": null,
"radio_div": null,
}
this.cb_get = (data) => {
this.render();
}
this.cb_set = (data) => {
this.get_config();
}
this.get_config();
}
render(){
if (this.td_map["current_mode"] == null) {
this.init_ele();
}
for (let key in this.config){
if (this.avalibale_mode.includes(key) == false)
{
this.avalibale_mode.push(key);
}
if (this.config[key] == 1) {
this.selected_mode = key;
this.td_map.current_mode.innerHTML = key;
}
}
this.create_mode_radio();
}
init_ele(){
var radio_div_th, current_mode_th, radio_div, current_mode, header_tr, setting_tr;
header_tr = document.createElement('div');
header_tr.className = "tr cbi-section-table-titles anonymous";
radio_div_th = document.createElement('div');
radio_div_th.className = "th cbi-section-table-cell";
radio_div_th.innerHTML = "<%:Dial Mode%>";
current_mode_th = document.createElement('div');
current_mode_th.className = "th cbi-section-table-cell";
current_mode_th.innerHTML = "<%:Current Mode%>";
setting_tr = document.createElement('div');
setting_tr.className = "tr cbi-section-table-row";
radio_div = document.createElement('div');
radio_div.className = "td cbi-section-table-cell left";
current_mode = document.createElement('div');
current_mode.className = "td cbi-section-table-cell left";
header_tr.appendChild(current_mode_th);
header_tr.appendChild(radio_div_th);
setting_tr.appendChild(current_mode);
setting_tr.appendChild(radio_div);
this.tbody.appendChild(header_tr);
this.tbody.appendChild(setting_tr);
this.td_map["radio_div"] = radio_div;
this.td_map["current_mode"] = current_mode;
this.mode_btn = this.createBTN("<%:Submit%>",() => {
this.set_config(this.selected_mode);
});
this.tbody.appendChild(this.mode_btn);
}
create_mode_radio(){
while (this.td_map.radio_div.firstChild) {
this.td_map.radio_div.removeChild(this.td_map.radio_div.firstChild);
}
for (let mode of this.avalibale_mode) {
let radio = this.createRadio("mode",mode);
if (mode == this.selected_mode) {
radio.checked = true;
}
radio.addEventListener('change',() => {
this.selected_mode = mode;
});
let span = document.createElement('span');
span.innerHTML = mode;
//clear radio_div
this.td_map.radio_div.appendChild(radio);
this.td_map.radio_div.appendChild(span);
}
}
update(){
this.get_config();
}
}
class NeighborCell extends ModemConfig {
constructor(cfg_id){
super(cfg_id,"<%:Neighbor Cell%>");
this.config_name = "neighborcell";
this.get_action = "get_neighborcell";
this.set_action = "set_neighborcell";
this.task = null;
this.init_nc_table();
this.get_config();
}
pause(){
if (this.task != null) {
clearInterval(this.task);
}
}
update(){
this.task = setInterval(() => {
this.get_config();
},10000);
}
nr_options(){
if (this.rat_input.selectedIndex == 0) {
this.band_tr.style.display = "none";
this.scs_tr.style.display = "none";
}
else{
this.band_tr.style.display = "";
this.scs_tr.style.display = "";
}
}
init_nc_table(){
var neighborcell_table,setting_table,status_table ;
neighborcell_table = this.createTable();
status_table = this.createTable();
setting_table = this.createTable();
this.fieldset.appendChild(neighborcell_table);
this.fieldset.appendChild(status_table);
this.fieldset.appendChild(setting_table);
this.neighborcell_table = neighborcell_table.querySelector('tbody');
this.status_table = status_table.querySelector('tbody');
this.setting_table = setting_table.querySelector('tbody');
var pci_tr,arfcn_tr,band_tr,scs_tr,header,td,td1,th,pci_input,arfcn_input,band_input,scs_input,rat_input,rat_tr;
var status_th,status_trh;
header = this.createTRHeader();
th = this.createTH("<%:Lock Cell Setting%>");
header.appendChild(th);
rat_input = this.createDroplist({0:"LTE",1:"NR"});
rat_tr = this.createTR();
td = this.createTD("<%:RAT%>");
td1 = this.createTD();
td1.appendChild(rat_input);
rat_tr.appendChild(td);
rat_tr.appendChild(td1);
pci_tr = this.createTR();
td = this.createTD("<%:PCI%>");
pci_input = this.createInput("pci","");
td1 = this.createTD();
td1.appendChild(pci_input);
pci_tr.appendChild(td);
pci_tr.appendChild(td1);
arfcn_tr = this.createTR();
td = this.createTD("<%:ARFCN%>");
arfcn_input = this.createInput("arfcn","");
td1 = this.createTD();
td1.appendChild(arfcn_input);
arfcn_tr.appendChild(td);
arfcn_tr.appendChild(td1);
band_tr = this.createTR();
td = this.createTD("<%:Band%>");
band_input = this.createInput("band","");
td1 = this.createTD();
td1.appendChild(band_input);
band_tr.appendChild(td);
band_tr.appendChild(td1);
scs_tr = this.createTR();
td = this.createTD("<%:SCS%>");
scs_input = this.createDroplist({0:"15KHZ",1:"30KHZ"});
td1 = this.createTD();
td1.appendChild(scs_input);
scs_tr.appendChild(td);
scs_tr.appendChild(td1);
status_th = this.createTH("<%:Status%>");
status_trh = this.createTRHeader();
status_trh.appendChild(status_th);
this.status_table.appendChild(status_trh);
this.pci_input = pci_input;
this.arfcn_input = arfcn_input;
this.band_input = band_input;
this.scs_input = scs_input;
this.rat_input = rat_input;
this.band_tr = band_tr;
this.scs_tr = scs_tr;
this.band_tr.style.display = "none";
this.scs_tr.style.display = "none";
this.rat_input.addEventListener('change',()=>{
this.nr_options();
});
var submit_btn = this.createBTN("<%:Submit%>",() => {
var config = {
"rat": this.rat_input.selectedIndex,
"pci": this.pci_input.value,
"arfcn": this.arfcn_input.value,
"band": this.band_input.value,
"scs": this.scs_input.selectedIndex
}
this.set_config(JSON.stringify(config));
});
this.setting_table.appendChild(header);
this.setting_table.appendChild(rat_tr);
this.setting_table.appendChild(pci_tr);
this.setting_table.appendChild(arfcn_tr);
this.setting_table.appendChild(band_tr);
this.setting_table.appendChild(scs_tr);
this.setting_table.appendChild(submit_btn);
}
render_neighborcell(){
//clear neighborcell_table
while (this.neighborcell_table.querySelector("tr")) {
let remove = this.neighborcell_table.querySelector("tr")
this.neighborcell_table.removeChild(remove);
}
var nr,lte,tr_left
nr = this.config.NR;
lte = this.config.LTE;
for (let cell_info of nr) {
this.create_nc_tr(1,cell_info);
}
for (let cell_info of lte) {
this.create_nc_tr(0,cell_info);
}
}
render_status(){
//clear status_table
while (this.status_table.querySelector("tr")) {
this.status_table.removeChild(this.status_table.querySelector("tr"));
}
var status = this.config.lockcell_status;
for (let key in status) {
if (status[key] != ""){
this.create_status_tr(key + ":" + status[key].toUpperCase());
}
}
}
create_status_tr(status){
var tr = this.createTR();
var td = this.createTD(status);
tr.appendChild(td);
this.status_table.appendChild(tr);
}
create_nc_tr(rat,cell_info){
if (rat == 0) {
var text = "LTE:";
}
else{
var text = "NR:";
}
for (let key in cell_info) {
if (cell_info[key] != ""){
text += key + ":" + cell_info[key] + " ";
}
}
let tr_left = this.createTD(text);
let tr_right = this.create_copy_btn_td(rat,cell_info.pci,cell_info.arfcn);
let tr = this.createTR();
tr.appendChild(tr_left);
tr.appendChild(tr_right);
this.neighborcell_table.appendChild(tr);
}
create_copy_btn_td(rat,pci,arfcn){
var copy_btn = this.createBTN("<%:Copy%>",() => {
this.pci_input.value = pci;
this.arfcn_input.value = arfcn;
this.rat_input.selectedIndex = rat;
this.nr_options()
});
var td = document.createElement('td');
td.className = "td cbi-section-table-cell left";
td.setAttribute("width","10%");
td.appendChild(copy_btn);
return td;
}
cb_get(){
this.render_neighborcell();
this.render_status();
}
}
class IMEI extends ModemConfig {
constructor(cfg_id){
super(cfg_id,"<%:Set IMEI%>");
this.config_name = "imei";
this.get_action = "get_imei";
this.set_action = "set_imei";
this.get_config();
this.render();
}
render(){
this.imei_input = this.createInput("imei",this.config);
this.imei_btn = this.createBTN("<%:Submit%>",() => {
this.set_config(this.imei_input.value);
});
this.fieldset.appendChild(this.imei_input);
this.fieldset.appendChild(this.imei_btn);
}
cb_get(){
this.imei_input.value = this.config;
}
cb_set(){
this.imei_input.value = this.config;
}
update(){
this.get_config();
}
}
class Select_Modem {
constructor(){
this.modem_selector = document.getElementById('modem_selector');
this.cfg_id = null;
this.modem_cfg_list = [];
this.create_modem_cfg_selector();
this.update_modem_cfg_list();
}
create_modem_cfg_selector() {
var selector = document.createElement('select');
selector.addEventListener('change', (event) => {
this.cfg_id = event.target.value;
this.update_cfg_id(this.cfg_id);
});
this.modem_selector.appendChild(selector);
this.selector = selector;
}
update_modem_cfg_list() {
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "qmodem", "get_modem_cfg")%>', {}, (x, data) => {
var new_cfg_list = [];
var cfgs = data.cfgs;
for (let i = 0; i < cfgs.length; i++) {
var cfg = cfgs[i];
var name = cfg.name;
var value = cfg.cfg;
new_cfg_list.push({ "value": value, "name": name });
}
if (JSON.stringify(new_cfg_list) != JSON.stringify(this.modem_cfg_list)) {
console.log(this.modem_cfg_list)
console.log(new_cfg_list)
this.cfg_options = new_cfg_list;
console.log("update_cfg_list")
}
});
}
set cfg_options(value) {
var longger = this.modem_cfg_list.length > value.length ? this.modem_cfg_list : value;
if (longger.length == 0) {
return;
}
for (let i = 0; i < longger.length; i++) {
var option = this.selector.options[i];
if (i < value.length) {
if (i >= this.selector.options.length) {
option = document.createElement('option');
this.selector.appendChild(option);
}
option.value = value[i].value;
option.innerHTML = value[i].name;
}
else {
this.selector.removeChild(option);
}
}
this.cfg_id = this.selector.value;
this.modem_cfg_list = value;
this.update_cfg_id(this.cfg_id);
}
}
class TabMenu extends Select_Modem {
functions = {
"DialMode": {"class": DialMode, "name":"<%:Dial Mode%>"},
"RatPrefer": {"class": RatPrefer, "name":"<%:Rat Prefer%>"},
"IMEI": {"class": IMEI, "name": "<%:Set IMEI%>"},
"NeighborCell": {"class": NeighborCell, "name": "<%:Neighbor Cell%>"},
"LockBand": {"class": Lockband, "name":"<%:Lock Band%>"}
}
constructor(){
super();
this.cbi_map = document.querySelector('.cbi-map');
this.class_map = {};
this.datatabs = [];
this.create_tabmenu();
}
update_cfg_id(cfg_id){
for (let key in this.class_map) {
this.class_map[key].cfg_id = cfg_id;
}
//check if all datatab not selected
for (let tab of this.datatabs) {
if (tab.className == "cbi-tab") {
this.switch_tab(tab);
return;
}
}
this.switch_tab(this.datatabs[0]);
}
create_tabmenu(){
//add support function to tabmenu
var tabmenu = document.createElement('ul');
tabmenu.className = "cbi-tabmenu";
for (let key in this.functions) {
var li = document.createElement('li');
li.className = "cbi-tab-disabled";
li.innerHTML = this.functions[key].name;
li.setAttribute("data-tab", key);
li.addEventListener('click', (event) => {
this.switch_tab(event.target)
});
tabmenu.appendChild(li);
this.datatabs.push(li);
}
this.cbi_map.appendChild(tabmenu);
this.tabmenu = tabmenu;
}
switch_tab(target){
target.className = "cbi-tab";
target.style.display = "";
var datatab = target.getAttribute("data-tab");
for (let i = 0; i < this.datatabs.length; i++) {
if (this.datatabs[i] != target) {
this.datatabs[i].className = "cbi-tab-disabled";
}
}
if (this.class_map[datatab] == undefined) {
this.class_map[datatab] = new this.functions[datatab].class(this.cfg_id);
}
for (let key in this.class_map) {
this.class_map[key].hide();
}
this.class_map[datatab].show();
}
}
window.onload = function(){
var tabmenu = new TabMenu();
}
</script>
<style>
.cbi-tabmenu li {
padding: 0.5rem;
}
</style>
<div class="cbi-map">
<fieldset class="cbi-section">
<table class="table">
<tbody>
<tr class="tr">
<td class="td" width="33%"><%:Modem Name%></td>
<td class="td" id="modem_selector">
</td>
</tr>
</tbody>
</table>
</fieldset>
</div>
<%+footer%>