41b27825db55ab0699dacce3c18c34cf791e6428 hiram Sat Sep 7 23:49:38 2024 -0700 correctly manipulate the copy to clipboard link refs #32596 diff --git src/hg/js/assemblySearch.js src/hg/js/assemblySearch.js index 16595a5..39c4bcb 100644 --- src/hg/js/assemblySearch.js +++ src/hg/js/assemblySearch.js @@ -45,30 +45,33 @@ if (asmStatus === "replaced") document.getElementById('statusReplaced').checked = true; if (asmStatus === "suppressed") document.getElementById('statusSuppressed').checked = true; } if (urlParams.has('category')) { let refSeqCategory = urlParams.get('category'); document.getElementById('refSeqAny').checked = true; // default // only one of these etwo cases will be true if (refSeqCategory === "reference") document.getElementById('refSeqReference').checked = true; if (refSeqCategory === "representative") document.getElementById('refSeqRepresentative').checked = true; } // default starts as hidden + let copyIcon0 = document.getElementById('copyIcon0'); + stateObject.copyIcon0 = copyIcon0.innerHTML; + document.getElementById('urlCopyLink').style.display = "none"; stateObject.advancedSearchVisible = false; advancedSearchVisible(false); if (urlParams.has('advancedSearch')) { let advancedSearch = urlParams.get('advancedSearch'); advancedSearchVisible(advancedSearch); stateObject.advancedSearchVisible = advancedSearch; } if (urlParams.has('measureTiming')) { // accepts no value or other string var measureValue = urlParams.get('measureTiming'); if ("0" === measureValue | "off" === measureValue) { measureTiming = false; } else { // any other string turns it on measureTiming = true; } } @@ -134,32 +137,31 @@ var searchTerm = document.getElementById('searchBox').value; var resultCountLimit = document.getElementById('maxItemsOutput'); var mustExist = document.getElementById('mustExist').checked; var notExist = document.getElementById('notExist').checked; browserExist = "mustExist"; if (mustExist && notExist) { browserExist = "mayExist"; } else if (notExist) { browserExist = "notExist"; } makeRequest(searchTerm, browserExist, resultCountLimit.value); }); advancedSearchButton.addEventListener('click', function() { - let shareThisSearch = document.getElementById('shareThisSearch'); - shareThisSearch.innerHTML = " "; + document.getElementById('urlCopyLink').style.display = "none"; let searchOptions = document.getElementById("advancedSearchOptions"); // I don't know why it is false the first time ? if (! searchOptions.style.display || searchOptions.style.display === "none") { advancedSearchVisible(true); } else { advancedSearchVisible(false); } }); // restore history on back button window.addEventListener('popstate', function(e) { var state = event.state; if (state) { stateObject.queryString = state.queryString; stateObject.advancedSearchVisible = state.advancedSearchVisible; @@ -455,30 +457,31 @@ } resultCounts += "out of " + availableAssemblies.toLocaleString() + " total number of assemblies"; document.getElementById('resultCounts').innerHTML = resultCounts; if (measureTiming) { var etMs = extraInfo.elapsedTimeMs; var elapsedTime = "" + etMs.toLocaleString() + " milliseconds"; if ( etMs > 1000 ) { var etSec = etMs/1000; elapsedTime = "" + etSec.toFixed(2) + " seconds"; } document.getElementById('elapsedTime').innerHTML = elapsedTime.toLocaleString(); document.getElementById("measureTiming").style.display = "inline"; } else { document.getElementById("measureTiming").style.display = "none"; } + document.getElementById('urlCopyLink').style.display = "inline"; } // function populateTableAndInfo(jsonData) function enableButtons() { document.getElementById('submitSearch').disabled = false; document.getElementById('clearSearch').disabled = false; } function disableButtons() { document.getElementById('submitSearch').disabled = true; document.getElementById('clearSearch').disabled = true; } function parentTable(e) { while (e) { e = e.parentNode; @@ -553,30 +556,65 @@ var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (4 === this.readyState && 200 === this.status) { requestSubmitButton.value = "request completed"; } else { if (4 === this.readyState && 404 === this.status) { failedRequest(url); } } }; xmlhttp.open("GET", url, true); xmlhttp.send(); } // sendRequest: function(name, email. asmId) +// borrowed this code from utils.js +function copyToClipboard(ev) { + /* copy a piece of text to clipboard. event.target is some DIV or SVG that is an icon. + * The attribute data-target of this element is the ID of the element that contains the text to copy. + * The text is either in the attribute data-copy or the innerText. + * see C function printCopyToClipboardButton(iconId, targetId); + * */ + + ev.preventDefault(); + + var buttonEl = ev.target.closest("button"); // user can click SVG or BUTTON element + + var targetId = buttonEl.getAttribute("data-target"); + if (targetId===null) + targetId = ev.target.parentNode.getAttribute("data-target"); + var textEl = document.getElementById(targetId); + var text = textEl.getAttribute("data-copy"); + if (text===null) + text = textEl.innerText; + + var textArea = document.createElement("textarea"); + textArea.value = text; + // Avoid scrolling to bottom + textArea.style.top = "0"; + textArea.style.left = "0"; + textArea.style.position = "fixed"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + buttonEl.innerHTML = 'Copied'; + ev.preventDefault(); +} + // do not allow both checkboxes to go off function atLeastOneCheckBoxOn(e) { var mustExist = document.getElementById('mustExist').checked; var notExist = document.getElementById('notExist').checked; if (! mustExist && ! notExist ) { // turn on the other one when both off if (e.name === "mustExist") { document.getElementById('notExist').checked = true; } else { document.getElementById('mustExist').checked = true; } } } function checkForm(e) { if (requestSubmitButton.value === "request completed") { @@ -679,55 +717,64 @@ if (overflow > 0) { modalWindow.style.maxHeight = (parseInt(window.getComputedStyle(modalWindow).height) - overflow) + "px"; } modalWindow.style.marginTop = (-modalWindow.offsetHeight)/2 + "px"; modalWindow.style.marginLeft = (-modalWindow.offsetWidth)/2 + "px"; } if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } } function optionsChange(e) { // options are changing, share URL is no longer viable, eliminate it - let shareThisSearch = document.getElementById('shareThisSearch'); - shareThisSearch.innerHTML = " "; + document.getElementById('copyIcon0').innerHTML = stateObject.copyIcon0; + document.getElementById('urlCopyLink').style.display = "none"; } function makeRequest(query, browserExist, resultLimit) { // Disable the submit button disableButtons(); var wordMatch = document.querySelector('input[name="wordMatch"]:checked').value; var asmStatus = document.querySelector('input[name="asmStatus"]:checked').value; var refSeqCategory = document.querySelector('input[name="refSeqCategory"]:checked').value; var asmLevel = document.querySelector('input[name="asmLevel"]:checked').value; // start with what the user requested: var queryString = query; // for allWords, place + sign in front of each word if not already there if (wordMatch === "allWords") { var words = queryString.split(/\s+/); if (words.length > 1) { // not needed on only one word var queryPlus = ""; // compose new query string + let inQuote = false; words.forEach(function(word) { - if (word.startsWith("-")) { - queryPlus += " " + word; // do not add + to - - } else if (word.startsWith("+")) { + if (word.match(/^[-+]?"/)) { + if (word.match(/^[-+]/)) + queryPlus += " " + word; // do not add + to - or + already there + else + queryPlus += " +" + word; + inQuote = true; + } else if (inQuote) { queryPlus += " " + word; // space separates each word + if (word.endsWith('"')) + inQuote = false; + } else if (word.match(/[^-+]/)) { + queryPlus += " " + word; // do not add + to - or + already there } else { queryPlus += " +" + word; } }); queryString = queryPlus.trim(); } } // remove stray white space from beginning or end queryString = queryString.trim(); // Show the wait spinner document.querySelector(".submitContainer").classList.add("loading"); document.getElementById("loadingSpinner").style.display = "block"; var xhr = new XMLHttpRequest(); @@ -756,54 +803,55 @@ var searchOptions = document.getElementById("advancedSearchOptions"); if (searchOptions.style.display === "flex") { stateObject.advancedSearchVisible = true; historyUrl += ";advancedSearch=true"; } else { stateObject.advancedSearchVisible = false; } stateObject.maxItemsOutput = maxItemsOutput; stateObject.browser = browserExist; stateObject.debug = debug; stateObject.measureTiming = measureTiming; stateObject.wordMatch = wordMatch; stateObject.asmStatus = asmStatus; stateObject.refSeqCategory = refSeqCategory; stateObject.asmLevel = asmLevel; - let shareThisSearch = document.getElementById('shareThisSearch'); - let thisPageHref = "Share this search"; - shareThisSearch.innerHTML = thisPageHref; + let urlText0 = document.getElementById('urlText0'); + let hostName = window.location.hostname; + urlText0.innerHTML = "https://" + hostName + "/assemblySearch.html" + historyUrl; xhr.open('GET', urlPrefix + url, true); xhr.onload = function() { if (xhr.status === 200) { // Hide the wait spinner once the AJAX request is complete document.querySelector(".submitContainer").classList.remove("loading"); document.getElementById("loadingSpinner").style.display = "none"; + document.getElementById('copyIcon0').innerHTML = stateObject.copyIcon0; enableButtons(); stateObject.jsonData = xhr.responseText; history.pushState(stateObject, '', historyUrl); var data = JSON.parse(xhr.responseText); populateTableAndInfo(data); } else { // Hide the wait spinner once the AJAX request is complete document.querySelector(".submitContainer").classList.remove("loading"); document.getElementById("loadingSpinner").style.display = "none"; + document.getElementById('copyIcon0').innerHTML = stateObject.copyIcon0; + document.getElementById('urlCopyLink').style.display = "none"; enableButtons(); var tableBody = document.getElementById('tableBody'); tableBody.innerHTML = "no results found for query: '" + queryString + "'"; var metaData = document.getElementById('metaData'); metaData.innerHTML = ''; // metaData.innerHTML = "no results found for query: '" + queryString + "'"; document.getElementById('resultCounts').innerHTML = ""; document.getElementById('elapsedTime').innerHTML = "0"; } }; xhr.onerror = function() { alert('console.log("Request failed")'); console.log('Request failed'); };