class DataDisplay extends HTMLElement{ #rootdoc = null; #source = null; #filter = { mode : "out", distance: 15, enzyme: "", zeromatches : false } #timeout = null; #export = "" constructor(){ super() this.#rootdoc = this.attachShadow({ "mode" : "open"}) this.render() } show(source){ this.#source = source this.render() } render(){ if(this.#source == null){ this.#rootdoc.innerHTML = `
Nothing to show
` }else{ const s = this.#source this.#rootdoc.innerHTML = `
${s.getHeader()}
Pair of two guides ?

Pair of two guides

Analysis of the imported data to find a pair of two gRNAs in the maximum desired distance. By clicking on the gRNA, the gRNAs that can be used as a pair are shown. The number of available gRNAs as a pair is shown as a blue square.

PAM OUT
pam out

The PAM sites of the pair of two gRNAs face outwards. The distance between them is calculated from the 5’ end of the one gRNA till the 5’ end of the other gRNA.

PAM IN
pam out

The PAM sites of the pair of two gRNAs face inwards. The distance between them is calculated from the 3’ end of the one gRNA till the 3’ end of the other gRNA.

Any PAM

All the different directions of the two gRNAs and the configurations of the PAM sites are considered, including the configurations PAM OUT and PAM IN.

Restriction Enzyme ?

Restriction Enzyme

pam out

Analysis of the imported data to find gRNAs in a maximum distance of a selected restriction enzyme. The distance between the gRNA and the restriction enzyme is calculated as the closest distance between the 5’ or 3’ end of the restriction enzyme and the 5’ or 3’ end the gRNA. By clicking on the gRNA, the accurate distance between the gRNA and the restriction enzyme is shown in a grey square. The – means that the restriction site is located upstream of the gRNA recognition site.

Maximum distance
${this.renderTable()}
` const helps = Array.prototype.slice.call(this.#rootdoc.querySelectorAll("span[name='help']")) helps.forEach(h=>{ h.addEventListener("click", ev=>{ ev.target.parentElement.querySelector(".help-text").classList.toggle("d-none") }) }) document.addEventListener("keydown", ev=>{ if(ev.key === "Escape"){ const hts = Array.prototype.slice.call(this.#rootdoc.querySelectorAll(".help-text")) hts.forEach(ht=>{ if(!ht.classList.contains("d-none")) ht.classList.add("d-none"); }) } }) this.#rootdoc.querySelector("div.filters").addEventListener("change", ev=>{ const tgt = ev.target if(tgt.id === "pam-any" || tgt.id === "pam-in" || tgt.id === "pam-out" || tgt.id === 're') { if(tgt.id === "pam-any" || tgt.id === "pam-in" || tgt.id === "pam-out"){ this.#rootdoc.querySelector("#restriction-enzyme").disabled = true; } else if(tgt.id === "re" ) { this.#rootdoc.querySelector("#restriction-enzyme").disabled = false; } this.#filter.mode = tgt.value this.#rootdoc.querySelector("#table-container").innerHTML = this.renderTable(); } }) this.#rootdoc.querySelector("div.filters").addEventListener("input", ev=>{ const tgt = ev.target if(tgt.id === "distance"){ if(this.#timeout == null){ this.#timeout = window.setTimeout(()=>{ this.#filter.distance = Number(this.#rootdoc.querySelector("#distance").value) this.#rootdoc.querySelector("#table-container").innerHTML = this.renderTable() this.#timeout = null; }, 1000); } } }) this.#rootdoc.querySelector("button[name='tsvexport2']").addEventListener("click", ev=>{ this.exportTable2("\t") }) this.#rootdoc.querySelector("button[name='export2ws']").addEventListener("click", ev => { this.export2Workspace("\t"); }) this.#rootdoc.querySelector("#table-container").addEventListener("click", ev=>{ var root = ev.target.parentElement while(root != null && !root.getAttribute("data-rank")){ root = root.parentElement } if(root == null) return; const rank = root.getAttribute("data-rank") if(rank){ Array.prototype.slice.call(this.#rootdoc.querySelectorAll(`#table-container tr[data-rel-rank='${rank}']`)).forEach(tr=>tr.classList.toggle("d-none")) } }) this.#rootdoc.querySelector("#toggle-zero-matches").addEventListener("change", ev=>{ const tgt = ev.target this.#filter.zeromatches = tgt.checked this.toggleVisibility() }) const reSelect = this.#rootdoc.querySelector("#restriction-enzyme"); reSelect.data = iGeneIndexer.restrictionEnzymes.filter(re=>!re.sequence.includes('?') && !re.sequence.includes('(')) /*const reSelect = this.#rootdoc.querySelector("#restriction-enzyme"); const reSelectFeedback = this.#rootdoc.querySelector("#restriction-enzyme-feedback"); const reSelectDatalist = this.#rootdoc.querySelector("#restriction-enzyme-datalist"); reSelectDatalist.innerHTML = iGeneIndexer.restrictionEnzymes.reduce((acc, e)=>{ return acc + ` ` }, '')*/ /*iGeneIndexer.restrictionEnzymes.forEach(enzyme => { const newOption = document.createElement("option"); newOption.text = enzyme.name + ' (' + enzyme.sequence + ')'; newOption.value = enzyme.sequence; if (enzyme.sequence.includes('?') || enzyme.sequence.includes('(')) { newOption.disabled = true; } reSelectDatalist.add(newOption); });*/ // reSelect.addEventListener("change", ev => { // this.#filter.enzyme = reSelect.value; // const o = reSelectDatalist.querySelector("option[value='" + reSelect.value + "']") // reSelectFeedback.textContent = o ? o.textContent : reSelect.value // this.#rootdoc.querySelector("#table-container").innerHTML = this.renderTable(); // }) } } toggleVisibility(){ const trs = Array.prototype.slice.call(this.#rootdoc.querySelectorAll("tr.table-row-nomatch")) trs.forEach(tr=>tr.classList.toggle('d-none')) } updateEnzyme(enzyme){ this.#filter.enzyme = enzyme setTimeout(() => { this.#rootdoc.querySelector("#table-container").innerHTML = this.renderTable(); }, 100); } renderTable() { const renderer = this.#source.getRenderer(this.#filter, "html") return renderer.renderTable() } constructFilename() { const indexer = this.#source.getIndexer(); const filter = this.#filter; let filename = 'export_'; filename += 'genome=' + indexer.getGenome() + '_chr=' + indexer.getChromosome() + '_pam=' + indexer.getPAM(); filename += '_dist=' + filter.distance + '_mode=pam-' + filter.mode + (filter.mode === 're' ? '_(enz=' + filter.enzyme + ')' : ''); return filename; } exportTable(sep){ const renderer = this.#source.getRenderer(this.#filter, "tsv") if(renderer != null){ this.#export = renderer.renderTable() var element = document.createElement('a'); element.setAttribute('href', 'data:text/tab-separated-values;charset=utf-8,' + encodeURIComponent(this.#export)); element.setAttribute('download', this.constructFilename() + '.tsv'); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } } exportTable2(sep){ const renderer = this.#source.getRenderer(this.#filter, "tsv2") if(renderer != null){ this.#export = renderer.renderTable() var element = document.createElement('a'); element.setAttribute('href', 'data:text/tab-separated-values;charset=utf-8,' + encodeURIComponent(this.#export)); element.setAttribute('download', this.constructFilename() + '.tsv'); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } } async export2Workspace(sep) { const renderer = this.#source.getRenderer(this.#filter, "tsv2") if(renderer != null){ const folderName = "i-Gene-Matcher"; const date = new Date(); const fileName = this.constructFilename() + '_' + date.toISOString().substring(0, 11) + date.toLocaleTimeString().replaceAll(":", "-") + ".tsv"; const file2export = renderer.renderTable(); const workspace = new D4SWorkspace("https://api.d4science.org/workspace"); const wsId = await workspace.getWorkspace(null); const iGeneFolder = await workspace.checkOrCreateFolder(wsId, folderName, "I-Gene tool export folder", null); if(await workspace.uploadFile(iGeneFolder, fileName, "I-Gene Matcher Export work of " + date, file2export, "text/tab-separated-values", null)) { alert("File successfully saved on D4Science Workspace as:\n\n/" + folderName + "/" + fileName); } else { alert("An error occurred during the file upload to workspace, check browser console for more details"); } } } } window.customElements.define('igene-data-display', DataDisplay);