Template:UCAS-China/igemUCAS.js

/*!

* igemUCAS JavaScript Library v0.18.1
* Copyright UCAS iGEM team
*/

( function( global, factory ) { var iU = global.iU = factory(global); iU(); } ) (window, function( window ) { var document = window.document, inspect = (function(){ var strErr = "igemUCAS v0.18.19\n", nextseq = 1, error = function( location, desc ){ strErr = strErr.concat(nextseq, " ", location, ": ", desc, '\n'); nextseq ++; }, garrison = function( name ){ var f = { string: function( s ){ if( (!s) || typeof s != 'string' ) error(name, "parameter should be of ."); return f; }, number: function( s ){ if( (!s) || typeof s != 'number' ) error(name, "parameter should be of number type."); return f; }, keyUnused: function(obj, key){ if( obj[key] ) error(name, "key "+key+" has been used."); return f; }, assert: function( val, desc ){ if( !val ) error(name, desc ); return f; } }; return f; };

garrison.displayErrors = function(){ if(strErr.length == 0 ) console.log("No errors, Congrats!") else console.log( strErr ); }; garrison.root_not_found = function(){ console.log("DIV igemUCAS does not exist."); garrison.displayErrors(); }; garrison.gl_not_supported = function(){ console.log("WebGL is not supported."); } return garrison; })(),

getUid = (function(){ var now = -1; return function(){ now ++; return (function(n){ return '_'+n+'_'; })(now); }; })(),

configs = { defSpan: 3, scriptPadding: 20, topBlank: 60 };

function css( elem, styles ){ if( !(elem && styles) ) return ;

for(var prop in styles){ var key = "", change = false;

for(var j = 0; j < prop.length; j ++){ if( prop[j] == '-' ) change = true; else{ key += change ? prop[j].toUpperCase() : prop[j]; change = false; } }

if( typeof styles[ prop ] == "function" ) elem.addEventListener(key, styles[prop]); else elem.style[ key ] = styles[ prop ]; } } function Component( node, cls, width, padding ){ if( typeof node == "string" ){ this.elem = document.createElement(node); this.elem.style.visibility = "hidden"; this.elem.wait = true; } else this.elem = node;

this.elem.id = getUid(); Component.prototype.iU_book.appendChild(this.elem);

this.padding = padding || 0; this.width = width - 2*this.padding;

if(cls) this.elem.className = cls;

if( this.elem.wait ) this.state = "wait"; else this.loaded(); } Component.prototype = { constructor: Component, loaded: function(){ css(this.elem,{"width": this.width+"px"}); this.height= this.elem.offsetHeight; this.state = "unused"; }, place: function(left, top){ this.left = left; this.top = top; this.state= "used"; }, render: function( offsetX ){ css(this.elem, { "position": "absolute", "left": (offsetX+this.left) +"px", "top": this.top +"px", "visibility": "visible" }); }, toString: function(){ return "["+this.elem.tagName.toLowerCase() +"] "+ this.elem.innerHTML.substr(0,50)+"\n"; } };

function Flow( seq, width, height, top ){ this.seq = seq;

this.width = width; this.height = height; this.top = top;

this.page = 0; this.frontier = 0; this.reserve = 0; this.usedW = 0;

this.comps = []; this.buffer = []; this.isVisible = true; } Flow.prototype = { constructor: Flow, operate: function(){ var pause = false; while( !pause && this.buffer.length > 0 ){ switch( this.buffer[0].state ){ case "dispose": this.buffer.shift(); break;

case "pause": if( this.buffer[0].state == "wait" ){ pause = true; break; } case "unused": var comp = this.buffer.shift();

if( this.page == 0 ) this.page = 1; else if( this.usedW == 0 || this.usedW + comp.width > this.width ){ if( this.frontier + comp.height > this.height ){ this.page += 1; this.frontier = 0; } this.reserve = this.frontier; this.usedW = 0; }

comp.place(this.width * (this.page-1) + this.usedW + comp.padding, this.reserve + this.top); comp.state = "used";

this.usedW += comp.width; this.frontier = Math.max( this.frontier, this.reserve+comp.height );

this.comps.push( comp ); } } }, hide: function(){ if( this.isVisible ) for(var i = 0, i_len = this.comps.length; i < i_len; i ++) this.comps[ i ].elem.style["visibility"] = "hidden";

this.isVisible = false; }, getBreadth: function(){ return this.page * this.width; }, render: function( offsetX ){ this.isVisible = true; this.operate();

for(var i = 0, i_len = this.comps.length; i < i_len; i ++) this.comps[ i ].render( offsetX ); } };

function Book( iU_root, nav ){ this.interface = document.createElement("div"); this.interface.id = "iU_book"; this.nav = nav;

iU_root.parentNode.appendChild( this.interface ); Component.prototype.iU_book = this.interface;

this.flows = []; this.buffer = []; this.nowFlow = null; this.counter = 0;

this.nav = undefined; this.width = 0; this.height = this.interface.clientHeight;

var _this = this; this.offset = 0; this.scroll = function( ev ){ ev = ev || window.event; if( ev.preventDefault ) ev.preventDefault();

_this.offset -= ev.wheelDelta || ev.detail || 0; _this.offset = Math.max(_this.offset, 0); var accum = 0; for(var i = 0; i < _this.flows.length; i ++){ _this.flows[i].render( accum - _this.offset ); accum += _this.flows[i].getBreadth(); } } } Book.prototype = { constructor: Book, alloc: function( span ){ this.buffer.push(new Flow( this.counter++, Math.round(window.innerWidth * span / 9), this.height - configs.topBlank, configs.topBlank ) ); }, forward: function(){ if( this.buffer.length == 0 ) this.alloc( configs.defSpan ); this.nowFlow = this.buffer.shift(); this.flows.push(this.nowFlow); return this.nowFlow; }, append: function( node ){ switch( ((node||{}).tagName||"").toLowerCase() ){ case "p": case "span": this.script(node); break; case "b": this.title(node); break; case "img": case "video": this.image(node); break; case "dfn": this.special(node);break; case "pre": this.formula(node); break; default: node.parentNode.removeChild(node); break; } }, script: function( node ){ var target = this.nowFlow || this.forward(); for(var i = 0, i_len = node.childNodes.length; i < i_len; i ++){ var e = node.childNodes[i]; if( !e.attributes ){ var child = document.createElement("span"); child.className = "script"; child.innerHTML = e.textContent; node.replaceChild(child, e); } } target.buffer.push( new Component(node, "script", target.width, configs.scriptPadding )); }, title: function( node ){ var target = this.forward(); target.buffer.push( new Component(node, "title", target.width, configs.scriptPadding )); }, image: function( node ){ var target = this.nowFlow || this.forward(), box = document.createElement("div"), comp = new Component(node, "title", target.width, configs.scriptPadding ); node.comp = comp; target.buffer.push( comp ); }, special:function( node ){ node.parentNode.removeChild(node); }, formula: function( node ){ node.parentNode.removeChild(node); } };

function NaviBar( iU_root, logo, sponsors ){ this.surface = document.createElement("div"); iU_root.parentNode.appendChild( this.surface );

this.headings = []; this.init(logo, sponsors);

this.fstNow = 0; this.secNow = 0; this.subheading= null; } NaviBar.prototype = { constructor: NaviBar, init: function( logo, sponsors ){ this.surface.id = "NaviBar"; this.header = document.createElement("div"); this.header.id = "header";

logo.id = "logo"; this.header.appendChild( logo );

this.ptrH = document.createElement("div"), this.ptrH.id = "heading pointer"; this.ptrH.className = "arrow"; css(this.ptrH,{ "visibility": "hidden", "position": "absolute" }); this.header.appendChild( this.ptrH );


this.ptrS = document.createElement("div"); this.ptrS.id = "subheading pointer"; this.ptrS.className = "arrow"; css(this.ptrS,{ "visibility": "hidden", "position": "absolute" }); this.header.appendChild( this.ptrS );

this.surface.appendChild( this.header);

var footer = document.createElement("div"); footer.id = "footer"; this.surface.appendChild(footer);

var strSponsors = document.createElement("span"); strSponsors.innerHTML = "Sponsors"; strSponsors.id = "strSponsors"; footer.appendChild(strSponsors);

for(var i = 0; i < sponsors.length; i ++){ sponsors[i].className = "sponsor"; footer.appendChild(sponsors[i]); } }, jumpTo: function( path ){ if( !path ) return false;

var tarF, tarS; if( typeof path == "string" ){ var sep = path.split(/\s*\.\s*/); if( !sep[0] ) return false;

var fst = sep[0].toUpperCase(), h = this.headings, s = null;

for(var i = 0; i < h.length; i ++){ if( h[i].innerHTML == fst ){ tarF = i; s = h[i]._catalog.children; } } if( !s ) return false;

if(sep[1]){ var sec = sep[1].toUpperCase(); for(var i = 0; i < s.length; i ++) if( s[i].innerHTML == sec ) tarS = i; } else tarS = 0; } else{ tarF = path[0]; tarS = path[1]; if(!(tarF === +tarF && tarS === +tarS)) return false; }

var fstElem = this.headings[ tarF ], t = fstElem.offsetTop + fstElem.clientHeight - 3, l = fstElem.offsetLeft + fstElem.clientWidth*0.5 - 5;

css(this.ptrH,{ "top": Math.round(t) + "px", "left": Math.round(l) + "px", "visibility": "visible" });

if(this.subheading) this.subheading.className = "HiddenCatalog";

this.subheading = h[ tarF ]._catalog; this.subheading.className = "VisibleCatalog"

return true; }, addPath: function( path, jumpFunc ){ var sep = path.split(/\s*\.\s*/); if( !(sep[0] && sep[1]) ) return false;

var fst = sep[0].toUpperCase(), sec = sep[1].toUpperCase(), _this = this, h = this.headings, target = null;

for(var i = 0; i < h.length; i ++) if( h[i].innerHTML == fst ) target = h[i];

if( !target ){ target = document.createElement("span"); target.className = "H1"; target.innerHTML = fst;

target._catalog = document.createElement("div"); target._catalog.className = "HiddenCatalog"; this.header.appendChild(target._catalog);

target.addEventListener("mousedown",(function(fst, target){ return function(){ _this.jumpTo( fst ); if(_this.subheading) _this.subheading.className = "HiddenCatalog";

_this.subheading = target._catalog; _this.subheading.className = "VisibleCatalog"; }; })(fst, target) );

this.header.appendChild(target); this.headings.push(target);

var accum = [ 0 ]; for(var i = 0; i < this.headings.length; i ++) accum[i+1] = accum[i] + this.headings[i].clientWidth + 60;

var left = Math.round(window.innerWidth * 0.6 - accum.pop()/2); for(var i = 0; i < this.headings.length; i ++) css(this.headings[i],{ "left": (left + accum[i]) + "px" }); }

var s = target._catalog.children; for(var i = 0; i < s.length; i ++) if( s[i].innerHTML == sec ){ s[i]._jumpFunc = jumpFunc; return true; }

var subheading = document.createElement("span"); subheading.className = "H2"; subheading.innerHTML = sec; subheading._jumpFunc = jumpFunc; subheading.addEventListener("mouseover",function(){ _this.jumpTo( path ); }); target._catalog.appendChild(subheading);

var accum = [ 0 ]; for(var i = 0; i < s.length; i ++) accum[i+1] = accum[i] + s[i].clientWidth + 60;

var left = Math.round(window.innerWidth * 0.6 - accum.pop()/2); for(var i = 0; i < s.length; i ++) css(s[i],{ "left": (left + accum[i]) + "px" }); return true; } };

function Loader( iU_root, cover ){ this.boot = document.createElement("div"); this.boot.id = "loader"; iU_root.parentNode.appendChild( this.boot );

this.total = 0; this.loaded = 0; this.failed = 0;

var _this = this; this.load = function( img ){ if( !img.height ){ img.onload = function(){ _this.loaded ++; if(img.comp) img.comp.state = "unused"; }; img.onerr = function(){ _this.failed ++; if(img.comp) img.comp.state = "dispose"; }; img.wait = true; _this.total ++; } }; } Loader.prototype.constructor = Loader;

var fn = { initRoot: function( overflow ){ var iU_root = document.getElementById("igemUCAS");

if( !iU_root ) return null;

iU_root.style.visibility = "hidden"; iU_root.style["z-index"] = "-100";


inspect("fn.initRoot").assert(iU_root, ""); return iU_root; }, initWebGL: function( iU_root ){ var canvas = document.createElement("canvas");

canvas.id = "bgCanvas"; canvas.width = window.innerWidth; canvas.height = window.innerHeight; iU_root.parentNode.appendChild(canvas);

var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

if(gl) css(canvas, { "position":"absolute", "top":"0", "left":"0", "z-index":"-90", "overflow":"hidden", "visibility":"visible" });

return gl; }, initBase: function( iU_root ){ var iU_base = document.createElement("div"); iU_base.id = "UCASigem"; iU_base.style.position = "absolute";

iU_root.parentNode.appendChild(iU_base); return iU_base; } };

function igemUCAS(){ var iU_root = fn.initRoot(); if( !iU_root ) return inspect.root_not_found();

var gl = fn.initWebGL( iU_root ); if( !gl ) inspect.gl_not_supported();

var icons = iU_root.children[0].children; cover = icons[0], logo = icons[1], sponsors = []; iU_root.removeChild(iU_root.children[0]); for(var i = 2; i < icons.length; i ++) sponsors.push( icons[i] );

var loader = new Loader ( iU_root, cover ), nav = new NaviBar( iU_root, logo, sponsors ); book = new Book( iU_root, nav );

for(var i = 0; i < icons.length; i ++) loader.load(icons[i]);

nav.addPath("project.description"); nav.addPath("project.light to color"); nav.addPath("project.light to odor"); nav.addPath("project.sound to light"); nav.addPath("results.overview"); nav.addPath("results.the rose!"); nav.addPath("results.hardware"); nav.addPath("results.software"); nav.addPath("results.proof & demonstrate"); nav.addPath("results.model"); nav.addPath("results.parts"); nav.addPath("human practice.gift for the world"); nav.addPath("human practice.integrated human practice"); nav.addPath("human practice.public engagement"); nav.addPath("human practice.expert interviews"); nav.addPath("human practice.safety & security"); nav.addPath("human practice.education"); nav.addPath("human practice.collaborations"); nav.addPath("people.meet the team"); nav.addPath("people.arrtibutions"); nav.addPath("people.medal achievement"); nav.addPath("people.notebook");

nav.jumpTo("human practice.safety & security");

while( iU_root.children.length > 0 ){ var node = iU_root.children[0]; node.style.visibility = "hidden"; if( (node||{}).tagName == "IMAGE" ) loader.load(node); book.append( node ); }

document.addEventListener("DOMMouseScroll", book.scroll, false); window.onmousewheel = document.onmousewheel = book.scroll; book.scroll( {wheelDelta: 0} ); inspect.displayErrors(); } return igemUCAS; });