Skip to main content

SOURCE CODE
QUERY SCOPING EXAMPLE-PROGRAM
Maximum Data for Example-Program is 3 Items

SOURCE CODE:

 <!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>JSON Dashboard - Light Theme</title>

<style>

body {

  font-family: Arial, sans-serif;

  padding: 20px;

  background: #f9fafb;

  color: #333;

}


/* ---------- Boxes / Sections ---------- */

.box {

  border-radius: 8px;

  background: #ffffff;

  box-shadow: 0 2px 6px rgba(0,0,0,0.1);

  padding: 20px;

  margin-bottom: 25px;

}

.box h3 {

  margin-top: 0;

  font-size: 18px;

  background: #e3f2fd;

  color: #0d47a1;

  padding: 8px 12px;

  border-radius: 6px;

}


/* ---------- Forms ---------- */

form input, form select, form button {

  margin: 5px;

  padding: 6px 10px;

  border-radius: 4px;

  border: 1px solid #ccc;

}

form button {

  background: #1976d2;

  color: #fff;

  border: none;

  cursor: pointer;

}

form button:hover { background: #1565c0; }

select[multiple] {

  height:100px;

  width:200px;

  border: 1px solid #ccc;

}


/* ---------- Scrollable Table Container ---------- */

.table-container {

  overflow-x:auto;

  overflow-y:auto;

  width:100%;

  height:300px;

  margin-top:10px;

  border-radius: 6px;

  border: 1px solid #ddd;

}


/* ---------- Table Styling ---------- */

table {

  border-collapse: collapse;

  white-space: nowrap;

  min-width: 100%;

}

table th, table td {

  border: 1px solid #ddd;

  padding: 8px 12px;

  text-align: left;

}

th {

  cursor:pointer;

  background-color:#e8f0fe;

  position: sticky;

  top: 0;

  z-index: 2;

}

tr:nth-child(even) { background: #f6f8fa; }


/* ---------- Flash highlight ---------- */

tr.new { background-color: #d0f0c0; animation: blinkNew 2s ease; }

tr.edited { background-color: #fff4b3; animation: blinkEdit 2s ease; }

@keyframes blinkNew {0%,100%{background:#d0f0c0;}50%{background:#fff;}}

@keyframes blinkEdit {0%,100%{background:#fff4b3;}50%{background:#fff;}}


/* ---------- Output / Input buttons ---------- */

button#exportJSON, button#exportCSV {

  background: #4caf50;

  color: #fff;

  border: none;

  padding: 6px 12px;

  border-radius: 4px;

  margin-right: 8px;

  cursor: pointer;

}

button#exportJSON:hover, button#exportCSV:hover { background: #388e3c; }

</style>

</head>

<body>


<!-- ==================== 1) CRUD SECTION ==================== -->

<div class="box">

<h3>ADD / EDIT / DELETE</h3>

<form id="addForm">

<input type="hidden" name="edit_id" value="">

<input type="text" name="name" placeholder="Item Name" required>

<input type="text" name="value" placeholder="Value" required>

<input type="text" name="user_id" placeholder="User ID" required>

<select name="status">

<option value="active">Active</option>

<option value="inactive">Inactive</option>

</select>

<button type="submit">Add Item</button>

<button type="button" id="cancelEdit" style="display:none;">Cancel Edit</button>

</form>

</div>


<!-- ==================== 2) INPUT - DATA (ALL) - OUTPUT ==================== -->

<div class="box">

<h3>ALL DATA<hr>BATCH INPUT and BATCH OUTPUT</h3>

<div>

<h4>INPUT</h4>

<input type="file" id="importFile" accept=".json">

</div>

<div>

<h4>DATA (ALL)</h4>

<div class="table-container">

  <table id="resultsTable">

    <thead>

      <tr>

        <th data-column="id">ID</th>

        <th data-column="name">Name</th>

        <th data-column="value">Value</th>

        <th data-column="user_id">User ID</th>

        <th data-column="status">Status</th>

        <th data-column="created_at">Created At</th>

        <th>Actions</th>

      </tr>

    </thead>

    <tbody id="resultsBody"></tbody>

  </table>

</div>

<div style="margin-top:10px;">

<h4>OUTPUT</h4>

<button id="exportJSON">Export JSON</button>

<button id="exportCSV">Export CSV</button>

</div>

</div>


<br>

<hr>

<!-- ==================== 3) Filter Inputs - Data Result ==================== -->

<div class="box">

<h3>AUTO-REFRESH<br>QUERY SCOPING</h3>

<div class="filter-group">

<h4>Filter Options</h4>

<select id="filterName" multiple></select>

<select id="filterUser" multiple></select>

<select id="filterStatus" multiple></select>

<select id="filterValue" multiple></select>

</div>

<div id="filteredCounter" style="margin-bottom:5px; font-weight:bold;">Filtered Rows: 0 / 0</div>

<div class="table-container">

  <table class="output-table">

    <thead>

      <tr>

        <th>ID</th>

        <th>Name</th>

        <th>Value</th>

        <th>User ID</th>

        <th>Status</th>

        <th>Created At</th>

      </tr>

    </thead>

    <tbody id="filteredBody"></tbody>

  </table>


</div>

<hr>

</div>


<script>

// ---------- Sample Database ----------

let database=[

{id:1,user_id:"123",name:"Item A",value:100,status:"active",created_at:"2026-03-24 10:00:00"},

{id:2,user_id:"123",name:"Item B",value:200,status:"active",created_at:"2026-03-24 10:05:00"},

{id:3,user_id:"456",name:"Item C",value:150,status:"inactive",created_at:"2026-03-24 09:50:00"}

];

let previousIds=new Set(), editedIds=new Set(), sortConfig={column:"id",asc:true};


// ---------- Display Main Table ----------

function displayMainTable(scroll=true){

    let data=database.slice();

    data.sort((a,b)=>sortConfig.asc?(a[sortConfig.column]<b[sortConfig.column]?-1:1):(a[sortConfig.column]<b[sortConfig.column]?1:-1));

    let tbody='';

    data.forEach(r=>{

        const isNew=!previousIds.has(r.id), isEdited=editedIds.has(r.id);

        if(isNew) previousIds.add(r.id);

        tbody+=`<tr class="${isNew?'new':isEdited?'edited':''}">

        <td>${r.id}</td><td>${r.name}</td><td>${r.value}</td><td>${r.user_id}</td>

        <td>${r.status}</td><td>${r.created_at}</td>

        <td><button onclick="editItem(${r.id})">Edit</button>

        <button onclick="deleteItem(${r.id})">Delete</button></td></tr>`;

    });

    document.getElementById('resultsBody').innerHTML=tbody;

    if(scroll) document.getElementById('resultsBody').parentElement.scrollTop=document.getElementById('resultsBody').parentElement.scrollHeight;

    setTimeout(()=>{ editedIds.clear(); },2000);

}


// ---------- Populate Filters ----------

function populateFilters(){

    const uniqueValues = (key) => [...new Set(database.map(r=>r[key]))].sort();

    const fName=document.getElementById('filterName'); fName.innerHTML=''; uniqueValues('name').forEach(v=>{fName.innerHTML+=`<option value="${v}">${v}</option>`});

    const fUser=document.getElementById('filterUser'); fUser.innerHTML=''; uniqueValues('user_id').forEach(v=>{fUser.innerHTML+=`<option value="${v}">${v}</option>`});

    const fStatus=document.getElementById('filterStatus'); fStatus.innerHTML=''; uniqueValues('status').forEach(v=>{fStatus.innerHTML+=`<option value="${v}">${v}</option>`});

    const fValue=document.getElementById('filterValue'); fValue.innerHTML=''; uniqueValues('value').forEach(v=>{fValue.innerHTML+=`<option value="${v}">${v}</option>`});

}


// ---------- Get Selected Values ----------

function getSelectedValues(selectEl){return [...selectEl.selectedOptions].map(o=>o.value);}


// ---------- Filtered Output ----------

function displayFilteredOutput(){

    const selectedNames=getSelectedValues(document.getElementById('filterName'));

    const selectedUsers=getSelectedValues(document.getElementById('filterUser'));

    const selectedStatus=getSelectedValues(document.getElementById('filterStatus'));

    const selectedValues=getSelectedValues(document.getElementById('filterValue'));

    

    let filtered=database.filter(r=>{

        return (selectedNames.length===0||selectedNames.includes(r.name)) &&

               (selectedUsers.length===0||selectedUsers.includes(r.user_id)) &&

               (selectedStatus.length===0||selectedStatus.includes(r.status)) &&

               (selectedValues.length===0||selectedValues.includes(r.value.toString()));

    });

    

    document.getElementById('filteredCounter').textContent=`Filtered Rows: ${filtered.length} / ${database.length}`;

    

    const tbody=document.getElementById('filteredBody');

    tbody.innerHTML=filtered.map(r=>`<tr>

        <td>${r.id}</td><td>${r.name}</td><td>${r.value}</td><td>${r.user_id}</td>

        <td>${r.status}</td><td>${r.created_at}</td>

    </tr>`).join('');

}


// ---------- Add/Edit ----------

const addForm=document.getElementById('addForm'), cancelEditBtn=document.getElementById('cancelEdit');

addForm.addEventListener('submit',function(e){

    e.preventDefault(); const f=e.target; const editId=f.edit_id.value;

    const newItem={id:editId?parseInt(editId):database.length+1,user_id:f.user_id.value,name:f.name.value,value:parseFloat(f.value.value),status:f.status.value,created_at:new Date().toISOString().slice(0,19).replace("T"," ")};

    if(editId){ const idx=database.findIndex(r=>r.id===parseInt(editId)); database[idx]=newItem; editedIds.add(newItem.id);}

    else database.push(newItem);

    f.reset(); f.edit_id=''; cancelEditBtn.style.display='none';

    populateFilters(); displayMainTable(); displayFilteredOutput();

});

cancelEditBtn.addEventListener('click',()=>{addForm.reset(); addForm.edit_id=''; cancelEditBtn.style.display='none';});


// ---------- Edit/Delete ----------

function editItem(id){const r=database.find(r=>r.id===id); addForm.edit_id.value=r.id; addForm.name.value=r.name; addForm.value.value=r.value; addForm.user_id.value=r.user_id; addForm.status.value=r.status; cancelEditBtn.style.display='inline';}

function deleteItem(id){if(confirm("Delete this item?")){database=database.filter(r=>r.id!==id); previousIds.delete(id); editedIds.delete(id); populateFilters(); displayMainTable(); displayFilteredOutput();}}


// ---------- Sorting ----------

document.querySelectorAll('th[data-column]').forEach(th=>{th.addEventListener('click',()=>{

    const col=th.dataset.column;

    sortConfig.column===col?sortConfig.asc=!sortConfig.asc:sortConfig={column:col,asc:true};

    displayMainTable();

});});


// ---------- Filters Event ----------

['filterName','filterUser','filterStatus','filterValue'].forEach(id=>{

    document.getElementById(id).addEventListener('change', displayFilteredOutput);

});


// ---------- Export JSON & CSV ----------

document.getElementById('exportJSON').addEventListener('click',()=>{

    const dataStr="data:text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(database,null,2));

    const dl=document.createElement('a'); dl.href=dataStr; dl.download='database.json'; dl.click();

});

document.getElementById('exportCSV').addEventListener('click',()=>{

    const rows=database.map(r=>[r.id,r.name,r.value,r.user_id,r.status,r.created_at]);

    const csvContent="data:text/csv;charset=utf-8,"+["ID,Name,Value,UserID,Status,CreatedAt",...rows.map(r=>r.join(","))].join("\n");

    const dl=document.createElement('a'); dl.href=csvContent; dl.download='database.csv'; dl.click();

});


// ---------- Safe Merge-Import ----------

document.getElementById('importFile').addEventListener('change',function(e){

    const f=e.target.files[0]; if(!f) return;

    const reader=new FileReader();

    reader.onload=function(evt){

        try{

            const imp=JSON.parse(evt.target.result); if(!Array.isArray(imp)){alert("Invalid JSON"); return;}

            let maxId=Math.max(...database.map(r=>r.id),0);

            imp.forEach(item=>{if(!item.id)item.id=++maxId; else if(database.some(r=>r.id===item.id)) item.id=++maxId; database.push(item); editedIds.add(item.id);});

            populateFilters(); displayMainTable(); displayFilteredOutput(); alert("Data imported safely!");

        }catch(err){alert("Error parsing JSON");}

    }; reader.readAsText(f);

});


// ---------- Auto-refresh ----------

setInterval(()=>{displayMainTable(false); displayFilteredOutput();},5000);


// ---------- Initial Display ----------

populateFilters(); displayMainTable(); displayFilteredOutput();

</script>

</body>

</html>

Comments