Files
repo-smod-atsc/out/rootfs/aw/anywave/web/www/sys_psip.html
T

848 lines
37 KiB
HTML
Executable File

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title id="webtitle"></title>
<link href="css/styles.css" rel="stylesheet" media="screen">
<script src="js/auth.js"></script>
<script src="js/jquery.js"></script>
<script src="js/dashboard.js"></script>
<script>
var time_sec_cnt=0;
var g_remot_local_ctrl = 0; // 0 remote 1 local
var lastTime = new Date().getTime();
var currentTime = new Date().getTime();
var timeOut = 20 * 60 * 1000; // 20 min
$(function(){
// Listen to multiple types of user activity to prevent timeout
$(document).on('mousemove keydown click scroll touchstart', function(){
lastTime = new Date().getTime();
});
});
function testTime(){
currentTime = new Date().getTime();
if(currentTime - lastTime > timeOut){
window.location.href="login.cgi?logout=1"
}
time_sec_cnt=time_sec_cnt+1;
if(time_sec_cnt%3==0){
get_remote_local_ctrl();
if(g_remot_local_ctrl==1) { // local
SetFormDefaults();
}
refreshDashboard();
}
}
// Timer check
window.setInterval(testTime, 1000);
refreshDashboard();
function get_remote_local_ctrl() {
var queryData = "sys_cfg=&";
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
// Handle case where data is a JSON object (e.g., session expired)
if (typeof data === 'object' && data !== null) {
if (data.error === 'session_expired' && data.redirect) {
window.location.href = data.redirect;
return;
}
console.error('Received JSON error response:', data);
return;
}
var table = data.split("|");
g_remot_local_ctrl = Number(table[0].split("#")[5]);
document.title = table[0].split("#")[11];
});
}
// Updated SetFormDefaults to populate the Single Form
function SetFormDefaults() {
// 1. DISABLE BUTTONS START (only in Remote mode)
if(g_remot_local_ctrl == 1) {
// Local mode: just fetch data, don't change button text
var queryData = "tsid_psip=&psip_cfg=&web_title=&";
} else {
// Remote mode: show LOADING indicator
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
.attr("disabled", true)
.val("LOADING...");
var queryData = "tsid_psip=&psip_cfg=&web_title=&";
}
$.get("atsc_status_cfg.cgi?" + queryData, function(data, status) {
// Handle case where data is a JSON object (e.g., session expired)
if (typeof data === 'object' && data !== null) {
if (data.error === 'session_expired' && data.redirect) {
window.location.href = data.redirect;
return;
}
console.error('Received JSON error response:', data);
return;
}
var table = data.split("|");
var form = table[0].split("#");
var title= table[1].split("#");
// 1. Handle Top Settings (Form 0)
var cf = document.getElementById("tsid_form");
var i = 1;
cf.ts_edit.value = form[i++];
cf.tsid.value = form[i++];
var index_max = Number(form[i++]);
// 2. Handle PSIP Table (Form 1 - The new single form)
var psipForm = document.getElementById("psip_table_form");
// Loop through all 13 potential rows (0 to 12)
for (var k = 0; k < 13; k++) {
// Populate inputs by name (e.g., "index0", "sht_name0")
if(psipForm.elements['index' + k]) {
psipForm.elements['index' + k].value = form[i++];
psipForm.elements['sht_name' + k].value = form[i++];
psipForm.elements['maj_num' + k].value = form[i++];
psipForm.elements['min_num' + k].value = form[i++];
}
// Hide unused rows
var row = document.getElementById("psip" + k);
if (row) {
if (k >= index_max && k != 0) {
row.style.display = "none";
} else {
row.style.display = "table-row"; // Ensure visible rows display correctly
}
}
}
// 2. RE-ENABLE BUTTONS END (only in Remote mode)
if(g_remot_local_ctrl == 1) {
// Local mode: keep buttons disabled
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
.attr("disabled", true)
.val("Local Mode");
} else {
// Remote mode: enable buttons
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
.attr("disabled", false)
.val("Set");
}
if (typeof setTsidFormSnapshotUpdate === 'function') setTsidFormSnapshotUpdate();
if (typeof psipFormSnapshotUpdate === 'function') psipFormSnapshotUpdate();
document.getElementById('webtitle').textContent = title[1];
document.getElementById('webtitle_header').textContent = title[1];
}).fail(function() {
// Optional: Error handling
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]').val("LOAD FAILED");
});
}
// ----- SET (unsaved) reminder: tsid_form (per-row: CTRL vs TSID) + psip_table_form (per-row), vanilla JS -----
var tsidFormSnapshotPerRow = [];
function getFormSnapshot(formId) {
var f = document.getElementById(formId);
if (!f) return [];
var out = [], els = f.querySelectorAll('select, input:not([type="button"])'), i, el, v;
for (i = 0; i < els.length; i++) {
el = els[i];
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : (el.value || '');
out.push({ name: el.name || el.id, value: String(v) });
}
return out;
}
function getFormSnapshotPerRowTsid(formId) {
var f = document.getElementById(formId);
if (!f) return [];
var rows = f.querySelectorAll('table tr'), out = [], i;
for (i = 0; i < rows.length; i++) {
if (rows[i].querySelector('input[type="button"]')) out.push(getRowValues(rows[i]));
}
return out;
}
function setTsidRowButtonState(tr, unsaved) {
var btn = tr.querySelector('input[type="button"]');
if (!btn || btn.disabled) return;
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
}
function setTsidFormSnapshotUpdate() {
var f = document.getElementById('tsid_form');
if (f) tsidFormSnapshotPerRow = getFormSnapshotPerRowTsid('tsid_form');
f = document.getElementById('tsid_form');
if (f) {
var rows = f.querySelectorAll('table tr');
for (var i = 0; i < rows.length; i++) {
if (rows[i].querySelector('input[type="button"]')) setTsidRowButtonState(rows[i], false);
}
}
}
function updateTsidFormRowButtonStates() {
var f = document.getElementById('tsid_form');
if (!f || !tsidFormSnapshotPerRow.length) return;
var rows = f.querySelectorAll('table tr');
var rowIdx = 0;
for (var i = 0; i < rows.length; i++) {
if (!rows[i].querySelector('input[type="button"]')) continue;
var dirty = rowIdx < tsidFormSnapshotPerRow.length && isRowDirty(getRowValues(rows[i]), tsidFormSnapshotPerRow[rowIdx]);
setTsidRowButtonState(rows[i], dirty);
rowIdx++;
}
}
var psipFormSnapshotPerRow = [];
function getRowValues(tr) {
var out = [], els = tr.querySelectorAll('select, input:not([type="button"])'), i, el, v;
for (i = 0; i < els.length; i++) {
el = els[i];
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : (el.value || '');
out.push({ name: el.name || el.id, value: String(v) });
}
return out;
}
function getFormSnapshotPerRow(formId) {
var f = document.getElementById(formId);
if (!f) return [];
var rows = f.querySelectorAll('table tr'), out = [], i;
for (i = 0; i < rows.length; i++) {
if (rows[i].querySelector('input[type="button"]')) out.push(getRowValues(rows[i]));
}
return out;
}
function isRowDirty(rowValues, rowSnapshot) {
if (rowValues.length !== rowSnapshot.length) return true;
for (var i = 0; i < rowValues.length; i++) {
if (rowValues[i].name !== rowSnapshot[i].name || rowValues[i].value !== rowSnapshot[i].value) return true;
}
return false;
}
function setPsipRowButtonState(tr, unsaved) {
var btn = tr.querySelector('input[type="button"]');
if (!btn || btn.disabled) return;
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
}
function updateAllPsipRowButtonStates(formId) {
var f = document.getElementById(formId);
if (!f || !psipFormSnapshotPerRow.length) return;
var rows = f.querySelectorAll('table tr');
var rowIdx = 0;
for (var i = 0; i < rows.length; i++) {
if (!rows[i].querySelector('input[type="button"]')) continue;
setPsipRowButtonState(rows[i], rowIdx < psipFormSnapshotPerRow.length && isRowDirty(getRowValues(rows[i]), psipFormSnapshotPerRow[rowIdx]));
rowIdx++;
}
}
function setAllPsipRowButtonsSaved() {
var f = document.getElementById('psip_table_form');
if (!f) return;
var rows = f.querySelectorAll('table tr');
for (var i = 0; i < rows.length; i++) setPsipRowButtonState(rows[i], false);
}
function psipFormSnapshotUpdate() {
psipFormSnapshotPerRow = getFormSnapshotPerRow('psip_table_form');
setAllPsipRowButtonsSaved();
}
function attachPsipUnsavedListeners() {
var f = document.getElementById('tsid_form');
if (f) {
f.addEventListener('change', updateTsidFormRowButtonStates);
f.addEventListener('input', updateTsidFormRowButtonStates);
}
var pf = document.getElementById('psip_table_form');
if (pf) pf.addEventListener('change', function() { updateAllPsipRowButtonStates('psip_table_form'); });
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attachPsipUnsavedListeners);
} else {
attachPsipUnsavedListeners();
}
function refresh_show(){
get_remote_local_ctrl();
SetFormDefaults();
refreshDashboard();
}
function cmd_confirm() {
return confirm("Please choose to confirm or cancel!");
}
function tsid_psip_top_set() {
var postData = "tsid_psip=";
var cf = document.forms[0];
postData += "#"+cf.ts_edit.value;
postData += "#"+cf.tsid.value;
if(cmd_confirm()){
$.post("atsc_status_cfg.cgi", postData, function(data, status){
if(status=="success"){
setTimeout(function() { SetFormDefaults(); }, 2000);
} else {
alert("post val err");
}
});
}
}
// Updated Sub Set Function to read from Single Form
function tsid_psip_sub_set(clickedIndex) {
var postData = "psip_cfg=";
var psipForm = document.getElementById("psip_table_form");
// Iterate through all 13 rows to build the data string
for(var k=0; k<13; k++) {
// Access values directly from the single form using names
postData += "#" + psipForm.elements['index'+k].value;
postData += "#" + psipForm.elements['sht_name'+k].value;
postData += "#" + psipForm.elements['maj_num'+k].value;
postData += "#" + psipForm.elements['min_num'+k].value;
}
if(cmd_confirm()){
$.post("atsc_status_cfg.cgi", postData, function(data, status){
if(status=="success"){
setTimeout(function() { SetFormDefaults(); }, 2000);
} else {
alert("post val err");
}
});
}
}
// Modal Logic - Open and close account modal
function openAccountModal() {
// Fetch current username from server
$.get("login.cgi?action=get_user", function(data) {
var trimmedData = (data || "").trim();
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
document.getElementById('current_user').value = trimmedData;
}
document.getElementById('accountModal').style.display = 'block';
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
}).fail(function() {
document.getElementById('accountModal').style.display = 'block';
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
});
}
function closeAccountModal() {
document.getElementById('accountModal').style.display = 'none';
// Clear sensitive fields
document.getElementById('current_pwd').value = '';
document.getElementById('new_pwd').value = '';
document.getElementById('confirm_pwd').value = '';
}
// Validates that a string contains only printable characters (excluding space)
function isValidPrintableString(str) {
// Regular expression to check for printable characters (ASCII 33-126), excluding space
// Space is ASCII 32, and we want to exclude it
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
return printableCharRegex.test(str);
}
// Validation - All required fields must be filled
function validateAccountForm() {
var currentUser = document.getElementById('current_user').value;
var currentPwd = document.getElementById('current_pwd').value;
var newUsername = document.getElementById('new_user').value;
var newPwd = document.getElementById('new_pwd').value;
var confirmPwd = document.getElementById('confirm_pwd').value;
// Current password is required (cannot be empty)
if (!currentPwd || currentPwd.trim() === "") {
alert("Current password is required");
return false;
}
// Validate current password contains only printable characters
if (!isValidPrintableString(currentPwd)) {
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
return false;
}
// New password is required (cannot be empty)
if (!newPwd || newPwd.trim() === "") {
alert("New password is required");
return false;
}
// Validate new password contains only printable characters
if (!isValidPrintableString(newPwd)) {
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
return false;
}
// Validate new password length (max 16 chars)
if (newPwd.length > 16) {
alert("New password must be no more than 16 characters");
return false;
}
// Validate new password length
if (newPwd.length < 6) {
alert("New password must be at least 6 characters");
return false;
}
// Confirm password must match new password
if (newPwd !== confirmPwd) {
alert("New passwords do not match");
return false;
}
// Validate confirm password contains only printable characters
if (!isValidPrintableString(confirmPwd)) {
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
return false;
}
// Validate confirm password length (max 16 chars)
if (confirmPwd.length > 16) {
alert("Confirm password must be no more than 16 characters");
return false;
}
// Validate new username if provided
if (newUsername && newUsername.trim() !== "") {
// Validate new username contains only printable characters
if (!isValidPrintableString(newUsername)) {
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
return false;
}
// Validate new username length (max 16 chars)
if (newUsername.length > 16) {
alert("New username must be no more than 16 characters");
return false;
}
}
return true;
}
// Form submission handler using fetch API
document.addEventListener('DOMContentLoaded', function() {
var accountForm = document.getElementById('accountForm');
if (accountForm) {
accountForm.addEventListener('submit', function(e) {
e.preventDefault();
if (!validateAccountForm()) return;
var formData = new URLSearchParams({
Username: document.getElementById('current_user').value,
OldPassword: document.getElementById('current_pwd').value,
NewUsername: document.getElementById('new_user').value,
NewPassword: document.getElementById('new_pwd').value,
ConfirmPassword: document.getElementById('confirm_pwd').value
});
fetch('login.cgi?action=change_account', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
alert("Update successful! Please login again.");
closeAccountModal();
// Redirect to login page after 1.5 seconds
setTimeout(function() {
window.location.href = 'login.cgi?logout=1';
}, 1500);
} else {
alert(data.error || "Update failed");
}
})
.catch(function(err) {
alert("Network error: " + err);
});
});
}
});
</script>
</head>
<body onload="refresh_show()">
<div class="app-layout">
<aside class="app-sidebar">
<ul class="items">
<li><a href="status_info.html" title="Status">Status</a></li>
<li><a href="sys_set.html" title="Settings">Settings</a></li>
<li><a href="sys_rf.html" title="RF Control">RF Control</a></li>
<li class="active"><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
<li><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
<li><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
<li><a href="log_output.html" title="Log">Log</a></li>
</ul>
<div class="sidebar-footer">
<h4>Anywave Broadcast Inc.</h4>
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
</div>
</aside>
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
<header class="app-header">
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
<h2 id="webtitle_header"><span></span></h2>
<h3>
<div class="dropdown">
<button class="dropbtn-modern">Admin &#9662;</button>
<div class="dropdown-content">
<a href="#" onclick="openAccountModal(); return false;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"></circle>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
</svg>
Account Settings
</a>
<a href="login.cgi?logout=1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
<polyline points="16 17 21 12 16 7"></polyline>
<line x1="21" y1="12" x2="9" y2="12"></line>
</svg>
Logout
</a>
</div>
</div>
</h3>
</header>
<!-- Fixed Dashboard Summary - Top of page, under header -->
<div class="dashboard-fixed">
<div class="summary-dashboard">
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
<span class="summary-label">Frequency</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-neutral" id="sum_freq">--</span>
<span class="summary-unit">MHz</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
<span class="summary-label">SNR</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-ok" id="sum_snr">--</span>
<span class="summary-unit">dB</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
<span class="summary-label">UIMD</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-ok" id="sum_uimd">--</span>
<span class="summary-unit">dBc</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
<span class="summary-label">LIMD</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-ok" id="sum_limd">--</span>
<span class="summary-unit">dBc</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
<span class="summary-label">RF Switch</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-muted" id="sum_rf">--</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
<span class="summary-label">Output Power</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-ok" id="sum_outpow">--</span>
<span class="summary-unit">dBm</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
<span class="summary-label">Input Source</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-neutral" id="sum_input">--</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
<span class="summary-label">Input Status</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-neutral" id="sum_input_status">--</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
<span class="summary-label">Bitrate</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
<span class="summary-unit">Mbps</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
<span class="summary-label">Temperature</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-ok" id="sum_temp">--</span>
<span class="summary-unit">&#176;F</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
<span class="summary-label">AGC</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-muted" id="sum_agc">--</span>
</div>
</div>
<div class="summary-card">
<div class="summary-label-row">
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
<span class="summary-label">Control</span>
</div>
<div class="summary-value-wrapper">
<span class="summary-value value-neutral" id="sum_control">--</span>
</div>
</div>
</div>
</div>
<main class="app-main">
<h2>TSID&PSIP</h2>
<div class="box">
<form id="tsid_form">
<table>
<tr>
<td>CTRL</td>
<td>
<select name="ts_edit" id="ts_edit">
<option value="0">Disable
<option value="1">Enable
<option value="2">Clear
</select>
</td>
<td>
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return tsid_psip_top_set();">
</td>
</tr>
<tr>
<td>TSID</td>
<td>
<input type="text" maxlength="5" size="8" name="tsid" id="tsid" value="">
</td>
<td>
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return tsid_psip_top_set();">
</td>
</tr>
</table>
</form>
</div>
<br>
<div class="box">
<form name="psip_table_form" id="psip_table_form">
<table id="psip_table">
<tr class="header-row">
<td style="width: 25%">Program</td>
<td style="width: 25%">Short Name</td>
<td style="width: 25%">Major Channel Number</td>
<td style="width: 25%">Minor Channel Number</td>
<td></td>
</tr>
<tr id="psip0">
<td><input type="text" name="index0" readonly></td>
<td><input type="text" name="sht_name0"></td>
<td><input type="text" name="maj_num0"></td>
<td><input type="text" name="min_num0"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(0);"></td>
</tr>
<tr id="psip1">
<td><input type="text" name="index1" readonly></td>
<td><input type="text" name="sht_name1"></td>
<td><input type="text" name="maj_num1"></td>
<td><input type="text" name="min_num1"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(1);"></td>
</tr>
<tr id="psip2">
<td><input type="text" name="index2" readonly></td>
<td><input type="text" name="sht_name2"></td>
<td><input type="text" name="maj_num2"></td>
<td><input type="text" name="min_num2"></td>
<td><input type="button" class="btn-modern" value="Set" disabled disabled onclick="return tsid_psip_sub_set(2);"></td>
</tr>
<tr id="psip3">
<td><input type="text" name="index3" readonly></td>
<td><input type="text" name="sht_name3"></td>
<td><input type="text" name="maj_num3"></td>
<td><input type="text" name="min_num3"></td>
<td><input type="button" class="btn-modern" value="Set" disabled disabled onclick="return tsid_psip_sub_set(3);"></td>
</tr>
<tr id="psip4">
<td><input type="text" name="index4" readonly></td>
<td><input type="text" name="sht_name4"></td>
<td><input type="text" name="maj_num4"></td>
<td><input type="text" name="min_num4"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(4);"></td>
</tr>
<tr id="psip5">
<td><input type="text" name="index5" readonly></td>
<td><input type="text" name="sht_name5"></td>
<td><input type="text" name="maj_num5"></td>
<td><input type="text" name="min_num5"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(5);"></td>
</tr>
<tr id="psip6">
<td><input type="text" name="index6" readonly></td>
<td><input type="text" name="sht_name6"></td>
<td><input type="text" name="maj_num6"></td>
<td><input type="text" name="min_num6"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(6);"></td>
</tr>
<tr id="psip7">
<td><input type="text" name="index7" readonly></td>
<td><input type="text" name="sht_name7"></td>
<td><input type="text" name="maj_num7"></td>
<td><input type="text" name="min_num7"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(7);"></td>
</tr>
<tr id="psip8">
<td><input type="text" name="index8" readonly></td>
<td><input type="text" name="sht_name8"></td>
<td><input type="text" name="maj_num8"></td>
<td><input type="text" name="min_num8"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(8);"></td>
</tr>
<tr id="psip9">
<td><input type="text" name="index9" readonly></td>
<td><input type="text" name="sht_name9"></td>
<td><input type="text" name="maj_num9"></td>
<td><input type="text" name="min_num9"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(9);"></td>
</tr>
<tr id="psip10">
<td><input type="text" name="index10" readonly></td>
<td><input type="text" name="sht_name10"></td>
<td><input type="text" name="maj_num10"></td>
<td><input type="text" name="min_num10"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(10);"></td>
</tr>
<tr id="psip11">
<td><input type="text" name="index11" readonly></td>
<td><input type="text" name="sht_name11"></td>
<td><input type="text" name="maj_num11"></td>
<td><input type="text" name="min_num11"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(11);"></td>
</tr>
<tr id="psip12">
<td><input type="text" name="index12" readonly></td>
<td><input type="text" name="sht_name12"></td>
<td><input type="text" name="maj_num12"></td>
<td><input type="text" name="min_num12"></td>
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(12);"></td>
</tr>
</table>
</form>
</div>
</main>
</div>
<div id="accountModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3>Account Settings</h3>
<span class="close" onclick="closeAccountModal()">&times;</span>
</div>
<div class="modal-body">
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
<table class="modal-table">
<tr>
<td>Current Username</td>
<td><input type="text" id="current_user" name="current_user" readonly></td>
</tr>
<tr>
<td>Current Password</td>
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
</tr>
<tr>
<td>New Username</td>
<td><input type="text" id="new_user" name="new_user"></td>
</tr>
<tr>
<td>New Password</td>
<td><input type="password" id="new_pwd" name="new_pwd"></td>
</tr>
<tr>
<td>Confirm Password</td>
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
</tr>
</table>
<div class="modal-footer">
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
<input type="submit" class="btn-modern" value="Save Changes">
</div>
</form>
</div>
</div>
</div>
<script>
function toggleSidebar(){
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
document.querySelector('.sidebar-overlay').classList.toggle('active');
}
</script>
</body>
</html>