pdb-web-components
Version:
140 lines (128 loc) • 15.9 kB
JavaScript
(function (exports) {
;
const selector=d=>d.response.docs[0];
const supportedSizes=new Set([36,48,64,128]);
const organismMap=new Map([['dinophyceae','algae'],['embryophyta','plant'],['streptophyta','plant'],['saccharomyces cerevisiae','yeast'],['saccharomyces','yeast'],['drosophila','fly'],['gallus gallus','chicken'],['homo sapiens','human'],['sus scrofa','pig'],['bos taurus','cow'],['mus musculus','mouse'],['rattus','rat'],['rat','rat'],['mammalia','mammal'],['fungi','fungi'],['ascomycota','fungi'],['viruses','virus'],['bacteria','bacteria'],['archaea','archaea'],['eukaryota','eukaryote'],['synthetic constructor','artificial']]);
const categoryUrls=new Map([['PrimaryCitation',{url:'citations',responseData(d){return d.citation_year?'published':'unpublished'},title(d){return'published'===d?'A paper describing this entry has been published':'unpublished'===d?'The PDB does not have any information about a published paper describing this entry':'This icon conveys information about whether or not a paper describing this entry has been published'}}],['Taxonomy',{url:'analysis',responseData(d){const e=d.entry_organism_scientific_name;// If not all the same
if(1<new Set(e).size)return'multiple';// Get from organism map variable;
const f=organismMap.get(e[0].split('|')[0].toLowerCase());return f||'other'},title(d){return'artificial'===d?'The biomacromolecules in this entry were artificially designed':'other'===d?'Information about the source organism of the biomacromolecules in this entry can be obtained by clicking on the icon':'multiple'===d?'The biomacromolecules in this entry derive from multiple organisms':'fly'===d?'The source organism of the biomacromolecules in this entry is fruit-fly':'CGIlogoUnknown'===d?'This icon conveys information about the source organism of the biomacromolecules in this entry':'The source organism of the biomacromolecules in this entry is '+d}}],['Expressed',{url:'analysis',responseData(d){const e=d.sample_preparation_method;if(!e){const f=d.entry_organism_scientific_name;return f.toLowerCase().contains('synthetic construct')?'synthetic':'CGIlogoUnknown'}// If not all the same
if(1<new Set(e).size)return'multiple';switch(e[0].toLowerCase()){case'engineered':return'expressed';case'synthetic':return'synthetic';case'natural':return'purified';default:return'other';}},title(d){switch(d){case'expressed':return'The sample of the biomacromolecules in this entry was obtained by expression and purification';case'synthetic':return'The sample of the biomacromolecules in this entry was obtained by chemical synthesis';case'purified':return'The sample of the biomacromolecules in this entry was extracted and purified from a biological source';case'multiple':return'The sample of the biomacromolecules in this entry was obtained using multiple techniques';case'other':return'The sample of the biomacromolecules in this entry was obtained using techniques other than expression, chemical synthesis or extraction from a biological source';case'CGIlogoUnknown':return'This icon conveys information about the production techniques used to obtain the biomacromolecular samples for this entry';default:throw new Error('Something wrong happened');}}}],['Experimental',{url:'experiment',responseData(d){let e;switch(d.experimental_method[0].toLowerCase()){case'x-ray diffraction':e='xray';break;case'solution nmr':case'solid-state nmr':e='nmr';break;case'electron microscopy':e='em';break;default:return'other';}return 1!==d.experimental_method.length&&(e='hybrid'),'y'!==d.experiment_data_available&&(e+='NoData'),e},title(d){let e;switch(d.replace('NoData','')){case'xray':e='The structure was determined using X-ray crystallography';break;case'nmr':e='The structure was determined using NMR spectroscopy';break;case'em':e='The structure was determined using Electron Microscopy';break;case'multiple':e='The structure was determined using Electron Crystallography';break;case'extal':e='The sample of the biomacromolecules in this entry was obtained using techniques other than expression, chemical synthesis or extraction from a biological source';break;case'hybrid':e='The structure was determined using a hybrid technique';break;case'other':e='The structure was determined using a technique other than X-ray, NMR, EM, or a hybrid thereof';break;default:return'This icon conveys information about the structure-determination technique for this entry';}return`${e} (${d.endsWith('NoData')?'no ':''}experimental data available)`}}],['Protein',{url:'analysis',responseData(d){return d.number_of_protein_chains?'present':'absent'},title(d){switch(d){case'present':return'This entry contains protein';case'absent':return'This entry does not contain protein';case'CGIlogoUnknown':return'This icon conveys information about the presence of protein in the entry';default:throw new Error('Something bas happened');}}}],['NucleicAcid',{url:'analysis',responseData(d){const e=d.number_of_RNA_chains||d.number_of_DNA_chains;return e?'present':'absent'},title(d){switch(d){case'present':return'This entry contains nucleic acid (DNA, RNA)';case'absent':return'This entry does not contain nucleic acid (DNA, RNA)';case'CGIlogoUnknown':return'This icon conveys information about the presence of nucleic acid (DNA, RNA) in the entry';default:throw new Error('Something bas happened');}}}],['Ligands',{url:'ligands',responseData(d){return d.number_of_bound_entities?'present':'absent'},title(d){switch(d){case'present':return'This entry contains one or more ligands';case'absent':return'This entry does not contain any ligand';case'CGIlogoUnknown':return'This icon conveys information about the presence of ligands in the entry';default:throw new Error('Something bas happened');}}}]]);// Unique id, for each instance, used for namespacing
let uniqueId=1;const categories=new Set(categoryUrls.keys());// Custom Element definition
class PdbPrints$1 extends HTMLElement{static get observedAttributes(){return['orientation','size','include','exclude']}_handleLoadEvent(d){this.data=selector(d.detail.payload);}_render(){if(this.data){const d=this.data.entry_entity.slice(0,4),e=`${this.size}px`;this.shadowRoot||(this.attachShadow({mode:'open'}),this.classList.add(this._namespace));const f=`
<style>
:host {
font-family: "Courier New";
font-size: ${this.size/3}px;
font-weight: bold;
display: inline-block;
overflow: hidden;
}
:host a {
text-decoration: none;
cursor: pointer;
}
:host > .root {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
${'horizontal'===this.orientation?`-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;`:`-ms-flex-direction: column;
flex-direction: column;`};
}
:host > .root > * {
height: ${e};
width: ${e};
}
:host > .root > span {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
:host > .root > a {
border-radius: 10%;
background-color: #81C16E;
background-color: var(--theme-color, #81C16E);
}
</style>
`.trim();(this.shadyRoot||this.shadowRoot).innerHTML=`
${this.shadyRoot?f.replace(/:host/g,`.${this._namespace}`):f}
<span class="root">
<span>
<a
title="${'For more information about key features of this entry, click on the individual icons'}"
href="//www.ebi.ac.uk/pdbe/entry/pdb/${d}/"
>
${d}
</a>
<a title="pdbe.org" href="//www.ebi.ac.uk/pdbe">
<img
src="//www.ebi.ac.uk/pdbe/widgets/html/PDBeWatermark_horizontal_${this.size}.png"
>
</a>
</span>
${[...categoryUrls.entries()].filter(([g])=>this._include.has(g)&&!this._exclude.has(g)).map(([g,{url:h,responseData:i,title:j}])=>{const k=i(this.data),l=j(k);return`
<a
href="//www.ebi.ac.uk/pdbe/entry/pdb/${d}/${h}"
title="${l}"
>
<img
src="//www.ebi.ac.uk/pdbe/widgets/pdblogos/transparent/${this.size}/${g}_${k}.png"
alt="${l}"
>
</a>
`.trim()}).join('')}
</span>
`.trim();}// If first render
}_planRender(){this._plannedRender||(this._plannedRender=!0,requestAnimationFrame(()=>{this._plannedRender=!1,this._render();}));}// Getters/Setters
// data
get data(){return this._data}set data(d){this._data=d,this._planRender();}// orientation
get orientation(){return this._orientation}set orientation(d){let e;switch(d.toLowerCase()[0]){case'v':e='vertical';break;case'h':e='horizontal';break;default:throw new Error(`${d} is not a supported orientation`);}this._orientation=e,this.setAttribute('orientation',e),this._planRender();}// size
get size(){return this._size}set size(d){// Parses to number, accepts strings with px unit
let e=+`${d}`.toLowerCase().replace('px','');// If not a valid number, or had a non-px unit, throws
if(isNaN(e))throw new Error(`${d} is not a supported size`);// If not a supported size, finds closest supported one to use instead
supportedSizes.has(e)||(e=[...supportedSizes].sort((f,g)=>Math.abs(f-e)-Math.abs(g-e))[0],console.warn(`${d} is not a supported value, setting to closest one: ${e}`)),this._size=e,this.setAttribute('size',`${e}px`),this._planRender();}// include
get include(){return[...this._include]}set include(d){let e=d;// If falsy value, sets to empty array
e||(e=[]),'string'==typeof e&&(e=e.replace(/[[\]'"]/m).split(/\s*,\s*/)),e=e.filter(f=>categories.has(f)),e.length?(this._include=new Set(e),this.setAttribute('include',e.join(' '))):(this._include=new Set(categories),this.removeAttribute('include')),this._planRender();}// exclude
get exclude(){return[...this._exclude]}set exclude(d){let e=d;// If falsy value, sets to empty array
e||(e=[]),'string'==typeof e&&(e=e.replace(/[[\]'"]/m).split(/\s*,\s*/)),e=e.filter(f=>categories.has(f)),this._exclude=new Set(e),e.length?this.setAttribute('exclude',e.join(' ')):this.removeAttribute('exclude'),this._planRender();}// Custom element actions
constructor(){super(),this._data=null,this._orientation='horizontal',this._size=36,this._include=new Set(categories),this._exclude=new Set,this._handleLoadEvent=this._handleLoadEvent.bind(this),this._planRender=this._planRender.bind(this),this._render=this._render.bind(this),this._namespace=`${this.tagName.toLowerCase()}-${uniqueId++}`;}connectedCallback(){this.addEventListener('load',this._handleLoadEvent);}disconnectedCallback(){this.removeEventListener('load',this._handleLoadEvent);}attributeChangedCallback(d,e,f){e===f||(this[d]=f);}}
const pdbIdPattern=/^[A-Z0-9]{4}$/;
const idToUrl=(a=>b=>`${a}&q=pdb_id:(${b.toLowerCase()})`)(`
//www.ebi.ac.uk/pdbe/search/pdb/select?
fl=pdb_id,organism_synonyms,number_of_bound_entities%2C+
number_of_protein_chains%2Cexperimental_method%2C+
experiment_data_available%2Cexpression_host_sci_name%2C+citation_year%2C+
entry_organism_scientific_name,number_of_RNA_chains,number_of_DNA_chains,
sample_preparation_method,emdb_id&wt=json
`.trim().replace('\n',''));class PdbDataLoader$1 extends HTMLElement{static get observedAttributes(){return['pdbid']}_render(){const a=this.pdbid,b=this.querySelectorAll('source');// Clean up the DOM
var _iteratorNormalCompletion=!0,_didIteratorError=!1,_iteratorError=void 0;try{for(var _step,_iterator=b[Symbol.iterator]();!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=!0){const e=_step.value;e.parentElement.removeChild(e);}// If no ID, skip
}catch(err){_didIteratorError=!0,_iteratorError=err;}finally{try{!_iteratorNormalCompletion&&_iterator.return&&_iterator.return();}finally{if(_didIteratorError)throw _iteratorError}}if(a){// We have an ID, add or modify a data-loader element to fetch the data
const c=document.createElement('source');c.src=idToUrl(a);let d=this.querySelector(PdbDataLoader$1.dataLoaderElementName);// If no data loader yet, create and add it
d?d.appendChild(c):(d=document.createElement(PdbDataLoader$1.dataLoaderElementName),d.appendChild(c),this.appendChild(d));}}_planRender(){// If render is already planned, skip
this._plannedRender||(this._plannedRender=!0,requestAnimationFrame(()=>{this._plannedRender=!1,this._render();}));}// Getters/Setters
// pdbid
get pdbid(){return this._pdbid}set pdbid(a){const b=(a||'').trim().toUpperCase();if(b&&!pdbIdPattern.test(b))throw new Error(`${a} is not a valid PDB ID`);this._pdbid=b||null,this._pdbid?(this.setAttribute('pdbid',this.pdbid),this._planRender()):this.removeAttribute('pdbid');}// Custom element reactions
constructor(){super(),this._pdbid=null,this._planRender=this._planRender.bind(this),this._render=this._render.bind(this);}connectedCallback(){this._planRender();}disconnectedCallback(){this._plannedRender=!1;}attributeChangedCallback(a,b,c){b===c||(this[a]=c);}}PdbDataLoader$1.dataLoaderElementName='data-loader';
function _asyncToGenerator(fn){return function(){var gen=fn.apply(this,arguments);return new Promise(function(resolve,reject){function step(key,arg){try{var info=gen[key](arg),value=info.value;}catch(error){return void reject(error)}return info.done?void resolve(value):Promise.resolve(value).then(function(value){step('next',value);},function(err){step('throw',err);})}return step('next')})}}const observerConfig={childList:!0}; const getSourceUrls=({children:a})=>[...a].filter(b=>'SOURCE'===b.tagName&&b.src).map(b=>b.src);class DataLoader extends HTMLElement{_fetch(){var _this=this;return _asyncToGenerator(function*(){const a=getSourceUrls(_this);if(a.length){let b=[],c=!0;var _iteratorNormalCompletion=!0,_didIteratorError=!1,_iteratorError=void 0;try{for(var _step,_iterator=a[Symbol.iterator]();!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=!0){const d=_step.value;try{const e=yield fetch(d);b=yield e.json(),c=!1;break}catch(e){b.push(e);}}}catch(err){_didIteratorError=!0,_iteratorError=err;}finally{try{!_iteratorNormalCompletion&&_iterator.return&&_iterator.return();}finally{if(_didIteratorError)throw _iteratorError}}_this.dispatchEvent(new CustomEvent(c?'error':'load',{detail:b,bubbles:!0})),_this._data=c?null:b;}})()}_planFetch(){// If fetch is already planned, skip the rest
this._plannedFetch||(this._plannedFetch=!0,this._data=null,setTimeout(()=>{this._plannedFetch=!1,this._fetch();},0));}// Getters/Setters
// data
get data(){return this._data}// loaded
get loaded(){return!!this.data}// Custom element reactions
constructor(){super(),this._src=null,this._data=null,this._observer=new MutationObserver(()=>this._planFetch()),this._selector=this.querySelectorAll('source');}connectedCallback(){this._observer.observe(this,observerConfig),this._planFetch();}disconnectedCallback(){this._plannedFetch=!1,this._observer.disconnect(this);}}
window.customElements&&(customElements.define('pdb-prints',PdbPrints$1),customElements.define('pdb-data-loader',PdbDataLoader$1),customElements.define('data-loader',DataLoader));const PdbDataLoader=PdbDataLoader$1;const PdbPrints=PdbPrints$1;
exports.PdbDataLoader = PdbDataLoader;
exports.PdbPrints = PdbPrints;
}((this.PDBWebComponents = this.PDBWebComponents || {})));
//# sourceMappingURL=index.js.map