// Copyright 2017, 2018, 2019, 2020 Max H. Parke KA1RBI // Copyright 2020, 2021 Michael Rose // // This file is part of OP25 // // OP25 is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3, or (at your option) // any later version. // // OP25 is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with OP25; see the file COPYING. If not, write to the Free // Software Foundation, Inc., 51 Franklin Street, Boston, MA // 02110-1301, USA. // Last Update: 04-Jun-2021 var delay = 250; const params = new URLSearchParams(window.location.search); // load query string from url window.file = params.get('file'); window.mode = params.get('mode'); window.nac = params.get('nac'); window.sys = params.get('sys'); var css = params.get('css') ? params.get('css') : 'dark'; // file - the tsv filename to work with (only matters for tg, src, sa - hard coded in the python for color) // id - the talkgroup or source ID to jump to upon load // css - [ light | dark ] - the display mode // mode - [ tg | src | color ] what is being worked on window.imp = false; var unsaved = false; var error1 = "ID and Tag fields are required. \n\n Error 1"; var error2 = "Talkgroup and Priority / Color fields must be an integer. \n\n Error 2"; var error3 = "Priority / Color field must be an integer. \n\n Error 3"; var error4 = "ID already exists and must be unique. \n\n Error 4"; var error5 = "Import file not specified. \n\n Error 5"; var error6 = "Editor table not present. \n\n Error 6"; var error7 = 'not supported. Expecting CSV or TSV. \n\n Error 7'; var error8 = 'Failed to load file: '; var error9 = ''; var error10 = 'All fields are required. \n\n Error 10'; var error11 = 'Duplicate rffs/site entries not permitted. \n\n Error 11'; var error12 = 'Invalid system ID. Input out of range. \n\n Error 12'; var error13 = 'Duplicate System ID. \n\nError 13'; $(window).on('load', function() { document.documentElement.setAttribute('data-theme', css); var tgid = params.get('id'); if (tgid) var x = setTimeout(function(){ scrollToAnchor(tgid) }, 300); var oc = "this.blur(); command_reload_tsv(" + nac + ");"; $('#btnReload').attr("onclick", oc); $('#searchInput').val(null); $('#csv-upload').hide(); $('#loading').hide(); $('#csvfile').val(null).on('change',readSingleFile); generateCSS(); beginJsonSettings(); accColorSel(); uiColorRefresh(); switch(mode) { case 'tg': window.modeTitle = "Talkgroup"; $('#btnLoad').text('Load Talkgroups'); document.querySelectorAll('button.saveButton').forEach(elem => { elem.innerHTML = "Save Talkgroups"; }); $('#title').text('Talkgroup TSV Editor - OP25'); break; case 'src': window.modeTitle = "Source"; $('#btnLoad').text('Load Source IDs'); document.querySelectorAll('button.saveButton').forEach(elem => { elem.innerHTML = "Save Source IDs"; }); $('#title').text('Source IDs TSV Editor - OP25'); break; case 'alias': window.modeTitle = "Alias"; $('#btnLoad').text('Load Aliases'); document.querySelectorAll('button.saveButton').forEach(elem => { elem.innerHTML = "Save Aliases"; }); $('#title').text('System Site Alias Editor - OP25'); break; case 'color': window.modeTitle = "Color"; $('#btnLoad').text('Load Colors'); document.querySelectorAll('button.saveButton').forEach(elem => { elem.innerHTML = "Save Colors"; }); $('#title').text('Colors Editor - OP25'); $('#btnColorEditor').hide(); $('.importExport').hide(); // hide these buttons -- import/export function not written yet break; } // end switch }); $(document).ready(function() { // nothing here right now }); window.onbeforeunload = function(){ if (unsaved == true) return 'Are you sure you want to leave? Unsaved changes will be lost.'; }; // delete button $('input[class="delbutton"]').click(function(e){ $(this).closest('tr').remove(); }) function tsv_onload() { switch(mode) { case "alias": beginAlias(); break; case "color": beginColor(); break; default: begin(); } } function begin() { // console.log('begin() started...'); $( "#loading" ).show(); if (begin.caller.name != "completeSave") $('#talkgroups').hide(250); $("#message").text("Fetching TSV..."); file = window.file; $.ajax({ url : file, type : 'GET', success : buildTable, error : function(XMLHttpRequest, textStatus, errorThrown) {alert('File Acces Error: \n\nFile:' + file + '\n\n' + errorThrown + '\n\n');} }); } function beginAlias() { // console.log('beginAlias() started...'); $( "#loading" ).show(); if (beginAlias.caller.name != "completeSave") $('#talkgroups').hide(250); $("#message").text("Fetching Info..."); file = window.file; $.ajax({ url : file, type : 'GET', success : buildAliasTable, error : function(XMLHttpRequest, textStatus, errorThrown) {alert('File Acces Error: \n\nFile:' + file + '\n\n' + errorThrown + '\n\n'); buildAliasTable();} }); } function beginColor() { console.log('beginColor started...'); $('#searchInput').hide(); $("#main").html('Loading...'); $(".saveButton").attr("onclick", "this.blur(); saveColorTable();"); $("#btnLoad").attr("onclick", "this.blur(); beginColor();"); $( "#loading" ).show(); generateCSS(); colorFile = 'color-map.json'; $.ajax({ url : colorFile, type : 'GET', success : buildColorTable, error : function(XMLHttpRequest, textStatus, errorThrown) {alert('File Acces Error: \n\nFile:' + colorFile + '\n\n' + errorThrown + '\n\n');} }); } function buildTable(d) { // console.log('build table started... ~207'); if (!d) { location.reload(); } $("#message").text("Building table..."); var x = ""; lines = []; data = d.split(/\r?\n/); // split by newline for(var i = 0; i < data.length; i++){ lines.push(data[i].split(/['\t']+/)); // split by tab \t } i = 0; // TODO split priority and color into 2 fields? aLen = lines.length; var html = '
'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ' '; html += ' '; html += ' '; html += '
New ' + window.modeTitle + ' IDNew ' + window.modeTitle + ' TagPriority / ColorActions

'; html += 'Editing TSV: ' + file + '        '; html += '         '; html += 'NAC: ' + (nac) + ' - 0x' + (hex(parseInt(nac)).toUpperCase()) + '        '; html += ''; html += '

'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; for (var i = 0; i < aLen - 1; i++) { x = i; var id = lines[i][0]; var tag = lines[i][1]; var col = lines[i][2]; // ? lines[i][2] : 0; var eleid_id = 'ID' + i + id + parseInt(Math.random() * 10000000); // unique IDs for each td, not used for anything right now. var eleid_tag = 'ID' + i + id + parseInt(Math.random() * 10000000); var eleid_col = 'ID' + i + col + parseInt(Math.random() * 10000000); html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; } html += '
Row' + window.modeTitle + ' ID' + window.modeTitle + ' TagPriority / ColorActions
' + (i + 1) + ''; html += '




'; var s = document.getElementById("main"); // todo - use jQ attri() method to assign custom attributes. s.innerHTML = html; s.content = 'editor'; $('#main').data('content', 'editor'); $("#main").html(html); $('#talkgroups').show(150); $('#records').html('Records: ' + (getHigh() + 1) + ' '); $('#message').text('Ready'); if (mode == 'src') $('.pricol').text('Color'); document.querySelectorAll(".tedit").forEach(item => { item.addEventListener('change', event => { isUnsaved(); }); }); // enter key behavior (clicks Add New button) $('#newtg').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); } }); $('#newtag').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); } }); $('#newcol').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); $('#newtg').focus(); } }); $( "#loading" ).hide(); if (window.imp == true) //only flag as unsaved if buildTable was used after import isUnsaved(); } function deleteRow(id, tag) { var r = confirm(id + ' - ' + tag + '\n\nConfirm delete.'); if (r == true) { var td = event.target.parentNode; var tr = td.parentNode; // the row to be removed tr.parentNode.removeChild(tr); isUnsaved(); } } function saveTable() { // console.log('saveTable()'); if (!document.getElementById("talkgroups")) { jAlert(error6, 'Error'); return 0; } $( "#loading" ).show(); window.location.href = "#top"; // $('#talkgroups').hide(250); $('#message').text('Saving...'); disableSave(); // disable save buttons momentarily var tgs, tag, col; data = []; table = document.getElementById("talkgroups"); rows = table.rows.length; var els = document.getElementsByClassName("tg"); // only the ID field is "tg" for(var i = 0; i < els.length; i++) { x = els[i].id; tgs = document.getElementById(x).value; tag = document.getElementById("tag" + (x)).value; col = document.getElementById("col" + (x)).value; if (tgs == "" || tag == "") { jAlert(error1 + '\n\nEmpty fields on Row ' + (i + 1) + '\n\n', 'Error'); enableSave(); return; } if (!Number.isInteger(Number(tgs)) && mode=='tg') { jAlert(error2 + ' \n\n' + tgs + ' looks like a ' + (typeof tgs) + ' on Row ' + (i + 1) + '.', 'Error'); enableSave(); return; } if (!Number.isInteger(Number(col))) { jAlert(error3 + ' \n\n' + col + ' looks like a ' + (typeof col) + ' on Row ' + (i + 1) + '.', 'Error'); enableSave(); return; } data[i] = new Array(tgs, tag, col); } if (mode == "tg") { data.sort(function(a, b) { return a[0] - b[0]; }); } // have to sort Source IDs differently because there could be wildcards/strings in there. if (mode == "src") { data.sort(function( a , b){ if(a[0] > b[0]) return 1; if(a[0] < b[0]) return -1; return 0; }); data.sort(function(a, b){ return a[0].length - b[0].length; }); } //json output - not currently used here var jsonOutput = JSON.stringify(data, undefined, 2); var textOutput = ""; for(var i = 0; i < data.length; i++) { textOutput += (data[i][0] + '\t' + data[i][1] + '\t' + data[i][2] + '\n'); } save_tsv('config-tsvsave', textOutput, window.file); // send data to server setTimeout(completeSave, delay); // artificial delays to allow http_server.py time to process things setTimeout(function(){ command_reload_tsv(nac); }, delay); // tell OP25 to reload the TSVs setTimeout(enableSave, delay); $('#talkgroups').show(delay); $( "#loading" ).hide(); isSaved(); } function addNew() { var id = getHigh() + 1; var table = document.getElementById("talkgroups"); var x; var newtg = $('#newtg').val(); // we're re-using the same AddNew code in Alias editor as well, hence the variable names. var newtag = $('#newtag').val(); var newcol = $('#newcol').val(); var alias = newtg; var r = newtag; var s = newcol; if (mode=="tg" || mode == "src") { if (newtg == "" || newtag == "" ) { // || newcol == "") { jAlert(error1, 'Error'); return; } if (!Number.isInteger(Number(newtg)) && mode=='tg') { jAlert(error2 + ' \n\n' + newtg + ' looks like a ' + (typeof newtg) + '.', 'Error'); return; } if (!Number.isInteger(Number(newcol))) { jAlert(error3 + ' \n\n' + newcol + ' looks like a ' + (typeof newtg) + '.', 'Error'); return; } var els = document.getElementsByClassName("tg"); for(var i = 0; i < els.length; i++) { x = parseInt(els[i].value); if (newtg == x) { jAlert(error4, 'Error'); return; } } } if (mode=="alias") { if (alias == "" || r == "" || s == "") { jAlert(error10, 'Error'); return; } } var row = table.insertRow(1); var cell0 = row.insertCell(0); var cell1 = row.insertCell(1); var cell2 = row.insertCell(2); var cell3 = row.insertCell(3); var cell4 = row.insertCell(4); if (mode == "tg" || mode == "src") { cell0.innerHTML = 'New'; cell1.innerHTML = ''; cell2.innerHTML = ''; cell3.innerHTML = ''; cell4.innerHTML = '  '; cell4.style = "text-align:center"; cell4.innerHTML += ''; } if (mode == "alias") { cell0.innerHTML = 'New'; cell1.innerHTML = ''; cell2.innerHTML = ''; cell3.innerHTML = ''; cell4.innerHTML = ''; cell4.style = "text-align:center"; cell4.innerHTML += ''; } $('#newtg').val(''); $('#newtag').val(''); $('#newcol').val(''); isUnsaved(); } function getHigh() { var x = []; var els = document.getElementsByClassName("tg"); for(var i = 0; i < els.length; i++) { x[i] = (parseInt(els[i].id)); } x = Math.max(...x); // console.log(x); if (x == -Infinity) x = -1; return x; } function scrollToAnchor(a){ var f; var els = document.getElementsByClassName("tg"); for(var i = 0; i < els.length; i++) { if (a == (parseInt(els[i].value))) { var x = document.getElementById(i); x.focus(); x.scrollIntoView({ behavior : 'smooth', block : 'center', inline : 'center' }); return; } } jAlert (modeTitle + ' ' + a + ' not found. There may be wildcard matches. \n\n Creating new. ', 'Add New'); $('#newtg').val(a); $('#newtg').focus(); } function tsv_csv() { // export to CSV file var filetag = 'op25_tsv_' + mode; var csv = ""; var separator = ","; var rows = []; var tgs = $('.tg'); var tag = $('.tag'); var col = $('.col'); for(var i = 0; i < tgs.length; i++) { rows.push ( [ tgs[i].value, tag[i].value, col[i].value ] ); } var filename = 'export_' + filetag + '_' + new Date().toLocaleDateString() + '.csv'; $("#unsaved").show(); exportToCsv(filename, rows); // in main.js } function clearMessage() { $('#message').text(''); } function refresh() { location.reload(); } function up() { window.location.href = '#top'; } function completeSave() { switch(mode) { case "alias": beginAlias(); break; case "color": beginColor(); break; default: // console.log('executing default...'); begin(); } } function disableSave() { $('.saveButton').prop('disabled', true); // document.querySelectorAll('button.saveButton').forEach(elem => { // elem.disabled = true; // }); } function enableSave(){ $('.saveButton').prop('disabled', false); // document.querySelectorAll('button.saveButton').forEach(elem => { // elem.disabled = false; // }); } function help(){ $.ajax({ url : 'tsv-help.html', type : 'GET', success : dispHelp }); } function dispHelp(h) { var s = document.getElementById("main"); // if (s.content == 'help') // return; if ($('#main').data('content') == 'help') return; // window.editorTable = s.innerHTML; // s.innerHTML = h; window.editorTable = $('#main').html(); $('#main').html(h); s.content = 'help'; $('#main').data('content', 'help'); } function closeHelp() { var s = document.getElementById("main"); s.innerHTML = window.editorTable; s.content = 'editor'; $('#main').data('content', 'editor'); } function isNum(x) { if (!x) return; y = Number.isInteger(x); return y; } function command_reload_tsv(nac) { $('#message').text('Sending command...'); reload_tsv(parseInt(nac)); $('#message').text('Command Sent'); } function dispImport() { $('#csv-upload').show(); } function hideImport() { $('#csv-upload').hide(); } function isUnsaved() { unsaved = true; $( "#unsaved" ).show(); } function isSaved() { $( "#unsaved" ).hide(); unsaved = false; } function readSingleFile(evt) { if (!evt.target.files) { alert(error5); return; } var f = evt.target.files[0]; if (f) { isUnsaved(); var ftype = (evt.target.value).substr((evt.target.value).length - 3).toUpperCase(); switch (ftype) { case 'CSV': var sep = ","; break; case 'TSV': var sep = "\t"; break; default: jAlert('File type ' + ftype + ' ' + error7, 'Error'); return; } var r = new FileReader(); if (!r) return; r.onload = function(e) { var contents = e.target.result; // document.write("File Uploaded!
" + "name: " + f.name + "
" + "content: " + 'contents hidden' + "
" + "type: " + f.type + "
" + "size: " + f.size + " bytes
"); var lines = contents.split("\n"), output = []; for (var i=0; i 0) output.push(lines[i].split(sep).join("\t") + "\n"); } output = "" + output.join("") + ""; isUnsaved(); window.imp = true; buildTable(output); } r.readAsText(f); isUnsaved(); } else { jAlert(error8 + evt.target.value, 'Error'); } } function buildAliasTable(d) { // geting JSON with this one if (!d) { location.reload(); } var lines = []; var i = 0; var sysid = window.sys; var alias; var systems = []; window.aliasData = d; for (r in d) { systems.push(r); } for (r in d[sysid]) { for (s in d[sys][r]) { alias = d[sys][r][s]['alias']; // console.log (sysid + ' / ' + hex(parseInt(sysid)).toUpperCase() + ' - ' + alias + ' - R=' + r + ' - S=' + s); lines.push([alias, r, s]); } } $("#message").text("Building table..."); aLen = lines.length; var html = '
'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ' '; html += ' '; html += ' '; html += '
New ' + window.modeTitle + 'RFSS ID (dec)Site ID (dec)Actions

