Last active
May 18, 2017 14:20
-
-
Save sbliven/5c18f5c05d4be89a479d471af7a7bdc4 to your computer and use it in GitHub Desktop.
Demo of many NGL instances on one page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<script | |
src="https://code.jquery.com/jquery-3.2.1.min.js" | |
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" | |
crossorigin="anonymous"></script> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> | |
<script | |
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" | |
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" | |
crossorigin="anonymous"></script> | |
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> | |
<!--[if lt IE 9]> | |
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> | |
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> | |
<![endif]--> | |
<style> | |
.structureframe { | |
width:160px; | |
/* | |
height: 220px; | |
*/ | |
padding:10px; | |
/*border:solid 1px black;*/ | |
text-align: center; | |
} | |
.structureframe .pdbid { | |
text-transform: uppercase; | |
font-size: 12px; | |
} | |
.structureframe .pdbdate { | |
font-size: 10px; | |
} | |
.structureframe .title { | |
font-size: 10px; | |
color: grey; | |
width: 140px; | |
text-transform: capitalize; | |
} | |
.structureframe .viewport { | |
width:140px; | |
height:140px; | |
background:black; | |
} | |
.structureframe .light { | |
width: 8px; | |
height: 8px; | |
position: absolute; | |
right: 1px; | |
bottom: 1px; | |
border-radius: 50%; | |
background: red; | |
/*display: none; */ | |
} | |
</style> | |
<script src="https://cdn.rawgit.com/arose/ngl/v0.9.3/dist/ngl.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> | |
<script> | |
'use strict'; | |
NGL.mainScriptFilePath = "https://cdn.rawgit.com/arose/ngl/v0.9.3/dist/ngl.js"; | |
var spinnerUrl = "http://www.eppic-web.org/ewui/resources/images/spinner_d1c5ka1.gif"; | |
/** | |
* Represents one structure on the page. | |
* Boxes can be active (NGL instance), or inactive (static image). | |
* | |
* You can listen for state change notifications with | |
* box.$viewport.on('StructureBox:activate',... or 'StructureBox:deactivate' | |
*/ | |
class StructureBox { | |
constructor(pdbId,$viewport) { | |
this.pdbId = pdbId; | |
this._active = false; | |
this.$viewport = $viewport; | |
this.stage = null; | |
this.setImage(spinnerUrl); | |
this.orientation = null; | |
} | |
/// Trigger notifications on the viewport | |
set active(val) { | |
if(this._active != val) { | |
if(val) { | |
this._active = val; | |
this.$viewport.trigger('StructureBox:activate',[this]); | |
} else { | |
this._active = val; | |
this.$viewport.trigger('StructureBox:deactivate',[this]); | |
} | |
} | |
} | |
get active() { | |
return this._active; | |
} | |
/** | |
* Enable NGL for this structure | |
* @return a Promise to resolve upon completion | |
*/ | |
activate() { | |
var pdbId = this.pdbId; | |
console.log("Activating "+pdbId); | |
this.active = true; | |
// Replace static image with NGL | |
this.$viewport.empty(); | |
// set up NGL | |
this.stage = new NGL.Stage( "viewport"+pdbId ); | |
this.stage.setParameters({ backgroundColor:"white"} ); | |
// Debugging info about webgl events | |
this.$viewport.find("canvas").on('webglcontextlost', function(e) { | |
console.log("Lost context for "+pdbId); | |
}).on('webglcontextrestored', function(e) { | |
console.log("Restored context for "+pdbId); | |
}); | |
return this.stage.loadFile("rcsb://"+pdbId, { defaultRepresentation: true } ) | |
.then(() => { | |
if(this.orientation) { | |
this.stage.setOrientation(this.orientation) | |
} | |
}); | |
} | |
/** | |
* Disable NGL for this structure, replacing it with an image. | |
* @return a Promise | |
*/ | |
deactivate() { | |
var pdbId = this.pdbId; | |
console.log("Deactivating "+pdbId); | |
this.active = false; | |
// toggle click handler | |
var $viewport = this.$viewport; | |
// Save canvas reference | |
var $canvas = $viewport.find("canvas"); | |
// async replace spinner with screenshot of NGL | |
var stage = this.stage; | |
if( stage ) { | |
this.orientation = stage.getOrientation(); | |
return stage.makeImage({ | |
factor: 2, | |
antialias: true, | |
trim: false, | |
transparent: false | |
}).then( (blob) => { //resolve | |
var urlCreator = window.URL || window.webkitURL; | |
var imageUrl = urlCreator.createObjectURL(blob); | |
// Replace NGL with static image | |
this.setImage(imageUrl); | |
// // Destroy NGL stage | |
// $canvas.each(function(i,canvas) { | |
// var gl = canvas.getContext("webgl"); | |
// // currently only implemented on Firefox | |
// var ext = gl.getExtension("WEBGL_lose_context") | |
// if(ext) { | |
// // Explicitely free webgl | |
// // On other browsers, will happen upon garbage collection | |
// ext.loseContext(); | |
// } | |
// }); | |
}, () => { //reject | |
this.setImage(spinnerUrl); | |
}); | |
} else { | |
this.setImage(spinnerUrl); | |
return Promise.resolve(); | |
} | |
} | |
setImage(url) { | |
if( url ){ | |
this.imageUrl = url; | |
} | |
var $img = $("<img/>", { | |
"src": this.imageUrl, | |
"css": { | |
'width':'100%', | |
'height':'100%', | |
} | |
}); | |
this.$viewport.empty().append($img); | |
} | |
} | |
/** | |
* Queue to manage activating StructureBoxes. | |
* Because browsers are limited to 16 WebGL instances (across all browser tabs), | |
* this class automatically disables boxes to keep the total number active reasonable. | |
* | |
* Note that the actual WebGL contexts won't get dropped until the browser runs GC. | |
* | |
* All activations of the boxes managed by this queue should happen through the queue. | |
*/ | |
class StructureQueue { | |
constructor(boxes) { | |
this.boxes = boxes; // map pdbId -> StructureBox | |
this.activeBoxes = []; //queue of pdbId by activateion time (push latest, shift oldest) | |
this.maxActive = 2; | |
this.ongoing = Promise.resolve(); // promise with ongoing activations | |
} | |
/** | |
* @return a Promise, whose resolve and return methods will be passed the StructureBox | |
*/ | |
activate(pdbId) { | |
var box = this.boxes[pdbId]; | |
if( box === undefined) { | |
return Promise.reject(new Error("Error: unregistered pdbId: "+pdbId)); | |
} | |
this.ongoing = this.ongoing.then( () => { | |
var activeIndex = this.activeBoxes.indexOf(pdbId); | |
if( activeIndex >= 0 ) { | |
// Already active; make most recent item | |
this.activeBoxes.splice(activeIndex,1); | |
this.activeBoxes.push(pdbId); | |
console.log("DEBUG "+pdbId+" already active; ignoring"); | |
return Promise.resolve(); | |
} | |
// check for free WebGL contexts | |
if(this.activeBoxes.length < this.maxActive) { | |
// activate immediately | |
console.log("DEBUG activating "+pdbId+" immediately"); | |
this.activeBoxes.push(pdbId); | |
return box.activate(); | |
} else { | |
// deactivate a box first | |
var oldBoxId = this.activeBoxes[0]; | |
var oldBox = this.boxes[oldBoxId]; | |
console.log("DEBUG first deactivating "+oldBoxId+" to make space for "+pdbId); | |
return oldBox.deactivate().then( () => { | |
if( oldBox.active ) { | |
throw new Error("Error: unsuccessfully deactivated "+pdbId); | |
} | |
// Remove old box from queue | |
var i = this.activeBoxes.indexOf(oldBoxId); | |
this.activeBoxes.splice(i,1); | |
for( i in this.boxes) { | |
if( this.boxes[i].active != (this.activeBoxes.indexOf(i)>=0)) { | |
// Shouldn't happen; debugging | |
console.log("Error: "+i+" is "+(this.boxes[i].active?"active":"inactive") | |
+" but is "+((this.activeBoxes.indexOf(i)>=0)?"":"not ")+ "in activeBoxes"); | |
} | |
} | |
//TODO not thread safe. Race conditions? | |
if(this.activeBoxes.length >= this.maxActive) { | |
// shouldn't happen; could indicate threading error | |
throw new Error("Error: Too many active boxes"); | |
} | |
// now activate the new box | |
this.activeBoxes.push(pdbId); | |
return box.activate(); | |
}, (e) => { | |
// Try to clean up activeBoxes list despite error | |
if( !oldBox.active && this.activeBoxes[0].pdbId == pdbId) { | |
this.activeBoxes.shift(); | |
} | |
throw e; | |
}); | |
} | |
}); | |
return this.ongoing; | |
} | |
} | |
/** | |
* Create basic wrapper div for a single structure (in inactive state) | |
* @param structure: dict with structure info | |
* @return | |
*/ | |
function createStructPanel($parent,structure) { | |
var pdbId = structure.pdbId; | |
var $wrapper = $("<div/>", { | |
id: 'wrapper'+pdbId, | |
class: 'structureframe col-sm-4 col-md-1', | |
}).appendTo($parent); | |
$("<h3/>",{ | |
text: pdbId, | |
class: "pdbid", | |
}).appendTo($wrapper); | |
// $("<p/>", { | |
// text: structure.title, | |
// class: "pdbtitle", | |
// }).appendTo($wrapper); | |
var date = moment(structure.date).format("YYYY-MM-DD"); | |
$("<p/>", { | |
text: date, | |
class: "pdbdate", | |
}).appendTo($wrapper); | |
var $viewport = $("<div/>", { | |
'id': 'viewport'+pdbId, | |
'class': 'viewport' | |
}).appendTo($wrapper); | |
// Light to indicate that this box is active; debugging only | |
var $light = $("<div/>", { | |
'id': 'light'+pdbId, | |
'class': 'light', | |
}).appendTo($wrapper); | |
$viewport.on('StructureBox:deactivate', (box) => { | |
$light.css({background:'red'}); | |
}); | |
$viewport.on('StructureBox:activate', (box) => { | |
$light.css({background:'green'}); | |
}); | |
var box = new StructureBox(pdbId,$viewport); | |
return box; | |
} | |
function sleep(time) { | |
return new Promise((resolve) => setTimeout(resolve, time)); | |
} | |
</script> | |
<script> | |
var data = [ | |
{"title":"1-AMINOCYCLOPROPANE-1-CARBOXYLATE SYNTHASE","pdbId":"1B8G","date":"1999-01-31","description":"LYASE"},{"title":"ASPARTATE AMINOTRANSFERASE P195A MUTANT","pdbId":"1BQA","date":"1998-08-13","description":"AMINOTRANSFERASE"},{"title":"ASPARTATE AMINOTRANSFERASE P138A/P195A DOUBLE MUTANT","pdbId":"1BQD","date":"1998-08-14","description":"AMINOTRANSFERASE"},{"title":"CRYSTAL STRUCTURE OF THIOREDOXIN F FROM SPINACH CHLOROPLAST (SHORT FORM)","pdbId":"1F9M","date":"2000-07-11","description":"ELECTRON TRANSPORT"},{"title":"CRYSTAL STRUCTURE OF THIOREDOXIN F FROM SPINACH CHLOROPLAST (LONG FORM)","pdbId":"1FAA","date":"2000-07-13","description":"ELECTRON TRANSPORT"},{"title":"CRYSTAL STRUCTURE OF THIOREDOXIN M FROM SPINACH CHLOROPLAST (REDUCED FORM)","pdbId":"1FB0","date":"2000-07-14","description":"ELECTRON TRANSPORT"},{"title":"CRYSTAL STRUCTURE OF THIOREDOXIN M FROM SPINACH CHLOROPLAST (OXIDIZED FORM)","pdbId":"1FB6","date":"2000-07-14","description":"ELECTRON TRANSPORT"},{"title":"CRYSTAL STRUCTURE OF THE SOLUBLE DOMAIN OF TLPA FROM BRADYRHIZOBIUM JAPONICUM","pdbId":"1JFU","date":"2001-06-22","description":"MEMBRANE PROTEIN"},{"title":"Crystal Structure Of The LCMV Peptidic Epitope Gp276 In Complex With The Murine Class I Mhc Molecule H-2Db","pdbId":"1JPF","date":"2001-08-02","description":"IMMUNE SYSTEM"},{"title":"Crystal Structure Of The LCMV Peptidic Epitope Np396 In Complex With The Murine Class I Mhc Molecule H-2Db","pdbId":"1JPG","date":"2001-08-02","description":"IMMUNE SYSTEM"},{"title":"Crystal Structure of the Anti-His Tag Antibody 3D5 Single-Chain Fragment (scFv) in Complex with a Oligohistidine peptide","pdbId":"1KTR","date":"2002-01-17","description":"IMMUNE SYSTEM"},{"title":"CRYSTAL STRUCTURE OF APPLE ACC SYNTHASE IN COMPLEX WITH [2-(AMINO-OXY)ETHYL](5\u0027-DEOXYADENOSIN-5\u0027-YL)(METHYL)SULFONIUM","pdbId":"1M4N","date":"2002-07-03","description":"LYASE"},{"title":"Crystal structure of apple ACC synthase in complex with L-aminoethoxyvinylglycine","pdbId":"1M7Y","date":"2002-07-23","description":"LYASE"},{"title":"Crystal structure of a mycobacterial hsp60 epitope with the murine class I MHC molecule H-2Db","pdbId":"1N3N","date":"2002-10-29","description":"IMMUNE SYSTEM"},{"title":"Crystal structure of Escherichia coli GadB (low pH)","pdbId":"1PMM","date":"2003-06-11","description":"LYASE"},{"title":"Crystal structure of Escherichia coli GadB (neutral pH)","pdbId":"1PMO","date":"2003-06-11","description":"LYASE"},{"title":"Crystal structure of the disulfide-linked complex between the N-terminal and C-terminal domain of the electron transfer catalyst DsbD","pdbId":"1VRS","date":"2005-06-17","description":"OXIDOREDUCTASE"},{"title":"Crystal structure of apple ACC synthase in complex with L-vinylglycine","pdbId":"1YNU","date":"2005-01-25","description":"Lyase"},{"title":"Crystal Structure Of The Disulfide-Linked Complex Between The N-Terminal Domain Of The Electron Transfer Catalyst DsbD and The Cytochrome c Biogenesis Protein CcmG","pdbId":"1Z5Y","date":"2005-03-21","description":"OXIDOREDUCTASE/BIOSYNTHETIC PROTEIN"},{"title":"Solution Structure of the type 1 pilus assembly platform FimD(25-139)","pdbId":"1ZDV","date":"2005-04-15","description":"MEMBRANE PROTEIN"},{"title":"Solution Structure of the type 1 pilus assembly platform FimD(25-125)","pdbId":"1ZDX","date":"2005-04-15","description":"Membrane Protein"},{"title":"Crystal Structure of the Ternary Complex of FIMD (N-Terminal Domain) with FIMC and the Pilin Domain of FIMH","pdbId":"1ZE3","date":"2005-04-17","description":"CHAPERONE/STRUCTURAL/MEMBRANE PROTEIN"},{"title":"Crystal structure of Aminoglycoside Phosphotransferase APH(3\u0027)-IIIa in complex with the designed ankyrin repeat inhibitor AR_3a","pdbId":"2BKK","date":"2005-02-16","description":"TRANSFERASE/PEPTIDE"},{"title":"Crystal structure of an N-terminal deletion mutant of Escherichia coli GadB in an autoinhibited state (aldamine)","pdbId":"2DGK","date":"2006-03-14","description":"LYASE"},{"title":"Crystal structure of Escherichia coli GadB in complex with bromide","pdbId":"2DGL","date":"2006-03-14","description":"LYASE"},{"title":"Crystal structure of Escherichia coli GadB in complex with iodide","pdbId":"2DGM","date":"2006-03-14","description":"LYASE"},{"title":"Crystal Structure of the PRYSPRY-domain","pdbId":"2FBE","date":"2005-12-09","description":"UNKNOWN FUNCTION"},{"title":"crystal structure of the C-terminal domain of the electron transfer catalyst DsbD (oxidized form)","pdbId":"2FWE","date":"2006-02-02","description":"Oxidoreductase"},{"title":"high resolution crystal structure of the C-terminal domain of the electron transfer catalyst DsbD (reduced form)","pdbId":"2FWF","date":"2006-02-02","description":"Oxidoreductase"},{"title":"high resolution crystal structure of the C-terminal domain of the electron transfer catalyst DsbD (photoreduced form)","pdbId":"2FWG","date":"2006-02-02","description":"Oxidoreductase"},{"title":"atomic resolution crystal structure of the C-terminal domain of the electron transfer catalyst DsbD (reduced form at pH7)","pdbId":"2FWH","date":"2006-02-02","description":"Oxidoreductase"},{"title":"NMR structure of region 2 of E. coli sigmaE","pdbId":"2MAO","date":"2013-07-16","description":"TRANSCRIPTION"},{"title":"Solution structure of the complex formed by the region 2 of E. coli sigmaE and its cognate -10 promoter element non template strand TGTCAAA.","pdbId":"2MAP","date":"2013-07-16","description":"TRANSCRIPTION/DNA"},{"title":"ORNITHINE AMINOTRANSFERASE COMPLEXED WITH 5-FLUOROMETHYLORNITHINE","pdbId":"2OAT","date":"1998-05-07","description":"AMINOTRANSFERASE"},{"title":"Inhibition of caspase-2 by a designed ankyrin repeat protein (DARPin)","pdbId":"2P2C","date":"2007-03-07","description":"HYDROLASE"},{"title":"Crystal structure of truncated FimG (FimGt) in complex with the donor strand peptide of FimF (DSF)","pdbId":"3BFQ","date":"2007-11-23","description":"STRUCTURAL PROTEIN/STRUCTURAL PROTEIN"},{"title":"Crystal structure of truncated FimG (FimGt) in complex with the donor strand peptide of FimF (DSF)","pdbId":"3BFW","date":"2007-11-23","description":"STRUCTURAL PROTEIN/STRUCTURAL PROTEIN"},{"title":"Crystal structure of the ternary complex of FimD (N-Terminal Domain, FimDN) with FimC and the N-terminally truncated pilus subunit FimF (FimFt)","pdbId":"3BWU","date":"2008-01-10","description":"CHAPERONE, STRUCTURAL, MEMBRANE PROTEIN"},{"title":"Crystal structure of reduced DsbL","pdbId":"3C7M","date":"2008-02-07","description":"OXIDOREDUCTASE"},{"title":"Crystal structure of the zink-knuckle 2 domain of human CLIP-170 in complex with CAP-Gly domain of human dynactin-1 (p150-GLUED)","pdbId":"3E2U","date":"2008-08-06","description":"PROTEIN BINDING"},{"title":"Crystal structure of oxidized Ost6L","pdbId":"3G7Y","date":"2009-02-11","description":"TRANSFERASE"},{"title":"Crystal structure of reduced Ost6L","pdbId":"3G9B","date":"2009-02-13","description":"TRANSFERASE"},{"title":"Crystal structure of Ost6L (photoreduced form)","pdbId":"3GA4","date":"2009-02-16","description":"TRANSFERASE"},{"title":"Crystal structure of GAD1 from Arabidopsis thaliana","pdbId":"3HBX","date":"2009-05-05","description":"LYASE"},{"title":"Crystal structure of StSPL (symmetric form)","pdbId":"3MAD","date":"2010-03-23","description":"LYASE"},{"title":"Crystal structure of StSPL (asymmetric form)","pdbId":"3MAF","date":"2010-03-23","description":"LYASE"},{"title":"Crystal structure of StSPL in complex with phosphoethanolamine","pdbId":"3MAU","date":"2010-03-24","description":"LYASE"},{"title":"Crystal structure of StSPL - apo form, after treatment with semicarbazide","pdbId":"3MBB","date":"2010-03-25","description":"LYASE"},{"title":"Crystal structure of ScDPL1","pdbId":"3MC6","date":"2010-03-27","description":"LYASE"},{"title":"High-resolution structure of native Malus domestica ACC synthase","pdbId":"3PIU","date":"2010-11-08","description":"LYASE"},{"title":"Structure of the major type 1 pilus subunit FimA bound to the FimC chaperone","pdbId":"3SQB","date":"2011-07-05","description":"STRUCTURAL PROTEIN/CHAPERONE"},{"title":"EB1c/EB3c heterodimer in complex with the CAP-Gly domain of P150glued","pdbId":"3TQ7","date":"2011-09-09","description":"PROTEIN BINDING"},{"title":"Structure of the major type 1 pilus subunit FIMA bound to the FIMC (2.5 A resolution)","pdbId":"4DWH","date":"2012-02-24","description":"STRUCTURAL PROTEIN/CHAPERONE"},{"title":"E. coli thioredoxin variant with Pro76 as single proline residue","pdbId":"4HU7","date":"2012-11-02","description":"oxidoreductase"},{"title":"E. coli thioredoxin variant with (4S)-FluoroPro76 as single proline residue","pdbId":"4HU9","date":"2012-11-02","description":"oxidoreductase"},{"title":"E. coli thioredoxin variant with (4R)-FluoroPro76 as single proline residue","pdbId":"4HUA","date":"2012-11-02","description":"oxidoreductase"},{"title":"CRYSTAL STRUCTURE OF THE BOTULINUM NEUROTOXIN A RECEPTOR-BINDING DOMAIN IN COMPLEX WITH THE LUMINAL DOMAIN Of SV2C","pdbId":"4JRA","date":"2013-03-21","description":"HYDROLASE"},{"title":"Crystal structure of the complex formed by region of E. coli sigmaE bound to its -10 element non template strand","pdbId":"4LUP","date":"2013-07-25","description":"TRANSCRIPTION/DNA"},{"title":"Crystal structure of serine hydroxymethyltransferase from Psychromonas ingrahamii","pdbId":"4P3M","date":"2014-03-09","description":"TRANSFERASE"},{"title":"Crystal structure of LppA from Legionella pneumophila","pdbId":"4TVV","date":"2014-06-28","description":"HYDROLASE"},{"title":"Crystal structure of the mixed disulfide complex of thioredoxin-like TlpAs(C110S) and copper chaperone ScoIs(C74S)","pdbId":"4TXO","date":"2014-07-04","description":"OXIDODREDUCTASE/COPPER BINDING PROTEIN"},{"title":"Crystal structure of the mixed disulfide intermediate between thioredoxin-like TlpAs(C110S) and subunit II of cytochrome c oxidase CoxBPD (C233S)","pdbId":"4TXV","date":"2014-07-07","description":"PROTEIN BINDING"},{"title":"Apo-structure of the Y79F,W322E-double mutant of Etr1p","pdbId":"4W99","date":"2014-08-27","description":"OXIDOREDUCTASE"},{"title":"STRUCTURE OF THE ETR1P/NADP/CROTONYL-COA COMPLEX","pdbId":"4WAS","date":"2014-08-31","description":"OXIDOREDUCTASE"},{"title":"Crystal structure of the E. coli type 1 pilus subunit FimG (engineered variant with substitution Q134E; N-terminal FimG residues 1-12 truncated) in complex with the donor strand peptide DsF_T4R-T6R-D13N","pdbId":"5IQM","date":"2016-03-11","description":"CELL ADHESION"},{"title":"Crystal structure of the E. coli type 1 pilus subunit FimG (engineered variant with substitution Q134E; N-terminal FimG residues 1-12 truncated) in complex with the donor strand peptide DsF_SRIRIRGYVR","pdbId":"5IQN","date":"2016-03-11","description":"CELL ADHESION"},{"title":"Crystal structure of the E. coli type 1 pilus subunit FimG (engineered variant with substitutions Q134E and S138E; N-terminal FimG residues 1-12 truncated) in complex with the donor strand peptide DsF_T4R-T6R-D13N","pdbId":"5IQO","date":"2016-03-11","description":"CELL ADHESION"},{"title":"Complex structure between p60N/p80C katanin and a peptide derived from ASPM","pdbId":"5LB7","date":"2016-06-15","description":"HYDROLASE"},{"title":"Apo structure of p60N/p80C katanin","pdbId":"5NBT","date":"2017-03-02","description":"HYDROLASE"},{"title":"Crystal structure of VEGF-A in complex with VEGFR-1 domains D1-6","pdbId":"5T89","date":"2016-09-07","description":"TRANSFERASE"} | |
]; | |
</script> | |
<title>Guido's Structures</title> | |
</head> | |
<body> | |
<script> | |
var boxes; | |
var queue; | |
$(document).ready( function() { | |
var $row; | |
$row = $("<div/>", { | |
class:"row" | |
}).appendTo("#structures"); | |
boxes = {}; | |
for(var i=0;i<data.length-66;i++) { | |
// for(var i=0;i<10;i++) { | |
// if(i%9 == 0) { | |
// $row = $("<div/>", { | |
// class:"row" | |
// }).appendTo("#structures"); | |
// } | |
var box = createStructPanel($row,data[i]); | |
boxes[box.pdbId] = box; | |
} | |
queue = new StructureQueue(boxes); | |
// Click handlers | |
for( var pdbId in boxes) { | |
var box = boxes[pdbId]; | |
(function(box) { | |
box.$viewport | |
.click( function() { | |
queue.activate(box.pdbId); | |
}).on('mouseenter', (event) => { | |
var hoverTime = 200; //ms | |
box.lastEntered = event.timeStamp; | |
if(!box.active) { | |
// console.log("DEBUG entered"); | |
setTimeout( () => { | |
if(box.active) { | |
return; | |
} | |
if( box.lastEntered ) { | |
queue.activate(box.pdbId); | |
} | |
}, hoverTime); | |
} | |
}).on('mouseleave',(event) => { | |
// console.log("DEBUG left"); | |
box.lastEntered = undefined; | |
}); | |
//.on('mousemove', (event) => { | |
// activate if the mouse has hovered long enough | |
//}); | |
})(box); | |
} | |
// Activate everything sequentially | |
var q = Promise.resolve(); | |
for( var pdbId in boxes) { | |
//TODO Improve queue so that sequential activation isn't required | |
// (function(pdbId){q = q.then(() => queue.activate(pdbId))})(pdbId); | |
queue.activate(pdbId); | |
} | |
} ); | |
</script> | |
<div class="container"> | |
<div class="jumbotron"> | |
<h1>Structures by Guido Capitani</h1> | |
</div> | |
<div id="structures"></div> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment