// jshint esversion:6 // Hashes for the two selected commits var commit1; var commit2; // Commits objects list var commits_form; // How may commits var num_commits; var old_view; var current_view = "show_sch"; current_diff_filter = "diff" // diff or normal var panZoom_instance = null; var lastEventListener = null; var lastEmbed = null; sch_current_zoom = null; sch_old_zoom = null; sch_current_pan = null; pcb_current_zoom = null; pcb_old_zoom = null; pcb_current_pan = null; // Variables updated by Kiri var selected_view = "schematic"; var is_fullscreen = false; // Schematic sheets for the commit1 var sheet_pages_commit1 = new Set(); // Schematic sheets for the commit1 var sheet_pages_commit2 = new Set(); // Displayed schematic sheets var current_sheets_list = []; // PCB layers for commit1 var layers_commit1 = new Set(); // PCB layers for commit2 var layers_commit2 = new Set(); // Displayed PCB layers var current_layers_list = []; // Icon to indicate the schematic was changed in a commit const SCH_IMG = ''; // Icon to indicate the PCB was changed in a commit const PCB_IMG = ''; // Icon to indicate no change in a commit const EMPTY_IMG = ''; // Color for the commit1 var commit1_legend_color; // Color for the commit2 var commit2_legend_color; // Color when only one commit is displayed var commit_standalone_color; // Image 1 element var diff_xlink_1; // Image 2 element var diff_xlink_2; // List of pages (objects) var pages; // Which one is selected var selected_page = -1; // List of layers (objects) var layers; // Which one is selected var selected_layer = -1; // ======================================= // HANDLE SHORTCUTS // ======================================= // Move 2nd commit downwards function select_next_2_commits() { var commit2_order = order_of(commit2); if (commit2_order == num_commits) { console.log('Already at the bottom'); return; } // Move the lower 1 place down commit2.checked = false; commit2 = commits_form[commit2_order]; commit2.checked = true; update_commits(); } function order_of(commit) { return parseInt(commit.getAttribute('order')); } // Move commits par downwards function select_next_commit() { var commit1_order = order_of(commit1); var commit2_order = order_of(commit2); var changed = false; if (commit2_order < num_commits) { // Move the lower 1 place down commit2.checked = false; commit2 = commits_form[commit2_order]; commit2.checked = true; changed = true; commit2_order = commit2_order + 1; } if ((commit1_order + 1) < commit2_order) { // Move the upper 1 place down commit1.checked = false; commit1 = commits_form[commit1_order]; commit1.checked = true; changed = true; } if (! changed) { console.log('Already at the bottom'); return; } update_commits(); } // Move 2nd commit upwards function select_previous_2_commits() { var commit1_order = order_of(commit1); var commit2_order = order_of(commit2); if ((commit2_order - 1) <= commit1_order) { console.log('Already next to the first'); return; } // Move the lower 1 place up commit2.checked = false; commit2 = commits_form[commit2_order - 2]; commit2.checked = true; update_commits(); } // Move commits par upwards function select_previous_commit() { var commit1_order = order_of(commit1); var commit2_order = order_of(commit2); var changed = false; if (commit1_order > 1) { // Move the upper 1 place up commit1.checked = false; commit1 = commits_form[commit1_order - 2]; commit1.checked = true; changed = true; commit1_order = commit1_order - 1; } if ((commit2_order - 1) > commit1_order) { // Move the lower 1 place up commit2.checked = false; commit2 = commits_form[commit2_order - 2]; commit2.checked = true; changed = true; } if (! changed) { console.log('Already at the top'); return; } update_commits(); } function update_commit_legend_visibility(id, status) { // Make all elements of the commitN class visible/hidden for (const e of document.getElementsByClassName("commit"+id)) { e.style.visibility = status; } } function update_commit_legend_color(id, color) { // Adjust the color for all the elements of the commitN class if (! color) { color = (id == 1 ? commit1_legend_color : commit2_legend_color); } for (const e of document.getElementsByClassName("icon-commit"+id+"-color")) { e.style.color = color; } } function set_image_filters(img1=true, img2=true) { if (img1 && img2) { diff_xlink_1.style.filter = 'url(#filter-1)'; /// FILTER_DEFAULT diff_xlink_2.style.filter = 'url(#filter-2)'; /// FILTER_DEFAULT } else if (img1) { diff_xlink_1.style.filter = 'url(#filter-12)'; /// FILTER_WHITE } else if (img2) { diff_xlink_2.style.filter = 'url(#filter-22)'; /// FILTER_WHITE } } function reset_commits_selection() { commit1.checked = false; commit2.checked = false; commit1 = commits_form[0]; commit2 = commits_form[1]; commit1.checked = true; commit2.checked = true; // reset visibility of the diff images update_commit_legend_visibility(1, 'visible'); update_commit_legend_color(1); update_commit_legend_visibility(2, 'visible'); update_commit_legend_color(2); update_commit_legend_visibility(3, 'visible'); set_image_filters(); update_commits(); } function toggle_sch_pcb_view() { old_view = current_view; if (current_view == "show_sch") { show_pcb(); } else { show_sch(); } update_commits(); } function toggle_old_commit_visibility() { if (diff_xlink_1.style.visibility === "hidden") { current_diff_filter = "diff"; set_image_filters(); update_commit_legend_visibility(1, 'visible'); update_commit_legend_visibility(3, 'visible'); update_commit_legend_color(1); update_commit_legend_color(2); } else { current_diff_filter = "single"; set_image_filters(false, true); update_commit_legend_visibility(1, 'hidden'); update_commit_legend_visibility(2, 'visible'); update_commit_legend_visibility(3, 'hidden'); update_commit_legend_color(2, commit_standalone_color); } } function toggle_new_commit_visibility() { if (diff_xlink_2.style.visibility === "hidden") { current_diff_filter = "diff"; set_image_filters(); update_commit_legend_visibility(2, 'visible'); update_commit_legend_visibility(3, 'visible'); update_commit_legend_color(1); update_commit_legend_color(2); } else { current_diff_filter = "single"; set_image_filters(true, false); update_commit_legend_visibility(1, 'visible'); update_commit_legend_visibility(2, 'hidden'); update_commit_legend_visibility(3, 'hidden'); update_commit_legend_color(1, commit_standalone_color); } } function select_next_sch_or_pcb(cycle = false) { if (current_view == "show_sch") { selected_page = selected_page + 1; if (selected_page >= pages.length) { selected_page = (cycle ? 0 : pages.length - 1); } pages[selected_page].checked = true; update_selected_page(); } else { selected_layer = selected_layer + 1; if (selected_layer >= layers.length) { selected_layer = (cycle ? 0 : layers.length - 1); } layers[selected_layer].checked = true; update_selected_layer(); } } function select_preview_sch_or_pcb(cycle = false) { if (current_view == "show_sch") { selected_page = selected_page - 1; if (selected_page < 0) { selected_page = (cycle ? pages.length - 1 : 0); } pages[selected_page].checked = true; update_selected_page(); } else { selected_layer = selected_layer - 1; if (selected_layer < 0) { selected_layer = (cycle ? layers.length - 1 : 0); } layers[selected_layer].checked = true; update_selected_layer(); } } function svg_fit_center() { panZoom_instance.resetZoom(); panZoom_instance.center(); } function svg_zoom_in() { panZoom_instance.zoomIn(); } function svg_zoom_out() { panZoom_instance.zoomOut(); } function manual_pan(direction) { const step = 50; switch(direction) { case "Up": panZoom_instance.panBy({x: 0, y: step}); break; case "Down": panZoom_instance.panBy({x: 0, y: -step}); break; case "Left": panZoom_instance.panBy({x: step, y: 0}); break; case "Right": panZoom_instance.panBy({x: -step, y: 0}); break; } } document.onkeydown = function (e) { /*console.log('e.key', e.key); console.log('e.altKey', e.altKey); console.log('e.code', e.code);*/ if (e.altKey && ! (e.ctrlKey || e.metaKey)) { // ALT + xxx switch (e.code) { case "KeyR": reset_commits_selection(); break; case "KeyQ": toggle_new_commit_visibility(); break; case "KeyW": toggle_old_commit_visibility(); break; // SVG PAN case "ArrowUp": case "ArrowDown": case "ArrowLeft": case "ArrowRight": manual_pan(e.key.substring(5)); break; } } else if ((e.ctrlKey || e.metaKey) && ! e.altKey) { // CTRL/Command + xxxx switch (e.code) { case "ArrowUp": case "BracketLeft": select_previous_2_commits(); break; case "ArrowDown": case "BracketRight": select_next_2_commits(); break; case "ArrowLeft": select_preview_sch_or_pcb(true); break; case "ArrowRight": select_next_sch_or_pcb(true); break; } } else if (! (e.ctrlKey || e.metaKey || e.altKey)) { // Key alone switch (e.code) { case "ArrowUp": case "BracketLeft": select_previous_commit(); break; case "ArrowDown": case "BracketRight": select_next_commit(); break; // View case "KeyS": toggle_sch_pcb_view(); break; case "ArrowLeft": select_preview_sch_or_pcb(); break; case "ArrowRight": select_next_sch_or_pcb(); break; // SVG ZOOM case "Digit0": svg_fit_center(); break; // Misc case "KeyF": toggle_fullscreen(); break; case "KeyI": document.getElementById("info-btn").click(); break; default: switch (e.key) { case "+": svg_zoom_in(); break; case "-": svg_zoom_out(); break; } } } } // ======================================= // ======================================= // For images related with each commit, it is good to have the same image cached with the same specially when serving throug the internet // For those images, it uses the commit hash as the timestamp function url_timestamp(timestamp_id="") { if (timestamp_id) { return "?t=" + timestamp_id; } else { return "?t=" + new Date().getTime(); } } function if_url_exists(url, callback) { let request = new XMLHttpRequest(); request.open('GET', url, true); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); request.setRequestHeader('Accept', '*/*'); request.onprogress = function(event) { let status = event.target.status; let statusFirstNumber = (status).toString()[0]; switch (statusFirstNumber) { case '2': request.abort(); return callback(true); default: request.abort(); return callback(false); } }; request.send(''); } // Called on commit checkbox change function update_selected_commits(commit, order) { console.log('Changing '+commit.value+' to '+commit.checked); if (! commit.checked) { // Keep 2 selected commit.checked = true; console.log('- Not allowed, we need 2 selected'); return; } // A new selection, keep only 2 selected if (order < parseInt(commit1.getAttribute('order'))) { commit1.checked = false; commit1 = commit; console.log('- Moving commit1'); } else { commit2.checked = false; commit2 = commit; console.log('- Moving commit2'); } update_commits(); } function update_commits() { // Remove tooltips so they dont get stuck //$('[data-toggle="tooltip"]').tooltip("hide"); console.log("================================================================================"); console.log("commit1:", commit1.value); console.log("commit2:", commit2.value); // 1. Update commit_legend_links // 2. Update commit_legend // 3. Update current_diff_view var commit1_hash = document.getElementById("commit1_hash"); var commit2_hash = document.getElementById("commit2_hash"); // Not yet synced, so this is the old var old_commit1 = commit1_hash.value; var old_commit2 = commit2_hash.value; // Update commit_legend_links var kicad_pro_path_1 = document.getElementById("commit1_kicad_pro_path").value; var kicad_pro_path_2 = document.getElementById("commit2_kicad_pro_path").value; document.getElementById("commit1_kicad_pro_path").value = kicad_pro_path_1.replace(old_commit1, commit1.value); document.getElementById("commit2_kicad_pro_path").value = kicad_pro_path_2.replace(old_commit2, commit2.value); // Update commit_legend commit1_hash.value = commit1.value; commit2_hash.value = commit2.value; document.getElementById("commit1_legend_hash").innerHTML = commit1.value; document.getElementById("commit2_legend_hash").innerHTML = commit2.value; // Update current_diff_view if (current_view == "show_sch") { update_page(); } else { update_layer(); } } function loadFile(filePath) { console.log("filePath:", filePath); var result = null; var xmlhttp = new XMLHttpRequest(); xmlhttp.open('GET', filePath, false); xmlhttp.send(); if (xmlhttp.status==200) { result = xmlhttp.responseText; } return result.split("\n").filter((a) => a); } function change_selected_page(index) { selected_page = index; update_selected_page(); } function update_selected_page() { var page_filename = pages[selected_page].value.replace(".kicad_sch", "").replace(".sch", ""); var image_path_1; var image_path_2; if (sheet_pages_commit1.has(page_filename)) { image_path_1 = commit1.value + "/_KIRI_/sch/" + page_filename + ".svg"; } else { image_path_1 = "blank.svg"; } if (sheet_pages_commit2.has(page_filename)) { image_path_2 = commit2.value + "/_KIRI_/sch/" + page_filename + ".svg"; } else { image_path_2 = "blank.svg"; } console.log("[SCH] page_filename =", page_filename); console.log("[SCH] image_path_1 =", image_path_1); console.log("[SCH] image_path_2 =", image_path_2); var image_path_timestamp_1 = image_path_1 + url_timestamp(commit1.value); var image_path_timestamp_2 = image_path_2 + url_timestamp(commit2.value); if (current_view != old_view) { old_view = current_view; removeEmbed(); lastEmbed = createNewEmbed(image_path_timestamp_1, image_path_timestamp_2); } else { diff_xlink_1.href.baseVal = image_path_timestamp_1; diff_xlink_2.href.baseVal = image_path_timestamp_2; diff_xlink_1.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image_path_timestamp_1); diff_xlink_2.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image_path_timestamp_2); } update_fullscreen_label(); } function update_page() { console.log("-----------------------------------------"); // Runs only when updating commits update_sheets_list(); update_selected_page(); } function update_sheets_list() { // File = [COMMIT]/_KIRI_/sch_sheets // Data format: Name_without_extension|Relative_file_name|UUID|Instance_name|Sheet_Path_Name data1 = loadFile(commit1.value + "/_KIRI_/sch_sheets" + url_timestamp(commit1)); data2 = loadFile(commit2.value + "/_KIRI_/sch_sheets" + url_timestamp(commit2)); var sheets = []; var new_sheets_list = []; sheet_pages_commit1 = new Set(); for (const d of data1) { sheets.push(d); sheet = d.split("|")[4]; sheet_pages_commit1.add(sheet); new_sheets_list.push(sheet); } sheet_pages_commit2 = new Set(); for (const d of data2) { if (! sheets.includes(d)) { sheets.push(d); } sheet = d.split("|")[4]; sheet_pages_commit2.add(sheet); new_sheets_list.push(sheet); } sheets = Array.from(new Set(sheets)); console.log("[SCH] Sheets =", sheets.length); console.log("sheets", sheets); var form_inputs_html; var index = 0; for (const d of sheets) { var splitted = d.split("|"); var visible_sheet = splitted[3]; var sheet = splitted[4]; var color_style; in_c1 = sheet_pages_commit1.has(sheet); in_c2 = sheet_pages_commit2.has(sheet); if (in_c1 && in_c2) { color_style = "normal_item"; } else if (in_c2) { color_style = "removed_item"; } else { color_style = "added_item"; } var input_html = ` `; form_inputs_html = form_inputs_html + input_html; index = index + 1; } // Return if the current list is equal to the new list console.log("current_sheets_list = ", current_sheets_list); console.log("new_sheets_list = ", new_sheets_list); if (current_sheets_list.toString() === new_sheets_list.toString()) { console.log("Keep the same list of sheets"); return; } current_sheets_list = new_sheets_list; // ID for the previous selection (if any) var old_selected_page_id; if (selected_page >= 0) { old_selected_page_id = pages[selected_page].id; } // Update list of pages console.log('Updating the list of pages'); document.getElementById("pages_list_form").innerHTML = form_inputs_html.replace("undefined", ""); var new_sel; if (selected_page >= 0) { const optionLabels = Array.from(pages).map((opt) => opt.id); new_sel = optionLabels.indexOf(old_selected_page_id); // Choose the last if it no longer exist (removed/added?) new_sel = (new_sel >= 0 ? new_sel : optionLabels.length - 1); } else { // First run, nothings selected, select the first new_sel = 0; } pages[new_sel].checked = true; selected_page = new_sel; } function pad(num, size) { num = num.toString(); while (num.length < size) { num = "0" + num; } return num; } function load_commits() { commit1 = commit2 = -1; commits = loadFile("commits"); var i = 1; var all_commits_html = ""; for (const line of commits) { // Data format: HASH|DATE|AUTHOR|DESCRIPTION|SCH_CHANGED|PCB_CHANGED|TXT_CHANGED // TXT_CHANGED doesn't seem to be useful, currently discarded splitted = line.split("|"); var hash = splitted[0]; var dt = splitted[1]; var author = splitted[2]; var desc = splitted[3]; var tooltip = `Commit: ${hash} Date: ${dt} Author: ${author} Description: ${desc}`; var sch_changed = splitted[4] == 'True'; var pcb_changed = splitted[5] == 'True'; var pcb_icon = (pcb_changed ? PCB_IMG : EMPTY_IMG); var sch_icon = (sch_changed ? SCH_IMG : EMPTY_IMG); var i02 = pad(i, 2); var cls = (hash == '_local_' ? 'text-warning' : 'text-info'); var checked = (i <= 2 ? ' checked="checked"' : ''); var commit_html = ` `; all_commits_html = all_commits_html + commit_html; i = i + 1; } // Update commits list document.getElementById("commits_form").innerHTML = all_commits_html; commits_form = document.getElementsByClassName("chkGroup"); num_commits = i - 1; // TODO What if just 1 or none? commit1 = commits_form[0]; commit2 = commits_form[1]; } function load_project_data() { // Data format: TITLE // SCH_TITLE|SCH_REVISION|SCH_DATE // PCB_TITLE|PCB_REVISION|PCB_DATE data = loadFile("project"); document.title = data[0]; splitted = data[1].split("|"); document.getElementById("sch_title_text").innerHTML = splitted[0]; document.getElementById("sch_rev").innerHTML = `Rev. ${splitted[1]} (${splitted[2]})`; splitted = data[2].split("|"); document.getElementById("pcb_title_text").innerHTML = splitted[0]; document.getElementById("pcb_rev").innerHTML = `Rev. ${splitted[1]} (${splitted[2]})`; } function change_selected_layer(index) { selected_layer = index; update_selected_layer(); } function update_layers_list() { var id; var layer; var dict = {}; var id_pad; var layer_name; var new_layers_list = []; var form_inputs_html; // File = [COMMIT]/_KIRI_/pcb_layers // Format = ID|LAYER var used_layers_1 = loadFile(commit1.value + "/_KIRI_/pcb_layers" + url_timestamp(commit1)); var used_layers_2 = loadFile(commit2.value + "/_KIRI_/pcb_layers" + url_timestamp(commit2)); layers_commit1 = new Set(); for (const line of used_layers_1) { id = line.split("|")[0]; layer = line.split("|")[1]; //.replace(".", "_"); dict[id] = [layer]; layers_commit1.add(pad(id, 2)); new_layers_list.push(id); } layers_commit2 = new Set(); for (const line of used_layers_2) { id = line.split("|")[0]; layer = line.split("|")[1]; //.replace(".", "_"); layers_commit2.add(pad(id, 2)); new_layers_list.push(id); // Add new key if (! dict.hasOwnProperty(id)) { dict[id] = [layer]; } else { // Append if id key exists if (dict[id] != layer) { dict[id].push(layer); } } } console.log("[PCB] Layers =", Object.keys(dict).length); var index = 0; for (const [layer_id, layer_names] of Object.entries(dict)) { id = parseInt(layer_id); id_pad = pad(id, 2); layer_name = layer_names[0]; var color_style; in_c1 = layers_commit1.has(id_pad); in_c2 = layers_commit2.has(id_pad); if (in_c1 && in_c2) { color_style = "normal_item"; } else if (in_c2) { color_style = "removed_item"; } else { color_style = "added_item"; } var input_html = ` `; form_inputs_html = form_inputs_html + input_html; index = index + 1; } // Return if the current list is equal to the new list console.log("current_layers_list = ", current_layers_list); console.log("new_layers_list = ", new_layers_list); if (current_layers_list.toString() === new_layers_list.toString()) { console.log("Keep the same list of layers"); return; } current_layers_list = new_layers_list; // ID for the previous selection (if any) var old_selected_layer_id; if (selected_layer >= 0) { old_selected_layer_id = layers[selected_layer].id; } // Update list of layers console.log('Updating the list of layers'); document.getElementById("layers_list_form").innerHTML = form_inputs_html.replace("undefined", ""); var new_sel; if (selected_layer >= 0) { const optionLabels = Array.from(layers).map((opt) => opt.id); new_sel = optionLabels.indexOf(old_selected_layer_id); // Choose the last if it no longer exist (removed/added?) new_sel = (new_sel >= 0 ? new_sel : optionLabels.length - 1); } else { // First run, nothings selected, select the first new_sel = 0; } layers[new_sel].checked = true; selected_layer = new_sel; } function update_layer() { console.log("-----------------------------------------"); // Runs only when updating commits update_layers_list(); update_selected_layer(); } function update_selected_layer() { var layer_id = layers[selected_layer].id.split("-")[1]; var image_path_1; var image_path_2; if (layers_commit1.has(layer_id)) { image_path_1 = commit1.value + "/_KIRI_/pcb/layer" + "-" + layer_id + ".svg"; } else { image_path_1 = "blank.svg"; } if (layers_commit2.has(layer_id)) { image_path_2 = commit2.value + "/_KIRI_/pcb/layer" + "-" + layer_id + ".svg"; } else { image_path_2 = "blank.svg"; } console.log("[PCB] layer_id =", layer_id); console.log("[PCB] image_path_1 =", image_path_1); console.log("[PCB] image_path_2 =", image_path_2); var image_path_timestamp_1 = image_path_1 + url_timestamp(commit1.value); var image_path_timestamp_2 = image_path_2 + url_timestamp(commit2.value); if (current_view != old_view) { old_view = current_view; removeEmbed(); lastEmbed = createNewEmbed(image_path_timestamp_1, image_path_timestamp_2); } else if (layer_id != "") { diff_xlink_1.href.baseVal = image_path_timestamp_1; diff_xlink_2.href.baseVal = image_path_timestamp_2; diff_xlink_1.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image_path_timestamp_1); diff_xlink_2.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image_path_timestamp_2); } update_fullscreen_label(); } // ======================================= // SVG Controls // ======================================= function ready() { console.log('Starting JS'); check_server_status(); pages = document.getElementById("pages_list_form"); layers = document.getElementById("layers_list_form"); commit1_legend_color = window.getComputedStyle(document.querySelector(".icon-commit1")).color; commit2_legend_color = window.getComputedStyle(document.querySelector(".icon-commit2")).color; commit_standalone_color = window.getComputedStyle(document.querySelector(".commit-standalone-color")).color load_project_data(); load_commits(); current_view = (selected_view == "schematic" ? "show_sch" : "show_pcb"); update_commits(); } window.addEventListener('DOMContentLoaded', ready); // ======================================= // Toggle Schematic/Layout // ======================================= function show_sch() { current_view = "show_sch"; // Show schematic stuff document.getElementById("show_sch_lbl").classList.add('active'); document.getElementById("show_sch").checked = true; // document.getElementById("diff-sch").style.display = "inline"; diff_xlink_1.parentElement.style.display = "inline"; diff_xlink_2.parentElement.style.display = "inline"; document.getElementById("pages_list").style.display = "inline"; document.getElementById("sch_title").style.display = "inline"; // Hide layout stuff document.getElementById("show_pcb_lbl").classList.remove('active'); document.getElementById("show_pcb").checked = false; // document.getElementById("diff-pcb").style.display = "none"; // document.getElementById("diff-xlink-1-pcb").parentElement.style.display = "none"; // document.getElementById("diff-xlink-2-pcb").parentElement.style.display = "none"; document.getElementById("layers_list").style.display = "none"; document.getElementById("pcb_title").style.display = "none"; update_page(); } function show_pcb() { current_view = "show_pcb"; // Show layout stuff document.getElementById("show_pcb_lbl").classList.add('active'); document.getElementById("show_pcb").checked = true; // document.getElementById("diff-pcb").style.display = "inline"; diff_xlink_1.parentElement.style.display = "inline"; diff_xlink_2.parentElement.style.display = "inline"; document.getElementById("layers_list").style.display = "inline"; document.getElementById("pcb_title").style.display = "inline"; // Hide schematic stuff document.getElementById("show_sch_lbl").classList.remove('active'); document.getElementById("show_sch").checked = false; // document.getElementById("diff-sch").style.display = "none"; // document.getElementById("diff-xlink-1-sch").parentElement.style.display = "none"; // document.getElementById("diff-xlink-2-sch").parentElement.style.display = "none"; document.getElementById("pages_list").style.display = "none"; document.getElementById("sch_title").style.display = "none"; update_layer(); } // ======================================= // ======================================= // Hide fields with missing images function imgError(image) { // console.log("Image Error (missing or problematic) =", image.href.baseVal); image.onerror = null; parent = document.getElementById(image.id).parentElement; parent.style.display = "none"; return true; } // #=========================== var server_status = 1; var old_server_status = -1; function check_server_status() { var img; img = document.getElementById("server_status_img"); if (! img) { img = document.body.appendChild(document.createElement("img")); img.setAttribute("id", "server_status_img"); img.style.display = "none"; } img.onload = function() { server_is_online(); }; img.onerror = function() { server_is_offline(); }; img.src = "blank.svg" + url_timestamp(); setTimeout(check_server_status, 5000); } function server_is_online() { server_status = 1; document.getElementById("server_offline").style.display = "none"; if (server_status != old_server_status) { old_server_status = server_status; console.log("Server is Online"); } } function server_is_offline() { server_status = 0; document.getElementById("server_offline").style.display = "block"; if (server_status != old_server_status) { old_server_status = server_status; console.log("Server is Offline"); } } // ================================================================== function createNewEmbed(src1, src2) { console.log("createNewEmbed..."); var embed = document.createElement('div'); embed.setAttribute('id', "diff-container"); embed.setAttribute('class', "position-relative"); embed.setAttribute('style', "padding: 0px; height: 94%;"); var filter_1 = (current_diff_filter === "diff" ? 'url(#filter-1)' : 'url(#filter-12)'); var filter_2 = (current_diff_filter === "diff" ? 'url(#filter-2)' : 'url(#filter-22)'); // WORKING WITH FILTERS.. // https://fecolormatrix.com/ var svg_element = ` `; document.getElementById('diff-container').replaceWith(embed); document.getElementById('diff-container').innerHTML = svg_element; document.getElementById('diff-container').onfullscreenchange = fullscreenchanged; console.log(">>> SVG: ", embed); svgpanzoom_selector = "#svg-id"; panZoom_instance = svgPanZoom( svgpanzoom_selector, { zoomEnabled: true, controlIconsEnabled: false, center: true, minZoom: 1, maxZoom: 20, zoomScaleSensitivity: 0.22, contain: false, fit: false, // cannot be used, bug? (this one must be here to change the default) viewportSelector: '.my_svg-pan-zoom_viewport', eventsListenerElement: document.querySelector(svgpanzoom_selector), onUpdatedCTM: function() { if (current_view == "show_sch") { if (sch_current_zoom != sch_old_zoom) { console.log(">> Restoring SCH pan and zoom"); panZoom_instance.zoom(sch_current_zoom); panZoom_instance.pan(sch_current_pan); sch_old_zoom = sch_current_zoom; } } else { if (pcb_current_zoom != pcb_old_zoom) { console.log(">> Restoring PCB pan and zoom"); panZoom_instance.zoom(pcb_current_zoom); panZoom_instance.pan(pcb_current_pan); pcb_old_zoom = pcb_current_zoom; } } } }); console.log("panZoom_instance:", panZoom_instance); embed.addEventListener('load', lastEventListener); document.getElementById('zoom-in').addEventListener('click', function(ev) { ev.preventDefault(); panZoom_instance.zoomIn(); panZoom_instance.center(); }); document.getElementById('zoom-out').addEventListener('click', function(ev) { ev.preventDefault(); panZoom_instance.zoomOut(); panZoom_instance.center(); }); document.getElementById('zoom-fit').addEventListener('click', function(ev) { ev.preventDefault(); panZoom_instance.resetZoom(); panZoom_instance.center(); }); diff_xlink_1 = document.getElementById("diff-xlink-1"); diff_xlink_2 = document.getElementById("diff-xlink-2"); return embed; } function removeEmbed() { console.log(">=============================================<"); console.log("removeEmbed..."); console.log(">> lastEmbed: ", lastEmbed); console.log(">> panZoom_instance: ", panZoom_instance); // Destroy svgpanzoom if (panZoom_instance) { if (current_view == "show_pcb") { sch_current_zoom = panZoom_instance.getZoom(); sch_current_pan = panZoom_instance.getPan(); sch_old_zoom = null; } else { pcb_current_zoom = panZoom_instance.getZoom(); pcb_current_pan = panZoom_instance.getPan(); pcb_old_zoom = null; } panZoom_instance.destroy(); // Remove event listener lastEmbed.removeEventListener('load', lastEventListener); // Null last event listener lastEventListener = null; // Remove embed element // document.getElementById('diff-container').removeChild(lastEmbed); // Null reference to embed lastEmbed = null; } } function update_fullscreen_label() { fullscreen_label = document.getElementById("fullscreen_label"); if (current_view == "show_sch") { page_name = document.getElementById("label-" + pages[selected_page].id).innerHTML; view_item = "Page " + page_name; } else { layer_name = document.getElementById("label-" + layers[selected_layer].id).innerHTML; view_item = "Layer " + layer_name; } if (is_fullscreen) { if (fullscreen_label) { document.getElementById("commit1_fs").innerHTML = `(${commit1.value})`; document.getElementById("commit2_fs").innerHTML = `(${commit2.value})`; document.getElementById("view_item_fs").innerHTML = view_item; } else { var vis1 = document.getElementById("commit1").style.visibility; var col1 = document.getElementById("commit1_legend").style.color; var vis2 = document.getElementById("commit2").style.visibility; var col2 = document.getElementById("commit2_legend").style.color; var vis3 = document.getElementById("commit3").style.visibility; label = `
` const element = document.getElementById("diff-container"); element.insertAdjacentHTML("afterbegin", label); } } } function toggle_fullscreen() { if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } is_fullscreen = false; const box = document.getElementById('fullscreen_label'); box.remove(); } else { element = document.getElementById("diff-container"); if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if (element.webkitRequestFullscreen) { element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); } else if (element.msRequestFullscreen) { element.msRequestFullscreen(); } is_fullscreen = true; update_fullscreen_label() } } /******************************************************************** Workaround for Chrome exiting full screen using ESC Note: If this works for any browser we could just do the API changes here. ********************************************************************/ function fullscreenchanged(event) { if (! document.fullscreenElement && is_fullscreen) { is_fullscreen = false; const box = document.getElementById('fullscreen_label'); box.remove(); } }