'; html += 'Editing: ' + file + '     '; html += '     '; html += 'System: ' + (sysid) + ' - 0x' + (hex(parseInt(sysid)).toUpperCase()) + '    '; html += 'Change: '; html += ''; html += ''; html += '

'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; if (aLen == 0) { jAlert('No Site Aliases found for System ' + sysid + '. Try creating some.', 'Create New'); } for (var i = 0; i < aLen; i++) { x = i; var alias = lines[i][0]; var rfss = lines[i][1]; var site = lines[i][2]; var eleid_alias = 'ID' + i + site + parseInt(Math.random() * 10000000); // unique IDs for each td, not used for anything right now. var eleid_rfss = 'ID' + i + site + parseInt(Math.random() * 10000000); var eleid_site = 'ID' + i + site + parseInt(Math.random() * 10000000); html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; } html += '
Row' + window.modeTitle + 'RFSS ID
(dec)
Site ID
(dec)
Actions
' + (i + 1) + ''; html += '




'; var s = document.getElementById("main"); // todo - use jQ attri() method to assign custom attributes. s.innerHTML = html; s.content = 'editor'; $('#main').data('content', 'editor'); $("#main").html(html); $('#talkgroups').show(150); $('#records').html('Records: ' + (getHigh() + 1) + ' '); $('#message').text('Ready'); if (mode == 'src') $('.pricol').text('Color'); document.querySelectorAll(".tedit").forEach(item => { item.addEventListener('change', event => { isUnsaved(); }); }); $( "#loading" ).hide(); if (window.imp == true) //only flag as unsaved if buildTable was used after import isUnsaved(); // enter key behavior (clicks Add New button) $('#newtg').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); } }); $('#newtag').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); } }); $('#newcol').on('keypress', function(e) { if(e.which == 13) { $('#btnAddNew').trigger('click'); $('#newtg').focus(); } }); populateChange(systems); } function populateChange(sys) { var s, h; $('#selSystem').append(''); for (i in sys) { s = sys[i]; h = hex(parseInt(s)); $('#selSystem').append(''); } $('#selSystem').append(''); $('#selSystem').on('change', function() { changeSys(sys); }); } function changeSys(sys) { if (sys == 0) return; var sel = $('#selSystem').val(); var sysd = 0; if (sel == 'new') { var p = prompt('Enter new System ID in hex.\n\n'); if (!p) { // Cancel btn $('#selSystem').val(0); return; } if (!(p.match("^[0-9a-fA-F]+$") !== null)) { // valid hex? jAlert(error12, 'Invalid Entry'); $('#selSystem').val(0); return; } sysd = dec(p); if (sysd < 1 || sysd > 4095) { jAlert(error12, 'Invalid Entry'); $('#selSystem').val(0); return; } if (sys.includes( sysd.toString())) { jAlert(error13, 'Invalid Entry'); $('#selSystem').val(0); return; } $('#selSystem').val(0); sel = sysd; } // end if new var url = 'alias-edit.html?file=site-alias.json&mode=alias&sys=' + sel; window.sys = sel; beginAlias(); } function deleteSys() { system = window.sys; if (Object.keys(aliasData).length == 1) { // console.log('cannot delete last system'); return; } var r = confirm("Confirm: Delete site aliases for System " + system + ' - 0x' + hex(parseInt(sys)).toUpperCase() + '\n\nWARNING: This action cannot be reversed.\n\n'); if (r == true) { delete window.aliasData[system.toString()]; $('#selSystem option[value="' + system + '"]').remove(); var jsonOutput = JSON.stringify(aliasData, undefined, 2); $( "#loading" ).show(); save_tsv('config-tsvsave', jsonOutput, window.file); // send data to server $('#selSystem :nth-child(1)').prop('selected', true); // select first option (below Select...) var newSys = $('#selSystem option').eq(1).val(); window.sys = newSys; $('#loading').hide(); beginAlias(); } else { // cancel return; } } function saveAliasTable() { if (!document.getElementById("talkgroups")) { jAlert(error6, 'Error'); return 0; } d = window.aliasData; var sysid = window.sys; $( "#loading" ).show(); window.location.href = "#top"; // $('#talkgroups').hide(250); $('#message').text('Saving...'); disableSave(); // disable save buttons momentarily var tgs, tag, col; data = []; out = []; rs = []; table = document.getElementById("talkgroups"); rows = table.rows.length; // check for dupe rfss/site combos var els = document.getElementsByClassName("tg"); for(var y = 0; y < els.length; y++) { rfss = document.getElementById("rfss" + (y)).value; site = document.getElementById("site" + (y)).value; rs.push([rfss, site]); } var arr = rs.map(JSON.stringify); rl = arr.length; var sar = new Set(arr); sl = sar.size; if (rl != sl ) { jAlert(error11, 'Error'); $('#message').text('Ready'); $( "#loading" ).hide(); enableSave(); return; } for(var i = 0; i < els.length; i++) { x = els[i].id; alias = document.getElementById(x).value; rfss = document.getElementById("rfss" + (x)).value; site = document.getElementById("site" + (x)).value; if (alias == "" || rfss == "" || site == "") { jAlert(error10 + '\n\nEmpty fields on Row ' + (i + 1) + '\n\n', 'Error'); enableSave(); return; } data[i] = new Array(alias, rfss, site); } data.sort(function(a, b) { return a[2] - b[2]; }); // these get added to site-alias.json when no data is present initially - just delete them. delete d['readyState']; delete d['responseText']; delete d['status']; delete d['statusText']; delete d[sys]; for(var i = 0; i < data.length; i++) { alias = data[i][0]; r = data[i][1]; s = data[i][2]; d[sys] = d[sys] || {}; d[sys][r] = d[sys][r] || {}; d[sys][r][s] = d[sys][r][s] || {}; d[sys][r][s]['alias'] = alias; } //json output var jsonOutput = JSON.stringify(d, undefined, 2); save_tsv('config-tsvsave', jsonOutput, window.file); // send data to server setTimeout(completeSave, delay); // artificial delays to allow http_server.py time to process things setTimeout(enableSave, delay); $('#talkgroups').show(delay); $('#loading').hide(); localStorage.AliasTableUpdated == true; isSaved(); } function buildColorTable(d) { // console.log('build color table started...'); var html = ''; html += '

