Location: A review of cardiac cellular electrophysiology models @ f954e5918331 / dojo-presentation / js / dojo / dojox / image / Badge.js

Author:
David Nickerson <david.nickerson@gmail.com>
Date:
2021-09-16 00:41:19+12:00
Desc:
Updating Noble 1962 model: * Exposing the membrane potential to the top-level model; * adding SED-ML for the paced and pacemaker variants of the model. Using OpenCOR Snapshot release 2021-09-14.
Permanent Source URI:
https://models.fieldml.org/workspace/a1/rawfile/f954e59183314cd37f86c8832dc81317d01c8ec5/dojo-presentation/js/dojo/dojox/image/Badge.js

dojo.provide("dojox.image.Badge");
dojo.experimental("dojox.image.Badge");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.fx.easing");

dojo.declare("dojox.image.Badge", [dijit._Widget, dijit._Templated], {
	// summary: A simple grid of Images that loops through thumbnails
	//

	baseClass: "dojoxBadge",
	
	templateString:'<div class="dojoxBadge" dojoAttachPoint="containerNode"></div>',

	// children: String
	// 		A CSS3 Selector that determines the node to become a child
	children: "div.dojoxBadgeImage",

	// rows: Integer
	//		Number of Rows to display
	rows: 4,
	
	// cols: Integer
	//		Number of Columns to display 
	cols: 5,
	
	// cellSize: Integer
	//		Size in PX of each thumbnail
	cellSize: 50,
	
	// delay: Integer
	//		Time (in ms) to show the image before sizing down again
	delay: 2000,
	
	// threads: Integer
	//		how many cycles will be going "simultaneously" (>2 not reccommended)
	threads: 1,
	
	// easing: Function|String
	//		An easing function to use when showing the node (does not apply to shrinking)
	easing: "dojo.fx.easing.backOut",
	
	startup: function(){
		if(this._started){ return; }
		if(dojo.isString(this.easing)){
			this.easing = dojo.getObject(this.easing);
		}
		this.inherited(arguments);
		this._init();
	},
	
	_init: function(){
		// summary: Setup and layout the images
	
		var _row = 0, 
			_w = this.cellSize; 

		dojo.style(this.domNode, {
			width: _w * this.cols + "px",
			height: _w * this.rows + "px"
		});

		this._nl = dojo.query(this.children, this.containerNode)
			.forEach(function(n, _idx){

				var _col = _idx % this.cols,
					t = _row * _w,
					l = _col * _w;
			
				dojo.style(n, {
		 			top: t + "px",
		 			left: l + "px",
					width: _w - 2 + "px",
					height: _w - 2 + "px"
		 		});

				if(_col == this.cols - 1){ _row++; }
				dojo.addClass(n, this.baseClass + "Image");
				
			}, this);
		;
		
		var l = this._nl.length;
		while(this.threads--){
			var s = Math.floor(Math.random() * l);
			setTimeout(dojo.hitch(this,"_enbiggen", { target: this._nl[s] }), this.delay * this.threads);
		}
		
	},
	
	_getCell: function(/* DomNode */ n){
		// summary: Return information about the position for a given node
		var _pos = this._nl.indexOf(n);
		if(_pos >= 0){
			var _col = _pos % this.cols;
			var _row = Math.floor(_pos / this.cols);
			return { x: _col, y: _row, n: this._nl[_pos], io: _pos };
		}else{
			return undefined;
		}
	},
	
	_getImage: function(){
		// summary: Returns the next image in the list, or the first one if not available
		return "url('')";
	},
	
	_enbiggen: function(/* Event|DomNode */ e){
		// summary: Show the passed node in the picker
		var _pos = this._getCell(e.target || e);

		if (_pos){
			// we have a node, and know where it is

			var _cc = (this.cellSize * 2) - 2; 
			var props = {
				height: _cc,
				width: _cc
			};
			
			var _tehDecider = function(){
				// if we have room, we'll want to decide which direction to go
				// let "teh decider" decide.
				return Math.round(Math.random()); 
			};
			
			if(_pos.x == this.cols - 1 || (_pos.x > 0 && _tehDecider() )){
				// we have to go left, at right edge (or we want to and not on left edge)
				props.left = this.cellSize * (_pos.x - 1);
			}
			
			if(_pos.y == this.rows - 1 || (_pos.y > 0 && _tehDecider() )){
				// we have to go up, at bottom edge (or we want to and not at top)
				props.top = this.cellSize * (_pos.y - 1);
			}

			var bc = this.baseClass;
			dojo.addClass(_pos.n, bc + "Top");
			dojo.addClass(_pos.n, bc + "Seen");

			dojo.animateProperty({ node: _pos.n, properties: props,
				onEnd: dojo.hitch(this, "_loadUnder", _pos, props),
				easing: this.easing 
			}).play();
			
		}
	},
	
	_loadUnder: function(info, props){
		// summary: figure out which three images are being covered, and 
		//		determine if they need loaded or not

		var idx = info.io;
		var nodes = [];

		var isLeft = (props.left >= 0);
		var isUp = (props.top >= 0);
		
		var c = this.cols,
			// the three node index's we're allegedly over:
			e = idx + (isLeft ? -1 : 1),
			f = idx + (isUp ? -c : c),
			// don't ask:
			g = (isUp ? (isLeft ? e - c : f + 1) : (isLeft ? f - 1 : e + c)),

			bc = this.baseClass;
		
		dojo.forEach([e, f, g], function(x){
			var n = this._nl[x];
			if(n){
				if(dojo.hasClass(n, bc + "Seen")){
					// change the background image out?
					dojo.removeClass(n, bc + "Seen");
				}
			}
		},this);
		
		setTimeout(dojo.hitch(this, "_disenbiggen", info, props), this.delay * 1.25);

	},
	
	_disenbiggen: function(info, props){
		// summary: Hide the passed node (info.n), passing along properties
		//		received.
		
		if(props.top >= 0){
			props.top += this.cellSize;
		}
		if(props.left >= 0){
			props.left += this.cellSize; 
		}
		var _cc = this.cellSize - 2;
		dojo.animateProperty({
			node: info.n, 
			properties: dojo.mixin(props, {
				width:_cc, 
				height:_cc
			}),
			onEnd: dojo.hitch(this, "_cycle", info, props)
		}).play(5);
	},
	
	_cycle: function(info, props){
		// summary: Select an un-viewed image from the list, and show it

		var bc = this.baseClass; 
		dojo.removeClass(info.n, bc + "Top");
		var ns = this._nl.filter(function(n){
			return !dojo.hasClass(n, bc + "Seen")
		});
		var c = ns[Math.floor(Math.random() * ns.length)];
		setTimeout(dojo.hitch(this,"_enbiggen", { target: c }), this.delay / 2)

	}
	
});