'; html += '
'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; for (i in d) { if (!d[i]) continue; if (d[i][0] > 99) continue; var x = i; var color = d[i][1]; var backg = d[i][2]; var blink = d[i][3]; var blinkOpt = (d[i][3] == true) ? "Yes" : "No"; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; } html += '
ColorFont ColorBackgroundBlinkSample Text
' + (parseInt(x)) + ''; html += ''; html += ''; html +='Sample Text 12345 '; html += '




'; generateCSS(); var s = document.getElementById("main"); // todo - use jQ attri() method to assign custom attributes. s.innerHTML = html; s.content = 'editor'; $('#main').data('content', 'editor'); $("#main").html(html); $('#talkgroups').show(150); for (i in d) { if (!d[i]) continue; if (d[i][0] > 99) continue; $('#' + (i) + 'blink').prop('checked', d[i][3]); } // color picker: Spectrum - https://github.com/bgrins/spectrum // Copyright (c) Brian Grinstead // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions... // ** see complete license in source css & js $(".coloredit").spectrum({ preferredFormat: "hex", localStorageKey: "spectrum.homepage", chooseText: "Select", clickoutFiresChange: false, containerClassName: 'colorPicker', replacerClassName: 'colorReplacer', showInput: true, showPalette: true, showInitial: true, allowEmpty: false, palette: [ ["#000","#444","#666","#999","#ccc","#eee","#f3f3f3","#fff"], ["#f00","#f90","#ff0","#0f0","#0ff","#00f","#90f","#f0f"], ["#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#cfe2f3","#d9d2e9","#ead1dc"], ["#ea9999","#f9cb9c","#ffe599","#b6d7a8","#a2c4c9","#9fc5e8","#b4a7d6","#d5a6bd"], ["#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6fa8dc","#8e7cc3","#c27ba0"], ["#c00","#e69138","#f1c232","#6aa84f","#45818e","#3d85c6","#674ea7","#a64d79"], ["#900","#b45f06","#bf9000","#38761d","#134f5c","#0b5394","#351c75","#741b47"], ["#600","#783f04","#7f6000","#274e13","#0c343d","#073763","#20124d","#4c1130"] ] }); $(".bgedit").spectrum({ preferredFormat: "hex", localStorageKey: "spectrum.homepage", clickoutFiresChange: false, containerClassName: 'colorPicker', replacerClassName: 'colorReplacer', chooseText: "Select", showInput: true, showPalette: true, showInitial: true, allowEmpty: true, palette: [ ["#000","#444","#666","#999","#ccc","#eee","#f3f3f3","#fff"], ["#f00","#f90","#ff0","#0f0","#0ff","#00f","#90f","#f0f"], ["#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#cfe2f3","#d9d2e9","#ead1dc"], ["#ea9999","#f9cb9c","#ffe599","#b6d7a8","#a2c4c9","#9fc5e8","#b4a7d6","#d5a6bd"], ["#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6fa8dc","#8e7cc3","#c27ba0"], ["#c00","#e69138","#f1c232","#6aa84f","#45818e","#3d85c6","#674ea7","#a64d79"], ["#900","#b45f06","#bf9000","#38761d","#134f5c","#0b5394","#351c75","#741b47"], ["#600","#783f04","#7f6000","#274e13","#0c343d","#073763","#20124d","#4c1130"] ] }); $('.coloredit').on('change', function(){ var v = this.value ? this.value : "initial"; var target = '#s' + (this.title); $(target).css('color', v); isUnsaved(); }); $('.bgedit').on('change', function(){ var v = this.value ? this.value : "initial"; var target = '#s' + (this.title); $(target).css('background-color', v); isUnsaved(); }); $('.blinkedit').on('change', function(){ var target = '#s' + (this.title); var z = this.checked == true ? "blinker 1s linear infinite" : "none"; $(target).css('animation', z); isUnsaved(); }); $('#loading').hide(); $('#message').text('Ready'); } function saveColorTable() { $( "#loading" ).show(); window.location.href = "#top"; $('#message').text('Saving...'); var i = null; var c = null; var b = null; var blink = null; var css = []; css[0] = new Array (500,"placeholder","do-not-use",false); // hack shack :( avoids a NULL at [0] in the resulting json for (i = 1; i < 100; i++){ c = $('#' + (i) + 'color').val(); b = $('#' + (i) + 'backg').val(); blink = $('#' + (i) + 'blink').is(':checked') ? true : false; css[i] = new Array(i, c, b, blink); } var jsonOutput = JSON.stringify(css, undefined, 2); save_tsv('config-tsvsave', jsonOutput, 'color-map.json'); $('#message').text('Colors saved. Ready.'); setTimeout(function() { $( "#loading" ).hide(); }, 250); // a little delay for the UI's benefit. localStorage.ColorsTableUpdated == true; isSaved(); } function generateCSS() { // console.log('generateCSS started...'); if (localStorage.ColorsTableUpdated == false) return; colorFile = 'color-map.json'; $.ajax({ url : colorFile, type : 'GET', success : applyCSS, // error : function(XMLHttpRequest, textStatus, errorThrown) { alert('File Acces Error: \n\nFile:' + colorFile + '\n\n' + errorThrown + '\n\n'); } }); } function applyCSS(d) { var sheet = (function() { var sheets = document.styleSheets, stylesheet = sheets[(sheets.length - 1)]; for(var i in document.styleSheets ){ if( sheets[i].title == 'tgcolors') { for (var y=0; y element to the page document.head.appendChild(style); localStorage.ColorsTableUpdated == false; return style.sheet; })(); for (i in d) { if (d[i]) { w = ' .c' + d[i][0] + ' { '; x = 'color: ' + d[i][1] + '; '; y = 'background-color: ' + d[i][2] + '; '; z = 'animation: ' + (d[i][3] == true ? "blinker 1s linear infinite;" : "none;") + '} \n'; sheet.insertRule( (w + x + y + z) ); } } setTimeout(enableSave, delay); $('#talkgroups').show(delay); $( "#loading" ).hide(); } function reloadCss() { // not used right now var links = document.getElementsByTagName("link"); for (var cl in links) { var link = links[cl]; if (link.rel === "stylesheet") link.href += ""; } }