=== File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js === Object.K = function(x) {return x;}; >>> Object.extend = function(destination, source) { >>> for (var property in source) { >>> destination[property] = source[property]; } >>> return destination; }; >>> Object.extend(Object, { --- inspect: function(object) { --- try { --- if (Object.isUndefined(object)) return 'undefined'; --- if (object === null) return 'null'; --- return object.inspect ? object.inspect() : String(object); --- } catch (e) { --- if (e instanceof RangeError) return '...'; --- throw e; --- } }, --- toJSON: function(object) { --- var type = typeof object; --- switch (type) { case 'undefined': case 'function': --- case 'unknown': return; --- case 'boolean': return object.toString(); } --- if (object === null) return 'null'; --- if (object.toJSON) return object.toJSON(); --- if (Object.isElement(object)) return; --- var results = []; --- for (var property in object) { --- var value = Object.toJSON(object[property]); --- if (!Object.isUndefined(value)) --- results.push(property.toJSON() + ': ' + value); } --- return '{' + results.join(', ') + '}'; }, --- toQueryString: function(object) { --- return $H(object).toQueryString(); }, --- toHTML: function(object) { --- return object && object.toHTML ? object.toHTML() : String.interpret(object); }, --- keys: function(object) { --- var keys = []; --- for (var property in object) --- keys.push(property); --- return keys; }, --- values: function(object) { --- var values = []; --- for (var property in object) --- values.push(object[property]); --- return values; }, --- clone: function(object) { --- return Object.extend({ }, object); }, --- isElement: function(object) { --- return object && object.nodeType == 1; }, --- isArray: function(object) { --- return object != null && typeof object == "object" && 'splice' in object && 'join' in object; }, --- isFunction: function(object) { --- return typeof object == "function"; }, --- isString: function(object) { --- return typeof object == "string"; }, --- isNumber: function(object) { --- return typeof object == "number"; }, --- isUndefined: function(object) { --- return typeof object == "undefined"; } }); >>> Object.extend(Function.prototype, { --- argumentNames: function() { --- var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); --- return names.length == 1 && !names[0] ? [] : names; }, --- bind: function() { --- if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; --- var __method = this, args = $A(arguments), object = args.shift(); --- return function() { --- return __method.apply(object, args.concat($A(arguments))); }; }, --- bindAsEventListener: function() { --- var __method = this, args = $A(arguments), object = args.shift(); --- return function(event) { --- return __method.apply(object, [event || window.event].concat(args)); }; }, --- curry: function() { --- if (!arguments.length) return this; --- var __method = this, args = $A(arguments); --- return function() { --- return __method.apply(this, args.concat($A(arguments))); }; }, --- delay: function() { --- var __method = this, args = $A(arguments), timeout = args.shift() * 1000; --- return window.setTimeout(function() { --- return __method.apply(__method, args); }, timeout); }, --- wrap: function(wrapper) { --- var __method = this; --- return function() { --- return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); }; }, --- methodize: function() { --- if (this._methodized) return this._methodized; --- var __method = this; --- return this._methodized = function() { --- return __method.apply(null, [this].concat($A(arguments))); }; } }); >>> Object.extend = function(destination, source) { >>> for (var property in source) >>> destination[property] = source[property]; >>> return destination; }; >>> Object.extend(Object, { --- inspect: function(object) { --- try { --- if (Object.isUndefined(object)) return 'undefined'; --- if (object === null) return 'null'; --- return object.inspect ? object.inspect() : String(object); --- } catch (e) { --- if (e instanceof RangeError) return '...'; --- throw e; --- } }, --- toJSON: function(object) { --- var type = typeof object; --- switch (type) { case 'undefined': case 'function': --- case 'unknown': return; --- case 'boolean': return object.toString(); } --- if (object === null) return 'null'; --- if (object.toJSON) return object.toJSON(); --- if (Object.isElement(object)) return; --- var results = []; --- for (var property in object) { --- var value = Object.toJSON(object[property]); --- if (!Object.isUndefined(value)) --- results.push(property.toJSON() + ': ' + value); } --- return '{' + results.join(', ') + '}'; }, --- toQueryString: function(object) { --- return $H(object).toQueryString(); }, --- toHTML: function(object) { --- return object && object.toHTML ? object.toHTML() : String.interpret(object); }, --- keys: function(object) { --- var keys = []; --- for (var property in object) --- keys.push(property); --- return keys; }, --- values: function(object) { --- var values = []; --- for (var property in object) --- values.push(object[property]); --- return values; }, --- clone: function(object) { --- return Object.extend({ }, object); }, --- isElement: function(object) { --- return object && object.nodeType == 1; }, --- isArray: function(object) { --- return object != null && typeof object == "object" && 'splice' in object && 'join' in object; }, --- isHash: function(object) { --- return object instanceof Hash; }, >>> isFunction: function(object) { >>> return typeof object == "function"; }, --- isString: function(object) { --- return typeof object == "string"; }, --- isNumber: function(object) { --- return typeof object == "number"; }, --- isUndefined: function(object) { --- return typeof object == "undefined"; } }); >>> Object.extend(Function.prototype, { --- argumentNames: function() { --- var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); --- return names.length == 1 && !names[0] ? [] : names; }, --- bind: function() { --- if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; --- var __method = this, args = $A(arguments), object = args.shift(); --- return function() { --- return __method.apply(object, args.concat($A(arguments))); }; }, --- bindAsEventListener: function() { --- var __method = this, args = $A(arguments), object = args.shift(); --- return function(event) { --- return __method.apply(object, [event || window.event].concat(args)); }; }, --- curry: function() { --- if (!arguments.length) return this; --- var __method = this, args = $A(arguments); --- return function() { --- return __method.apply(this, args.concat($A(arguments))); }; }, --- delay: function() { --- var __method = this, args = $A(arguments), timeout = args.shift() * 1000; --- return window.setTimeout(function() { --- return __method.apply(__method, args); }, timeout); }, --- wrap: function(wrapper) { --- var __method = this; --- return function() { --- return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); }; }, --- methodize: function() { --- if (this._methodized) return this._methodized; --- var __method = this; --- return this._methodized = function() { --- return __method.apply(null, [this].concat($A(arguments))); }; } }); >>> var $break = { }; >>> var Enumerable = { >>> each: function(iterator, context) { >>> var index = 0; >>> try { >>> this._each(function(value) { >>> iterator(value, index++); }); >>> } catch (e) { >>> if (e != $break) throw e; >>> } >>> return this; }, --- eachSlice: function(number, iterator, context) { --- var index = -number, slices = [], array = this.toArray(); --- while ((index += number) < array.length) --- slices.push(array.slice(index, index+number)); --- return slices.collect(iterator, context); }, --- all: function(iterator, context) { --- var result = true; --- this.each(function(value, index) { --- result = result && !!iterator(value, index); --- if (!result) throw $break; }); --- return result; }, >>> groupBy: function(iterator, context) { >>> var result = {}; >>> this.each(function(value, index) { >>> var key = iterator(value, index); >>> if (!result[key]) result[key] = []; >>> result[key].append(value); }); >>> return result; }, --- any: function(iterator, context) { --- var result = false; --- this.each(function(value, index) { --- if (result = !!iterator(value, index)) --- throw $break; }); --- return result; }, >>> collect: function(iterator, context) { >>> var results = []; >>> this.each(function(value, index) { >>> results.push(iterator(value, index)); }); >>> return results; }, --- detect: function(iterator, context) { var result; --- this.each(function(value, index) { --- if (iterator(value, index)) { --- result = value; --- throw $break; } }); --- return result; }, >>> findAll: function(iterator, context) { >>> var results = []; >>> this.each(function(value, index) { >>> if (iterator(value, index)) >>> results.push(value); }); >>> return results; }, --- grep: function(filter, iterator, context) { --- var results = []; --- if (Object.isString(filter)) --- filter = new RegExp(filter); --- this.each(function(value, index) { --- if (filter.match(value)) --- results.push(iterator(value, index)); }); --- return results; }, >>> include: function(object) { >>> if (Object.isFunction(this.indexOf)) >>> if (this.indexOf(object) != -1) return true; >>> var found = false; >>> this.each(function(value) { >>> if (value == object) { --- found = true; --- throw $break; } }); >>> return found; }, --- inGroupsOf: function(number, fillWith) { --- fillWith = Object.isUndefined(fillWith) ? null : fillWith; --- return this.eachSlice(number, function(slice) { --- while(slice.length < number) slice.push(fillWith); --- return slice; }); }, >>> inject: function(memo, iterator, context) { >>> this.each(function(value, index) { >>> memo = iterator(memo, value, index); }); >>> return memo; }, >>> invoke: function(method) { >>> var args = $A(arguments).slice(1); >>> return this.map(function(value) { >>> return value[method].apply(value, args); }); }, --- max: function(iterator, context) { var result; --- this.each(function(value, index) { --- value = iterator(value, index); --- if (result == null || value >= result) --- result = value; }); --- return result; }, --- min: function(iterator, context) { var result; --- this.each(function(value, index) { --- value = iterator(value, index); --- if (result == null || value < result) --- result = value; }); --- return result; }, --- partition: function(iterator, context) { --- var trues = [], falses = []; --- this.each(function(value, index) { --- (iterator(value, index) ? trues : falses).push(value); }); --- return [trues, falses]; }, --- pluck: function(property) { --- var results = []; --- this.each(function(value) { --- results.push(value[property]); }); --- return results; }, --- reject: function(iterator, context) { --- var results = []; --- this.each(function(value, index) { --- if (!iterator(value, index)) --- results.push(value); }); --- return results; }, --- sortBy: function(iterator, context) { --- return this.map(function(value, index) { --- return {value: value, criteria: iterator(value, index)}; --- }).sort(function(left, right) { --- var a = left.criteria, b = right.criteria; --- return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, --- toArray: function() { --- return this.map(); }, --- zip: function() { --- var iterator = Object.K, args = $A(arguments); --- if (Object.isFunction(args.last())) --- iterator = args.pop(); --- var collections = [this].concat(args).map($A); --- return this.map(function(value, index) { --- return iterator(collections.pluck(index)); }); }, --- size: function() { --- return this.toArray().length; }, --- inspect: function() { --- return '#'; } }; >>> Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, filter: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray, every: Enumerable.all, some: Enumerable.any }); >>> function $A(iterable) { >>> if (!iterable) return []; >>> if (iterable.toArray) return iterable.toArray(); >>> var length = iterable.length || 0, results = new Array(length); >>> while (length--) results[length] = iterable[length]; >>> return results; } >>> Array.from = $A; >>> Object.extend(Array.prototype, Enumerable); >>> if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; >>> Object.extend(Array.prototype, { --- _each: function(iterator) { --- for (var i = 0, length = this.length; i < length; i++) --- iterator(this[i]); }, --- clear: function() { --- this.length = 0; --- return this; }, >>> first: function() { >>> return this[0]; }, --- last: function() { --- return this[this.length - 1]; }, --- compact: function() { --- return this.select(function(value) { --- return value != null; }); }, --- flatten: function() { --- return this.inject([], function(array, value) { --- return array.concat(Object.isArray(value) ? value.flatten() : [value]); }); }, --- without: function() { --- var values = $A(arguments); --- return this.select(function(value) { --- return !values.include(value); }); }, >>> reverse: function(inline) { >>> return (inline !== false ? this : this.toArray())._reverse(); }, --- reduce: function() { --- return this.length > 1 ? this : this[0]; }, --- uniq: function(sorted) { --- return this.inject([], function(array, value, index) { --- if (0 == index || (sorted ? array.last() != value : !array.include(value))) --- array.push(value); --- return array; }); }, --- intersect: function(array) { --- return this.uniq().findAll(function(item) { --- return array.detect(function(value) { return item === value }); }); }, --- clone: function() { --- return [].concat(this); }, --- size: function() { --- return this.length; }, --- inspect: function() { --- return '[' + this.map(Object.inspect).join(', ') + ']'; }, --- toJSON: function() { --- var results = []; --- this.each(function(object) { --- var value = Object.toJSON(object); --- if (!Object.isUndefined(value)) results.push(value); }); --- return '[' + results.join(', ') + ']'; } }); // use native browser JS 1.6 implementation if available >>> if (Object.isFunction(Array.prototype.forEach)) >>> Array.prototype._each = Array.prototype.forEach; >>> if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { --- i || (i = 0); --- var length = this.length; --- if (i < 0) i = length + i; --- for (; i < length; i++) --- if (this[i] === item) return i; --- return -1; }; >>> if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { --- i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; --- var n = this.slice(0, i).reverse().indexOf(item); --- return (n < 0) ? n : i - n - 1; }; >>> Array.prototype.toArray = Array.prototype.clone; >>> Object.extend(Number.prototype, { --- toColorPart: function() { --- return this.toPaddedString(2, 16); }, >>> succ: function() { >>> return this + 1; }, --- times: function(iterator) { --- $R(0, this, true).each(iterator); --- return this; }, --- toPaddedString: function(length, radix) { --- var string = this.toString(radix || 10); --- return '0'.times(length - string.length) + string; }, --- toJSON: function() { --- return isFinite(this) ? this.toString() : 'null'; } }); >>> var $R = function(start, end, exclusive) { >>> var range = {}; >>> Object.extend(range, Enumerable); >>> range._each = function(iterator) { >>> var value = start; >>> while (range.include(value)) { >>> iterator(value); >>> value = value.succ(); } }; >>> range.include = function(value) { >>> if (value < start) --- return false; >>> if (exclusive) --- return value < end; >>> return value <= end; }; >>> return range; }; === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/sylvester.js === eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9 17={3i:\'0.1.3\',16:1e-6};l v(){}v.23={e:l(i){8(i<1||i>7.4.q)?w:7.4[i-1]},2R:l(){8 7.4.q},1u:l(){8 F.1x(7.2u(7))},24:l(a){9 n=7.4.q;9 V=a.4||a;o(n!=V.q){8 1L}J{o(F.13(7.4[n-1]-V[n-1])>17.16){8 1L}}H(--n);8 2x},1q:l(){8 v.u(7.4)},1b:l(a){9 b=[];7.28(l(x,i){b.19(a(x,i))});8 v.u(b)},28:l(a){9 n=7.4.q,k=n,i;J{i=k-n;a(7.4[i],i+1)}H(--n)},2q:l(){9 r=7.1u();o(r===0){8 7.1q()}8 7.1b(l(x){8 x/r})},1C:l(a){9 V=a.4||a;9 n=7.4.q,k=n,i;o(n!=V.q){8 w}9 b=0,1D=0,1F=0;7.28(l(x,i){b+=x*V[i-1];1D+=x*x;1F+=V[i-1]*V[i-1]});1D=F.1x(1D);1F=F.1x(1F);o(1D*1F===0){8 w}9 c=b/(1D*1F);o(c<-1){c=-1}o(c>1){c=1}8 F.37(c)},1m:l(a){9 b=7.1C(a);8(b===w)?w:(b<=17.16)},34:l(a){9 b=7.1C(a);8(b===w)?w:(F.13(b-F.1A)<=17.16)},2k:l(a){9 b=7.2u(a);8(b===w)?w:(F.13(b)<=17.16)},2j:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x+V[i-1]})},2C:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x-V[i-1]})},22:l(k){8 7.1b(l(x){8 x*k})},x:l(k){8 7.22(k)},2u:l(a){9 V=a.4||a;9 i,2g=0,n=7.4.q;o(n!=V.q){8 w}J{2g+=7.4[n-1]*V[n-1]}H(--n);8 2g},2f:l(a){9 B=a.4||a;o(7.4.q!=3||B.q!=3){8 w}9 A=7.4;8 v.u([(A[1]*B[2])-(A[2]*B[1]),(A[2]*B[0])-(A[0]*B[2]),(A[0]*B[1])-(A[1]*B[0])])},2A:l(){9 m=0,n=7.4.q,k=n,i;J{i=k-n;o(F.13(7.4[i])>F.13(m)){m=7.4[i]}}H(--n);8 m},2Z:l(x){9 a=w,n=7.4.q,k=n,i;J{i=k-n;o(a===w&&7.4[i]==x){a=i+1}}H(--n);8 a},3g:l(){8 S.2X(7.4)},2d:l(){8 7.1b(l(x){8 F.2d(x)})},2V:l(x){8 7.1b(l(y){8(F.13(y-x)<=17.16)?x:y})},1o:l(a){o(a.K){8 a.1o(7)}9 V=a.4||a;o(V.q!=7.4.q){8 w}9 b=0,2b;7.28(l(x,i){2b=x-V[i-1];b+=2b*2b});8 F.1x(b)},3a:l(a){8 a.1h(7)},2T:l(a){8 a.1h(7)},1V:l(t,a){9 V,R,x,y,z;2S(7.4.q){27 2:V=a.4||a;o(V.q!=2){8 w}R=S.1R(t).4;x=7.4[0]-V[0];y=7.4[1]-V[1];8 v.u([V[0]+R[0][0]*x+R[0][1]*y,V[1]+R[1][0]*x+R[1][1]*y]);1I;27 3:o(!a.U){8 w}9 C=a.1r(7).4;R=S.1R(t,a.U).4;x=7.4[0]-C[0];y=7.4[1]-C[1];z=7.4[2]-C[2];8 v.u([C[0]+R[0][0]*x+R[0][1]*y+R[0][2]*z,C[1]+R[1][0]*x+R[1][1]*y+R[1][2]*z,C[2]+R[2][0]*x+R[2][1]*y+R[2][2]*z]);1I;2P:8 w}},1t:l(a){o(a.K){9 P=7.4.2O();9 C=a.1r(P).4;8 v.u([C[0]+(C[0]-P[0]),C[1]+(C[1]-P[1]),C[2]+(C[2]-(P[2]||0))])}1d{9 Q=a.4||a;o(7.4.q!=Q.q){8 w}8 7.1b(l(x,i){8 Q[i-1]+(Q[i-1]-x)})}},1N:l(){9 V=7.1q();2S(V.4.q){27 3:1I;27 2:V.4.19(0);1I;2P:8 w}8 V},2n:l(){8\'[\'+7.4.2K(\', \')+\']\'},26:l(a){7.4=(a.4||a).2O();8 7}};v.u=l(a){9 V=25 v();8 V.26(a)};v.i=v.u([1,0,0]);v.j=v.u([0,1,0]);v.k=v.u([0,0,1]);v.2J=l(n){9 a=[];J{a.19(F.2F())}H(--n);8 v.u(a)};v.1j=l(n){9 a=[];J{a.19(0)}H(--n);8 v.u(a)};l S(){}S.23={e:l(i,j){o(i<1||i>7.4.q||j<1||j>7.4[0].q){8 w}8 7.4[i-1][j-1]},33:l(i){o(i>7.4.q){8 w}8 v.u(7.4[i-1])},2E:l(j){o(j>7.4[0].q){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][j-1])}H(--n);8 v.u(a)},2R:l(){8{2D:7.4.q,1p:7.4[0].q}},2D:l(){8 7.4.q},1p:l(){8 7.4[0].q},24:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(7.4.q!=M.q||7.4[0].q!=M[0].q){8 1L}9 b=7.4.q,15=b,i,G,10=7.4[0].q,j;J{i=15-b;G=10;J{j=10-G;o(F.13(7.4[i][j]-M[i][j])>17.16){8 1L}}H(--G)}H(--b);8 2x},1q:l(){8 S.u(7.4)},1b:l(a){9 b=[],12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;b[i]=[];J{j=10-G;b[i][j]=a(7.4[i][j],i+1,j+1)}H(--G)}H(--12);8 S.u(b)},2i:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4.q==M.q&&7.4[0].q==M[0].q)},2j:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x+M[i-1][j-1]})},2C:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x-M[i-1][j-1]})},2B:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4[0].q==M.q)},22:l(a){o(!a.4){8 7.1b(l(x){8 x*a})}9 b=a.1u?2x:1L;9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2B(M)){8 w}9 d=7.4.q,15=d,i,G,10=M[0].q,j;9 e=7.4[0].q,4=[],21,20,c;J{i=15-d;4[i]=[];G=10;J{j=10-G;21=0;20=e;J{c=e-20;21+=7.4[i][c]*M[c][j]}H(--20);4[i][j]=21}H(--G)}H(--d);9 M=S.u(4);8 b?M.2E(1):M},x:l(a){8 7.22(a)},32:l(a,b,c,d){9 e=[],12=c,i,G,j;9 f=7.4.q,1p=7.4[0].q;J{i=c-12;e[i]=[];G=d;J{j=d-G;e[i][j]=7.4[(a+i-1)%f][(b+j-1)%1p]}H(--G)}H(--12);8 S.u(e)},31:l(){9 a=7.4.q,1p=7.4[0].q;9 b=[],12=1p,i,G,j;J{i=1p-12;b[i]=[];G=a;J{j=a-G;b[i][j]=7.4[j][i]}H(--G)}H(--12);8 S.u(b)},1y:l(){8(7.4.q==7.4[0].q)},2A:l(){9 m=0,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(F.13(7.4[i][j])>F.13(m)){m=7.4[i][j]}}H(--G)}H(--12);8 m},2Z:l(x){9 a=w,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(7.4[i][j]==x){8{i:i+1,j:j+1}}}H(--G)}H(--12);8 w},30:l(){o(!7.1y){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][i])}H(--n);8 v.u(a)},1K:l(){9 M=7.1q(),1c;9 n=7.4.q,k=n,i,1s,1n=7.4[0].q,p;J{i=k-n;o(M.4[i][i]==0){2e(j=i+1;j17.16){1Y++;1I}}H(--G)}H(--a);8 1Y},3d:l(){8 7.1Y()},2W:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}9 T=7.1q(),1p=T.4[0].q;9 b=T.4.q,15=b,i,G,10=M[0].q,j;o(b!=M.q){8 w}J{i=15-b;G=10;J{j=10-G;T.4[i][1p+j]=M[i][j]}H(--G)}H(--b);8 T},2w:l(){o(!7.1y()||7.2y()){8 w}9 a=7.4.q,15=a,i,j;9 M=7.2W(S.I(a)).1K();9 b,1n=M.4[0].q,p,1c,2v;9 c=[],2c;J{i=a-1;1c=[];b=1n;c[i]=[];2v=M.4[i][i];J{p=1n-b;2c=M.4[i][p]/2v;1c.19(2c);o(p>=15){c[i].19(2c)}}H(--b);M.4[i]=1c;2e(j=0;j3||b.4.q>3){8 w}9 c=b.1u();o(c===0){8 w}7.K=a;7.U=v.u([b.4[0]/c,b.4[1]/c,b.4[2]/c]);8 7}};14.u=l(a,b){9 L=25 14();8 L.1Z(a,b)};14.X=14.u(v.1j(3),v.i);14.Y=14.u(v.1j(3),v.j);14.Z=14.u(v.1j(3),v.k);l 11(){}11.23={24:l(a){8(7.1h(a.K)&&7.1m(a))},1q:l(){8 11.u(7.K,7.W)},2U:l(a){9 V=a.4||a;8 11.u([7.K.4[0]+V[0],7.K.4[1]+V[1],7.K.4[2]+(V[2]||0)],7.W)},1m:l(a){9 b;o(a.W){b=7.W.1C(a.W);8(F.13(b)<=17.16||F.13(F.1A-b)<=17.16)}1d o(a.U){8 7.W.2k(a.U)}8 w},2k:l(a){9 b=7.W.1C(a.W);8(F.13(F.1A/2-b)<=17.16)},1o:l(a){o(7.1v(a)||7.1h(a)){8 0}o(a.K){9 A=7.K.4,B=a.K.4,N=7.W.4;8 F.13((A[0]-B[0])*N[0]+(A[1]-B[1])*N[1]+(A[2]-B[2])*N[2])}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;8 F.13((A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2])}},1h:l(a){o(a.W){8 w}o(a.U){8(7.1h(a.K)&&7.1h(a.K.2j(a.U)))}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=F.13(N[0]*(A[0]-P[0])+N[1]*(A[1]-P[1])+N[2]*(A[2]-(P[2]||0)));8(b<=17.16)}},1v:l(a){o(1g(a.U)==\'1f\'&&1g(a.W)==\'1f\'){8 w}8!7.1m(a)},1U:l(a){o(!7.1v(a)){8 w}o(a.U){9 A=a.K.4,D=a.U.4,P=7.K.4,N=7.W.4;9 b=(N[0]*(P[0]-A[0])+N[1]*(P[1]-A[1])+N[2]*(P[2]-A[2]))/(N[0]*D[0]+N[1]*D[1]+N[2]*D[2]);8 v.u([A[0]+D[0]*b,A[1]+D[1]*b,A[2]+D[2]*b])}1d o(a.W){9 c=7.W.2f(a.W).2q();9 N=7.W.4,A=7.K.4,O=a.W.4,B=a.K.4;9 d=S.1j(2,2),i=0;H(d.2y()){i++;d=S.u([[N[i%3],N[(i+1)%3]],[O[i%3],O[(i+1)%3]]])}9 e=d.2w().4;9 x=N[0]*A[0]+N[1]*A[1]+N[2]*A[2];9 y=O[0]*B[0]+O[1]*B[1]+O[2]*B[2];9 f=[e[0][0]*x+e[0][1]*y,e[1][0]*x+e[1][1]*y];9 g=[];2e(9 j=1;j<=3;j++){g.19((i==j)?0:f[(j+(5-i)%3)%3])}8 14.u(g,c)}},1r:l(a){9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=(A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2];8 v.u([P[0]+N[0]*b,P[1]+N[1]*b,(P[2]||0)+N[2]*b])},1V:l(t,a){9 R=S.1R(t,a.U).4;9 C=a.1r(7.K).4;9 A=7.K.4,N=7.W.4;9 b=C[0],1E=C[1],1J=C[2],1w=A[0],18=A[1],1a=A[2];9 x=1w-b,y=18-1E,z=1a-1J;8 11.u([b+R[0][0]*x+R[0][1]*y+R[0][2]*z,1E+R[1][0]*x+R[1][1]*y+R[1][2]*z,1J+R[2][0]*x+R[2][1]*y+R[2][2]*z],[R[0][0]*N[0]+R[0][1]*N[1]+R[0][2]*N[2],R[1][0]*N[0]+R[1][1]*N[1]+R[1][2]*N[2],R[2][0]*N[0]+R[2][1]*N[1]+R[2][2]*N[2]])},1t:l(a){o(a.W){9 A=7.K.4,N=7.W.4;9 b=A[0],18=A[1],1a=A[2],2M=N[0],2L=N[1],2Q=N[2];9 c=7.K.1t(a).4;9 d=b+2M,2p=18+2L,2m=1a+2Q;9 Q=a.1r([d,2p,2m]).4;9 e=[Q[0]+(Q[0]-d)-c[0],Q[1]+(Q[1]-2p)-c[1],Q[2]+(Q[2]-2m)-c[2]];8 11.u(c,e)}1d o(a.U){8 7.1V(F.1A,a)}1d{9 P=a.4||a;8 11.u(7.K.1t([P[0],P[1],(P[2]||0)]),7.W)}},1Z:l(a,b,c){a=v.u(a);a=a.1N();o(a===w){8 w}b=v.u(b);b=b.1N();o(b===w){8 w}o(1g(c)==\'1f\'){c=w}1d{c=v.u(c);c=c.1N();o(c===w){8 w}}9 d=a.4[0],18=a.4[1],1a=a.4[2];9 e=b.4[0],1W=b.4[1],1X=b.4[2];9 f,1i;o(c!==w){9 g=c.4[0],2l=c.4[1],2t=c.4[2];f=v.u([(1W-18)*(2t-1a)-(1X-1a)*(2l-18),(1X-1a)*(g-d)-(e-d)*(2t-1a),(e-d)*(2l-18)-(1W-18)*(g-d)]);1i=f.1u();o(1i===0){8 w}f=v.u([f.4[0]/1i,f.4[1]/1i,f.4[2]/1i])}1d{1i=F.1x(e*e+1W*1W+1X*1X);o(1i===0){8 w}f=v.u([b.4[0]/1i,b.4[1]/1i,b.4[2]/1i])}7.K=a;7.W=f;8 7}};11.u=l(a,b,c){9 P=25 11();8 P.1Z(a,b,c)};11.2I=11.u(v.1j(3),v.k);11.2H=11.u(v.1j(3),v.i);11.2G=11.u(v.1j(3),v.j);11.36=11.2I;11.35=11.2H;11.3j=11.2G;9 $V=v.u;9 $M=S.u;9 $L=14.u;9 $P=11.u;',62,206,'||||elements|||this|return|var||||||||||||function|||if||length||||create|Vector|null|||||||||Math|nj|while||do|anchor||||||||Matrix||direction||normal||||kj|Plane|ni|abs|Line|ki|precision|Sylvester|A2|push|A3|map|els|else||undefined|typeof|contains|mod|Zero|D3|D2|isParallelTo|kp|distanceFrom|cols|dup|pointClosestTo|np|reflectionIn|modulus|intersects|A1|sqrt|isSquare|X2|PI|X3|angleFrom|mod1|C2|mod2|sin|cos|break|C3|toRightTriangular|false|Y3|to3D|E2|E1|E3|Rotation|Y2|Y1|intersectionWith|rotate|v12|v13|rank|setVectors|nc|sum|multiply|prototype|eql|new|setElements|case|each|PA3|PA2|part|new_element|round|for|cross|product|AD2|isSameSizeAs|add|isPerpendicularTo|v22|AN3|inspect|AD3|AN2|toUnitVector|PsubQ3|PsubQ2|v23|dot|divisor|inverse|true|isSingular|determinant|max|canMultiplyFromLeft|subtract|rows|col|random|ZX|YZ|XY|Random|join|N2|N1|D1|slice|default|N3|dimensions|switch|liesIn|translate|snapTo|augment|Diagonal|trace|indexOf|diagonal|transpose|minor|row|isAntiparallelTo|ZY|YX|acos|RotationZ|RotationY|liesOn|RotationX|inv|rk|tr|det|toDiagonalMatrix|toUpperTriangular|version|XZ'.split('|'),0,{})) === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/linkage.js === // a simple cache --------------------- // give it a function that computes a value // it will compute the value the first time it is called, // and then cache it. It uses the cached value // until expire is called, which triggers the cache // to be recomputed on its next access. >>> var cache = function(find) { >>> var value = null; >>> var that = function() { >>> if (value === null) { >>> value = find(); } >>> return value; }; >>> that.expiring = function() {}; >>> that.expire = function() { >>> value = null; >>> that.expiring(); }; >>> return that; }; // model of dependent values -------------------- // a linkage is a single value which can be watched for changes. >>> var linkage = function() { --- var value = arguments.length === 0 ? null : arguments[0]; --- var index = 1; --- var keys = []; --- var observers = []; // if called with no arguments, returns its value // a single argument sets the value --- var that = function() { --- if (arguments.length === 0) { --- return value; --- } else { --- value = arguments[0]; // trigger observers --- if (keys.length > 0) { --- for (var key=0; key < keys.length; key++) { --- observers[keys[key]](value); } } --- return value; } }; // watch takes a function of one argument // which is called whenever this value changes --- that.watch = function(observer) { --- var id = index; --- observers[id] = observer; --- keys.push(id); --- index++; --- return id; }; // given the id returned from a previous watch() call, // disables that observer --- that.unwatch = function(id) { --- keys.splice(keys.indexOf(id), 1); }; --- return that; }; >>> Object.prototype.access = function(entry) { --- if (entry) { --- var path = entry.split('.'); --- var component = path.shift(); --- var parts = component.match(/([^\(]+)\(([^\)]*)\)/); --- var found = parts === null ? this[component] : this[parts[1]](parts[2]); --- return found.access(path.join('.')); --- } else { --- return this; } }; === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/math.js === Math.greater = function(where, to) {return where >= to;}; >>> Math.less = function(where, to) {return where <= to;}; >>> Vector.prototype.o = function(i) { >>> return (i < 0 || i >= this.elements.length) ? null : this.elements[i]; }; >>> Vector.prototype.magnitude = function() { --- return Math.sqrt(this.elements.inject(0, function(sum, element) { --- return sum + element * element; })); }; >>> Vector.prototype.scaleTo = function(magnitude) { >>> return this.toUnitVector().x(magnitude); }; >>> Vector.prototype.inverse = function() { --- return $V(this.elements.map(function(el) { --- return -el; })); }; >>> Vector.prototype.times = function(other) { >>> var result = []; >>> for (var o=0; o>> result[o] = this.elements[o] * other.elements[o]; } >>> return $V(result); }; >>> Vector.prototype.nonrootDistance = function(other) { >>> var result = 0; >>> for (var n = 0; n < this.elements.length; n++) { >>> result += Math.square(this.elements[n] - other.elements[n]); } >>> return result; }; >>> Math.square = function(n) { >>> return n * n; }; // given the lengths of three sides of a triangle a b and c, // the angle between b and c pivoting on a. // (derived from law of cosines) >>> Math.angleFromLengths = function(a, b, c) { --- var num = Math.square(b) + Math.square(c) - Math.square(a); --- var den = 2 * b * c; --- var theta = (den == 0) ? 0 : Math.acos(num / den); --- return (theta > Math.PI) ? (theta - (2*Math.PI)) : theta; }; >>> Math.angleFromPoints = function(a, b, c) { --- var bc = b.distanceFrom(c); --- var ca = c.distanceFrom(a); --- var ab = a.distanceFrom(b); --- return Math.angleFromLengths(bc, ca, ab); }; // sum all angles constructed from the given point // to all pairs of points in the polygon. >>> Math.windingSubtend = function(point, polygon) { --- var previous = polygon.last(); --- return polygon.inject(0, function(sum, vertex) { --- var angle = Math.angleFromPoints(point, previous, vertex); --- previous = vertex; --- return angle + sum; }); }; // if the sum of all subtended angles is 2*pi // the point lies within the polygon // (we fudge a little to compensate for floating point inaccuracies) >>> Math.pointWithin = function(point, polygon) { --- return Math.windingSubtend(point, polygon) > (Math.PI * 1.95); }; // build a kdtree for nearest neighbor comparisons >>> Math.kdtree = function(elements, property) { >>> if (elements.length === 0) {return null;}; >>> var dimension = elements.first()[property]().elements.length; >>> var along = function(el, axis) { >>> return el[property]().elements[axis]; }; >>> var mirror = function(way) { >>> return way === 'left' ? 'right' : 'left'; }; >>> var node = function(value, left, right) { >>> var that = { value: value, left: left, right: right }; >>> that.nearest = function(pos, n, predicate) { >>> n = n || 1; >>> predicate = predicate || function(all) {return true;}; >>> var results = function() { >>> var that = { nodes: [] }; // insert neighbors sorted by distance, so that the last element // in the list is always the furthest away. >>> that.insert = function(node, distance) { >>> distance = distance || pos.nonrootDistance(node.value[property]()); >>> if (that.nodes.length === 0) { >>> that.nodes[0] = {node: node, distance: distance}; >>> } else { >>> var index = that.nodes.length; >>> while (index > 0 && that.nodes[index-1].distance > distance) >>> { >>> that.nodes[index] = that.nodes[index-1]; >>> index--; } >>> that.nodes[index] = {node: node, distance: distance}; } >>> if (that.nodes.length > n) { >>> that.nodes.pop(); } >>> return that; }; >>> that.farthest = function() { >>> return that.nodes[that.nodes.length-1] ? that.nodes[that.nodes.length-1].distance : Infinity; }; >>> return that; }; >>> var check = function(at, best, depth) { >>> return predicate(at.value) ? best.insert(at) : best; }; >>> var within = function(at, best, depth) { >>> if (at === null) {return best;} >>> var axis = depth % dimension; >>> var index = pos.dup(); >>> index.elements[axis] = at.value[property]().o(axis); >>> var distance = pos.nonrootDistance(index); >>> if (distance < best.farthest()) { >>> best = check(at, best, depth); >>> var way = pos.o(axis) < along(at.value, axis) ? 'left' : 'right'; >>> return within(at[way], best, depth+1); >>> } else { >>> return best; } }; >>> var recur = function(at, best, depth) { >>> if (at === null) { >>> return best; } >>> var axis = depth % dimension; >>> var way = pos.o(axis) < along(at.value, axis) ? 'left' : 'right'; >>> best = recur(at[way], best, depth+1); >>> check(at, best, depth); >>> return within(at[mirror(way)], best, depth+1); }; >>> return recur(that, results(), 0).nodes.map(function(node) { >>> return node.node.value; }); }; >>> that.add = function(el, depth) { --- var axis = depth % dimension; --- var way = along(el, axis) < along(that.value, axis) ? 'left' : 'right'; --- if (that[way] === null) { --- that[way] = node(el, null, null); --- } else { --- that[way].add(el, depth+1); } --- return that; }; >>> that.each = function(func) { --- func(that.value); --- if (exists(that.left)) { --- that.left.each(func); --- } else if (exists(that.right)) { --- that.right.each(func); } }; >>> return that; }; >>> var recur = function(elements, depth) { >>> if (elements.length < 1) { >>> return null; } >>> var axis = depth % dimension; >>> var sorted = elements.sort(function(left, right) { >>> var l = along(left, axis); >>> var r = along(right, axis); >>> return l < r ? -1 : l > r ? 1 : 0; }); >>> var median = Math.floor(elements.length / 2); >>> var left = recur(sorted.slice(0, median), depth+1); >>> var right = recur(sorted.slice(median+1), depth+1); >>> return node(sorted[median], left, right); }; >>> return recur(elements, 0); }; === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/canvastext.js === // // This code is released to the public domain by Jim Studt, 2007. // He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/ // >>> var CanvasTextFunctions = { }; >>> CanvasTextFunctions.letters = { ' ': { width: 16, points: [] }, '!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, '"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] }, '#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] }, '$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, '%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] }, '&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] }, '\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] }, '(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] }, ')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] }, '*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] }, '+': { width: 26, points: [[13,18],[13,0],[-1,-1],[4,9],[22,9]] }, ',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, '-': { width: 26, points: [[4,9],[22,9]] }, '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] }, '/': { width: 22, points: [[20,25],[2,-7]] }, '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] }, '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] }, '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] }, '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, '4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] }, '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] }, '7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] }, '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] }, '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] }, ':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, ';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, '<': { width: 24, points: [[20,18],[4,9],[20,0]] }, '=': { width: 26, points: [[4,12],[22,12],[-1,-1],[4,6],[22,6]] }, '>': { width: 24, points: [[4,18],[20,9],[4,0]] }, '?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] }, '@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] }, 'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] }, 'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] }, 'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] }, 'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] }, 'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] }, 'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] }, 'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] }, 'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] }, 'I': { width: 8, points: [[4,21],[4,0]] }, 'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] }, 'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] }, 'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] }, 'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] }, 'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] }, 'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] }, 'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] }, 'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] }, 'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] }, 'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, 'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] }, 'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] }, 'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] }, 'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] }, 'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] }, 'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] }, 'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] }, '[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] }, '\\': { width: 14, points: [[0,21],[14,-3]] }, ']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] }, '^': { width: 16, points: [[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]] }, '_': { width: 16, points: [[0,-2],[16,-2]] }, '`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] }, 'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, 'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] }, 'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, 'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] }, 'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] }, 'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] }, 'l': { width: 8, points: [[4,21],[4,0]] }, 'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] }, 'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, 'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] }, 'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, 'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, 'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] }, 's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] }, 't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] }, 'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] }, 'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] }, 'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] }, 'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] }, 'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] }, 'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] }, '{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] }, '|': { width: 8, points: [[4,25],[4,-7]] }, '}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] }, '~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] } }; >>> CanvasTextFunctions.letter = function (ch) >>> { >>> return CanvasTextFunctions.letters[ch]; }; >>> CanvasTextFunctions.ascent = function(font, size) --- { --- return size; }; >>> CanvasTextFunctions.descent = function(font, size) --- { --- return 7.0*size/25.0; }; >>> CanvasTextFunctions.measure = function(font, size, str) >>> { >>> var total = 0; >>> var len = str.length; >>> for (i = 0; i < len; i++) { >>> var c = CanvasTextFunctions.letter(str.charAt(i)); >>> if (c) total += c.width * size / 25.0; } >>> return total; }; >>> CanvasTextFunctions.draw = function(ctx,font,size,x,y,str) --- { --- var total = 0; --- var len = str.length; --- var mag = size / 25.0; --- ctx.save(); --- ctx.lineCap = "round"; --- ctx.lineWidth = 2.0 * mag; --- for (i = 0; i < len; i++) { --- var c = CanvasTextFunctions.letter(str.charAt(i)); --- if (!c) continue; --- ctx.beginPath(); --- var penUp = 1; --- var needStroke = 0; --- for (j = 0; j < c.points.length; j++) { --- var a = c.points[j]; --- if (a[0] == -1 && a[1] == -1) { --- penUp = 1; continue; } --- if (penUp) { --- ctx.moveTo(x + a[0]*mag, y - a[1]*mag); --- penUp = false; --- } else { --- ctx.lineTo(x + a[0]*mag, y - a[1]*mag); } } --- ctx.stroke(); --- x += c.width*mag; } --- ctx.restore(); --- return total; }; >>> CanvasTextFunctions.op = function(ctx,font,size,x,y,str) >>> { >>> var total = 0; >>> var len = str.length; >>> var mag = size / 25.0; >>> ctx.lineCap = "round"; >>> ctx.lineWidth = 2.0 * mag; >>> for (i = 0; i < len; i++) { >>> var c = CanvasTextFunctions.letter(str.charAt(i)); >>> if (!c) continue; >>> var penUp = 1; >>> var needStroke = 0; >>> for (j = 0; j < c.points.length; j++) { >>> var a = c.points[j]; >>> if (a[0] == -1 && a[1] == -1) { >>> penUp = 1; continue; } >>> if (penUp) { >>> ctx.moveTo(x + a[0]*mag, y - a[1]*mag); >>> penUp = false; >>> } else { >>> ctx.lineTo(x + a[0]*mag, y - a[1]*mag); } } >>> x += c.width*mag; } >>> return total; }; >>> CanvasTextFunctions.enable = function(ctx) >>> { >>> ctx.drawText = function(font,size,x,y,text) { return CanvasTextFunctions.draw(ctx,font,size,x,y,text); }; >>> ctx.opText = function(font,size,x,y,text) { return CanvasTextFunctions.op(ctx,font,size,x,y,text); }; >>> ctx.measureText = function(font,size,text) { return CanvasTextFunctions.measure(font,size,text); }; >>> ctx.fontAscent = function(font,size) { return CanvasTextFunctions.ascent(font,size); }; >>> ctx.fontDescent = function(font,size) { return CanvasTextFunctions.descent(font,size); }; >>> ctx.drawTextRight = function(font,size,x,y,text) { --- var w = CanvasTextFunctions.measure(font,size,text); --- return CanvasTextFunctions.draw(ctx, font,size,x-w,y,text); }; >>> ctx.drawTextCenter = function(font,size,x,y,text) { --- var w = CanvasTextFunctions.measure(font,size,text); --- return CanvasTextFunctions.draw(ctx, font,size,x-w/2,y,text); }; }; === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/flux.js === Object.beget = function(o) { --- var F = function() {}; --- F.prototype = o; --- return new F(); }; >>> Function.prototype.method = function(name, func) { --- if (!this.prototype[name]) { --- this.prototype[name] = func; } }; >>> Array.prototype.append = function(el) { >>> this[this.length] = el; >>> return this; }; >>> var exists = function(value) { >>> return !(value === null || value === undefined); }; >>> var vector_to_rgba = function(v) { >>> if (v) { >>> var inner = v.elements.map(function(component) { >>> return Math.floor(component); }).join(', '); >>> return 'rgba(' + inner + ')'; --- } else { --- return ''; } }; // basic framework namespace >>> var flux = { browser: { >>> dim: function() { >>> var w = arguments[0]; >>> var h = arguments[1]; // if two arguments are provided, they represent width and height >>> if (w && h) { >>> this.w = w; >>> this.h = h; >>> this.dimension = $V([w, h]); // if only one, it is a vector --- } else if (w) { --- this.w = w.elements[0]; --- this.h = w.elements[1]; --- this.dimension = w; } // if none (or any), simply return dimension >>> return this.dimension; } } }; >>> flux.bounds = function(xlow, xhigh, ylow, yhigh) { >>> var that = []; >>> var checks = [Math.min, Math.max]; >>> that.x = [xlow, xhigh]; >>> that.y = [ylow, yhigh]; >>> that[0] = that.x; >>> that[1] = that.y; >>> that.extreme = function(way) { --- return [that[0][way], that[1][way]]; }; >>> that.copy = function() { >>> return flux.bounds(that.x[0], that.x[1], that.y[0], that.y[1]); }; >>> that.range = function(axis) { >>> return that[axis][1] - that[axis][0]; }; >>> that.low = function() { --- return that.extreme(0); }; >>> that.high = function() { --- return that.extreme(1); }; >>> that.width = function() { >>> return that.range(0); }; >>> that.height = function() { >>> return that.range(1); }; >>> that.randomValue = function(axis) { >>> return Math.random()*that.range(axis)+that[axis][0]; }; >>> that.randomPoint = function() { >>> return [0, 1].map(that.randomValue); }; // unions with another bounds object >>> that.union = function(other) { >>> for (var a = 0; a < 2; a++) { >>> for (var b = 0; b < 2; b++) { >>> that[a][b] = checks[b](that[a][b], other[a][b]); } } >>> return that; }; // grows to ensure it encloses the given point >>> that.include = function(point) { >>> for (var a = 0; a < 2; a++) { >>> for (var b = 0; b < 2; b++) { >>> that[a][b] = checks[b](that[a][b], point.o(a)); } } >>> return that; }; // shifts the entire object by the given vector >>> that.translate = function(point) { --- for (var a = 0; a < 2; a++) { --- for (var b = 0; b < 2; b++) { --- that[a][b] += point.o(a); } } --- return that; }; // check whether the given point is within these bounds // returning a list of comparision values by axis >>> that.check = function(point) { >>> return point.elements.map(function(a, index) { >>> return (a < that[index][0]) ? - 1 : (a > that[index][1]) ? 1 : 0; }); }; // check whether the given point is within these bounds // returning a boolean >>> that.inside = function(point) { >>> return that.check(point).inject(true, function(side, a, index) { >>> return side && a === 0; }); }; >>> that.shapeFor = function() { >>> return flux.shape({ops: [ {op: 'move', to: $V([that.x[0], that.y[0]])}, {op: 'line', to: $V([that.x[1], that.y[0]])}, {op: 'line', to: $V([that.x[1], that.y[1]])}, {op: 'line', to: $V([that.x[0], that.y[1]])} ]}); }; >>> that.scale = function(factor) { >>> var w = that.width(); >>> var h = that.height(); >>> var wfactor = (w*factor-w)*0.5; >>> var hfactor = (h*factor-h)*0.5; >>> return flux.bounds(that.x[0]-wfactor, that.x[1]+wfactor, that.y[0]-hfactor, that.y[1]+hfactor); }; >>> return that; }; >>> flux.compositebounds = function() { }; // provide objects to represent atomic drawing operations >>> flux.op = function() { >>> var result = {}; >>> result.base = function(spec) { >>> var that = {}; >>> that.op = spec.op; >>> that.method = spec.method || 'lineTo'; >>> that.to = spec.to ? $V([spec.to.elements[0], spec.to.elements[1]]) : $V([0, 0]); >>> that.args = function() { >>> return that.to.elements; }; >>> that.prod = function(box) { >>> box.include(that.to); }; >>> that.dup = function() { --- return result.base(that); }; >>> that.between = function(other, cycles) { --- return [flux.tweenV({ obj: that, property: 'to', to: other.to, cycles: cycles })]; }; >>> return that; }; >>> result.line = function(spec) { >>> spec.method = 'lineTo'; >>> var that = result.base(spec); >>> that.dup = function() { >>> return result.line(that); }; >>> return that; }; >>> result.move = function(spec) { >>> spec.method = 'moveTo'; >>> var that = result.base(spec); >>> that.dup = function() { >>> return result.move(that); }; >>> return that; }; >>> result.text = function(spec) { >>> spec.method = 'opText'; >>> var that = result.base(spec); >>> that.size = spec.size || 12; >>> that.string = spec.string || ''; >>> that.dup = function() { --- return result.text(that); }; >>> that.args = function() { >>> return [true, that.size, that.to.o(0), that.to.o(1), that.string]; }; >>> that.prod = function(box) { >>> var renderLength = function(string) { >>> return CanvasTextFunctions.measure(true, that.size, string); }; // find the longest line to use as the outermost horizontal boundary >>> var lines = that.string.split('\n'); >>> var longest = {length: renderLength(lines[0]), line: lines[0]}; >>> for (var index=1; index < lines.length; index++) { --- var possible = renderLength(line[index]); --- if (possible > longest.length) { --- longest = {length: possible, line: line[index]}; } } >>> box.union(flux.bounds( that.to.o(0), that.to.o(0) + longest.length, that.to.o(1) - that.size, that.to.o(1) + that.size*lines.length )); }; >>> return that; }; >>> result.arc = function(spec) { >>> spec.method = 'arc'; >>> var that = result.base(spec); >>> that.radius = spec.radius || 10; >>> that.arc = spec.arc || $V([0, Math.PI*2]); >>> that.clockwise = spec.clockwise || true; >>> that.args = function() { >>> return that.to.elements.concat([that.radius].concat(that.arc.elements).append(that.clockwise)); }; >>> that.between = function(other, cycles) { --- return [ flux.tweenV({obj: that, property: 'to', to: other.to, cycles: cycles}), flux.tweenN({obj: that, property: 'radius', to: other.radius, cycles: cycles}), flux.tweenN({obj: that, property: 'arc', to: other.arc, cycles: cycles}) ]; }; >>> that.prod = function(box) { >>> box.union(flux.bounds( that.to.o(0) - that.radius, that.to.o(0) + that.radius, that.to.o(1) - that.radius, that.to.o(1) + that.radius )); }; >>> that.dup = function() { --- return result.arc(that); }; >>> return that; }; >>> result.bezier = function(spec) { >>> spec.method = 'bezierCurveTo'; >>> spec.to = spec.to ? spec.to.dup() : $V([10, 10]); >>> var that = result.base(spec); >>> that.control1 = spec.control1 ? spec.control1.dup() : $V([0, 0]); >>> that.control2 = spec.control2 ? spec.control2.dup() : $V([0, 0]); >>> that.args = function() { >>> return that.control1.elements.concat(that.control2.elements).concat(that.to.elements); }; >>> that.prod = function(box) { >>> box.include(that.to); >>> box.include(that.control1); >>> box.include(that.control2); }; >>> that.between = function(other, cycles) { --- return [ flux.tweenV({ obj: that, property: 'to', to: other.to, cycles: cycles}), flux.tweenV({ obj: that, property: 'control1', to: other.control1, cycles: cycles}), flux.tweenV({ obj: that, property: 'control2', to: other.control2, cycles: cycles}) ]; }; >>> that.dup = function() { >>> return result.bezier(that); }; >>> return that; }; >>> return result; }(); >>> flux.shape = function(spec) { >>> var that = {}; >>> that.ops = spec.ops ? spec.ops.map(function(op) {return flux.op[op.op](op);}) : null || []; >>> that.color = spec.color; >>> that.fill = spec.fill || 'fill'; >>> that.between = function(other, cycles, postcycle) { --- return that.ops.inject([], function(tweens, op, index) { --- return tweens.concat(op.between(other.ops[index], cycles)); }); }; >>> that.dup = function() { >>> return flux.shape({ops: that.ops.map(function(vertex) {return vertex.dup();})}); }; // construct a simple bounding box to tell if further bounds checking is necessary >>> that.boxFor = function() { >>> var box = flux.bounds(0, 0, 0, 0); >>> that.ops.each(function(vertex) { >>> vertex.prod(box); }); >>> return box; }; >>> that.box = that.boxFor(); >>> that.draw = function(context) { >>> context.beginPath(); >>> if (that.color) context[that.fill+'Style'] = vector_to_rgba(that.color); >>> that.ops.each(function(vertex) { >>> context[vertex.method].apply(context, vertex.args()); }); >>> context.closePath(); >>> context[that.fill](); }; >>> return that; }; // generic base tween object >>> flux.tween = function(spec) { >>> var that = {}; >>> that.obj = spec.obj || spec; >>> that.property = spec.property || ((spec.property === 0) ? spec.property : 'this'); >>> that.target = spec.target || function(value) {return value === 0;}; >>> that.step = spec.step || function(value) {return value - 1;}; >>> that.value = function() { >>> return that.obj[that.property]; }; >>> that.cycle = function() { >>> if (that.target(that.value())) { --- return false; >>> } else { >>> that.obj[that.property] = that.step(that.value()); >>> return true; } }; >>> return that; }; // tween object for numbers >>> flux.tweenN = function(spec) { >>> var that = flux.tween(spec); >>> var increment = spec.increment || (spec.cycles ? ((spec.to - spec.obj[spec.property]) / spec.cycles) : 1); >>> var greater = function(where, to) {return where >= to;}; >>> var less = function(where, to) {return where <= to;}; >>> that.to = spec.to || 0; >>> that.test = spec.test || ((that.value() < that.to) ? greater : less); >>> that.target = spec.target || function(value) { >>> return that.test(value, that.to); }; >>> that.step = spec.step || function(value) { >>> return value + increment; }; >>> return that; }; // tween object for vectors >>> flux.tweenV = function(spec) { >>> var that = {}; >>> that.obj = spec.obj || spec; >>> that.property = spec.property || 'this'; >>> that.to = spec.to || $V([1, 1]); >>> that.cycles = spec.cycles || 10; >>> that.postcycle = spec.postcycle || function() {}; >>> that.posttween = spec.posttween || function() {}; >>> that.vector = function() { >>> return that.obj[that.property]; }; >>> var differing = $R(0, that.vector().dimensions() - 1).select(function(index) { >>> return !(that.vector().o(index) === that.to.o(index)); }); >>> that.tweens = differing.map(function(index) { >>> return flux.tweenN({ obj: that.vector().elements, property: index, to: that.to.o(index), cycles: that.cycles }); }); >>> that.cycle = function() { >>> that.tweens = that.tweens.select(function(tween) {return tween.cycle();}); >>> that.postcycle(); >>> if (that.tweens.length === 0) { --- that.posttween(); } >>> return that.tweens.length > 0; }; >>> return that; }; >>> flux.tweenEvent = function(spec) { --- spec.obj = {count: 0}; --- spec.property = 'count'; --- var that = flux.tween(spec); --- that.cycles = spec.cycles || 10; --- that.event = spec.event || function() {}; --- that.target = function(n) { --- var met = true; --- if (n < that.cycles) { --- met = false; --- } else { --- that.event(); } --- return met; }; --- that.step = function(n) { --- return n += 1; }; --- return that; }; // representation of individual agents >>> flux.mote = function(spec) { >>> var that = {}; >>> spec = spec || {}; >>> that.type = spec.type || 'mote'; >>> that.supermote = spec.supermote || null; >>> that.submotes = spec.submotes || []; >>> that.pos = spec.pos || $V([0, 0]); >>> that.shape = spec.shape || flux.shape({ops: [{op: 'arc', to: $V([500, 500]), radius: 50, arc: $V([0, Math.PI*2])}]}); >>> that.orientation = (spec.orientation === undefined) ? Math.random()*2*Math.PI : spec.orientation; >>> that.rotation = (spec.rotation === undefined) ? 0 : spec.rotation; >>> that.velocity = spec.velocity || $V([0, 0]); >>> that.shapes = spec.shapes || [that.shape]; >>> that.visible = spec.visible === undefined ? true : spec.visible; >>> that.color = spec.color || $V([200, 200, 200, 1]); >>> that.scale = spec.scale || $V([1, 1]); >>> that.fill = spec.fill || 'fill'; >>> that.lineWidth = spec.lineWidth || 1; >>> that.outline = spec.outline || null; >>> that.bounds = spec.bounds; >>> that.transform = spec.transform || 'pos'; >>> that.paused = false; >>> that.tweens = []; >>> that.future = []; >>> that.neighbors = []; >>> that.mouseDown = function(mouse) {}; >>> that.mouseUp = function(mouse) {}; >>> that.mouseClick = function(mouse) {}; >>> that.mouseIn = function(mouse) {}; >>> that.mouseOut = function(mouse) {}; >>> that.mouseMove = function(mouse) {}; // absolute is a function to find the absolute position of the mote // with the position, orientation and scale each supermote in this mote's // heirarchy of supermotes taken into consideration. // rise takes a position and recursively applies the transformations of // all supermotes onto it >>> that.rise = function(pos) { >>> pos = that.transform === 'screen' ? pos.add(that.pos.times(flux.browser.dim())) : pos; >>> return that.supermote ? that.supermote.rise(that.supermote.extrovert(pos)) : pos; }; // find_absolute is for the cache, so that the absolute position does not // need to be calculated every time it is accessed, only when the // position or orientation of it or one of its supermotes is changed. >>> var find_absolute = function() { >>> return that.rise(that.pos); }; >>> that.absolute = cache(find_absolute); >>> that.absolute.expiring = function() { >>> that.submotes.each(function(submote) { >>> submote.absolute.expire(); }); }; >>> that.contains = function(point) { >>> return that.box.inside(point.subtract(that.absolute())); }; // construct a simple bounding box to tell if further bounds checking is necessary >>> that.findBox = function() { >>> var box = flux.bounds(0, 0, 0, 0); >>> box = that.shapes.inject(box, function(grow, shape) { >>> return grow.union(shape.box); }); >>> that.submotes.each(function(submote) { --- box.union(submote.box); }); >>> that.box = box; >>> return box; }; >>> that.findBox(); >>> that.findIn = function(mouse, pos) { >>> if (that.contains(pos) && !mouse.inside.include(that)) { >>> mouse.inside.append(that); >>> that.mouseIn(mouse); } >>> that.submotes.invoke('findIn', mouse, pos); }; >>> var findColorSpec = function(prop) { >>> return function() {return vector_to_rgba(that[prop]);}; }; >>> that.color_spec = cache(findColorSpec('color')); >>> that.outline_spec = cache(findColorSpec('outline')); >>> that.tweenColor = function(color, cycles, posttween) { >>> posttween = posttween || function() {}; >>> that.tweens.append(flux.tweenV({ obj: that, property: 'color', to: color, cycles: cycles, >>> postcycle: function() {that.color_spec.expire();}, posttween: posttween })); >>> return that; }; >>> that.tweenPos = function(to, cycles, posttween) { >>> that.tweens.append(flux.tweenV({ obj: that, property: 'pos', to: to, cycles: cycles, >>> postcycle: function() {that.absolute.expire();}, posttween: posttween })); >>> return that; }; >>> that.tweenOrientation = function(orientation, cycles, posttween) { --- that.tweens.append(flux.tweenN({ obj: that, property: 'orientation', to: orientation, cycles: cycles, posttween: posttween })); --- return that; }; >>> that.tweenScale = function(scale, cycles) { >>> that.tweens.append(flux.tweenV({ obj: that, property: 'scale', to: scale, cycles: cycles })); >>> return that; }; >>> that.tweenShape = function(shape, cycles) { --- var tween = that.shape.between(shape, cycles); --- that.tweens = that.tweens.concat(tween); --- return that; }; >>> that.tweenEvent = function(event, cycles) { --- var tween = flux.tweenEvent({event: event, cycles: cycles}); --- that.tweens = that.tweens.concat(tween); --- return that; }; >>> that.expireSupermotes = function() { >>> that.supermotes.expire(); >>> that.absolute.expire(); >>> that.submotes.each(function(submote) { >>> submote.expireSupermotes(); }); }; >>> that.attach = function(other) { >>> other.orientation -= that.orientation; >>> if (other.supermote) { --- other.supermote.submotes = other.supermote.submotes.without(other); } >>> that.submotes.append(other); >>> other.supermote = that; >>> other.expireSupermotes(); }; >>> that.detach = function(other) { --- that.submotes = that.submotes.without(other); --- other.orientation += that.orientation; // other.pos = other.supermote.extrovert(other.pos); --- other.supermote = null; --- if (that.supermote) { // other.pos = that.supermote.extrovert(other.pos); --- that.supermote.attach(other); } --- other.absolute.expire(); }; >>> that.addSubmotes = function(submotes) { >>> submotes.each(function(submote) { >>> that.attach(submote); }); }; >>> that.introvert = function(pos) { >>> return pos.times(that.scale.map(function(el) {return 1.0 / el;})).rotate(-that.orientation, that.pos).subtract(that.pos); }; >>> that.extrovert = function(pos) { // var transform = that.transform === 'screen' ? pos.add(that.pos.times(flux.browser.dim())) : pos.add(that.pos); >>> var transform = pos.add(that.pos); >>> return transform.rotate(that.orientation, that.pos).times(that.scale); }; >>> that.find_supermotes = function() { >>> return (that.supermote === null) ? [] : that.supermote.supermotes().slice().append(that.supermote); }; >>> that.supermotes = cache(that.find_supermotes); >>> that.commonSupermote = function(other) { >>> if (that.supermote === null || other.supermote === null) { --- return null; } >>> var n = that.supermotes().length - 1; >>> var common = null; >>> var down = -1; >>> var possible = null; >>> while (!common && n >= 0) { >>> possible = that.supermotes()[n]; >>> down = other.supermotes().indexOf(possible); >>> if (down >= 0) { >>> common = possible; >>> } else { >>> n -= 1; } } >>> return { common: common, up: that.supermotes().length - 1 - n, down: down === -1 ? other.supermotes().length : other.supermotes().length - 1 - down }; }; >>> that.relativePos = function(other) { >>> if (that.supermote === other.supermote) { >>> return other.pos; } >>> var common = that.commonSupermote(other); >>> var transformed = other.pos; >>> for (var extro = 0; extro < common.down; extro++) { >>> transformed = other.supermotes()[(other.supermotes().length - 1) - extro].extrovert(transformed); } >>> for (var intro = 0; intro < common.up; intro++) { >>> transformed = that.supermotes()[(that.supermotes().length - common.up) + intro].introvert(transformed); } >>> return transformed; }; >>> that.distance = function(other) { >>> return that.absolute().distanceFrom(other.absolute()); }; >>> that.to = function(other) { >>> return other.absolute().subtract(that.absolute()); }; >>> that.angleFrom = function(other) { --- return that.pos.angleFrom(other.pos); }; // this finds the closest mote from a list of possible motes. // a predicate can be provided to filter out choices. >>> that.findClosest = function(others, predicate) { >>> var closestMote = null; >>> var closestDistance = null; >>> predicate = predicate || function(other) {return true;}; >>> others.each(function(other) { >>> if (predicate(other)) { >>> if (closestMote === null) { >>> closestMote = other; >>> closestDistance = that.distance(other); >>> } else { >>> var newDistance = that.distance(other); >>> if (newDistance < closestDistance) { >>> closestMote = other; >>> closestDistance = newDistance; } } } }); >>> return closestMote; }; >>> that.pause = function() { >>> that.paused = true; }; >>> that.unpause = function() { --- that.paused = false; }; >>> that.perceive = spec.perceive || function(env) { >>> that.submotes.each(function(submote) { >>> submote.perceive(env); }); }; >>> that.adjust = spec.adjust || function() { >>> if (!that.paused) { >>> that.orientation += that.rotation; >>> while (that.orientation > Math.PI) { >>> that.orientation -= Math.PI*2; >>> } while (that.orientation < -Math.PI) { >>> that.orientation += Math.PI*2; } >>> for (var dim=0; dim < that.pos.dimensions(); dim++) { >>> that.pos.elements[dim] += that.velocity.o(dim); } >>> that.future.each(function(moment) { >>> moment(that); }); >>> that.future = []; } >>> that.tweens = that.tweens.select(function(tween) { >>> return tween.cycle(); }); >>> that.submotes.invoke('adjust'); >>> that.absolute.expire(); // ----------- lazy bounds checking --------------- >>> if (that.bounds) { >>> var check = that.bounds.check(that.pos); >>> check.each(function(result, index) { >>> if (!(result === 0)) { >>> that.velocity.elements[index] = -that.velocity.elements[index]; } }); } // ------------------------------------------------- }; >>> that.drawShape = function(context, fill) { >>> context.beginPath(); >>> that.shape.ops.each(function(vertex) { >>> context[vertex.method].apply(context, vertex.args()); }); >>> context.closePath(); >>> context[fill](); }; >>> that.draw = function(context) { // drawing lines to neighbors >>> if (that.visible && that.neighbors.length > 1) { >>> context.save(); >>> that.neighbors.each(function(neighbor) { >>> context.lineWidth = 3; >>> context.strokeStyle = that.color_spec(); >>> context.beginPath(); >>> context.moveTo.apply(context, that.pos.elements); >>> context.lineTo.apply(context, that.relativePos(neighbor).elements); >>> context.closePath(); >>> context.stroke(); }); >>> context.restore(); } // drawing the shape >>> context.save(); >>> context[that.fill + 'Style'] = that.color_spec(); >>> context.lineWidth = that.lineWidth; >>> if (that.transform === 'screen') { >>> context.translate(Math.floor(that.pos.o(0)*flux.browser.w), Math.floor(that.pos.o(1)*flux.browser.h)); >>> } else { >>> context.translate.apply(context, that.pos.elements); } >>> context.rotate(that.orientation); >>> context.scale.apply(context, that.scale.elements); >>> if (that.visible) { >>> var len = that.shapes.length; >>> for (var index=0; index < len; index++){ >>> that.shapes[index].draw(context); } >>> if (that.outline) { >>> context.save(); >>> context.strokeStyle = that.outline_spec(); >>> that.drawShape(context, 'stroke'); >>> context.restore(); } } >>> that.submotes.invoke('draw', context); >>> context.restore(); }; >>> return that; }; // managing the canvas for all motes >>> flux.canvas = function(spec) { >>> var that = {}; var canvas, context; var now, before, interval; >>> that.motes = spec.motes || []; >>> that.id = spec.id || ''; >>> that.transforms = that.motes.groupBy(function(mote) { >>> return mote.transform; }); >>> that.down = spec.down || function(m){return null;}; >>> that.up = spec.up || function(m){return null;}; >>> that.move = spec.move || function(m){return null;}; >>> that.translation = spec.translation || $V([0, 0]); >>> that.orientation = spec.orientation || 0; >>> that.scale = spec.scale || $V([1, 1]); >>> that.tweens = []; >>> that.predraw = spec.predraw || function(context) {}; >>> that.postdraw = spec.postdraw || function(context) {}; >>> that.resize = spec.resize || function(browser) {}; >>> that.wheel = spec.wheel || function(delta) {}; >>> that.preventKeys = spec.preventKeys || false; >>> var time = function() { >>> return new Date().getTime(); }; >>> that.triangulate = function() { }; >>> var keys = {}; >>> keys.pressed = {}; >>> keys.predown = function(key) { --- keys.pressed[key] = true; --- keys.down(that, key); }; >>> keys.preup = function(key) { --- delete this.pressed[key]; --- keys.up(that, key); }; >>> keys.down = spec.keyDown || function(th, key) {}; >>> keys.up = spec.keyUp || function(th, key) {}; >>> var mouse = { pos: $V([0, 0]), prevpos: $V([0, 0]), screen: $V([0, 0]), prevscreen: $V([0, 0]), down: false, inside: [], --- diffpos: function() { --- return this.pos.subtract(this.prevpos); }, --- diffscreen: function() { --- return this.screen.subtract(this.prevscreen); }, >>> posify: function(where) { >>> return where.subtract(that.translation).times(that.scale.map(function(el) {return 1.0 / el;})); }, --- deposify: function(where) { --- return where.times(that.scale).add(that.translation); } }; >>> that.addMote = function(mote) { --- if (!that.transforms[mote.transform]) that.transforms[mote.transform] = []; --- that.transforms[mote.transform].append(mote); --- that.motes.append(mote); }; >>> that.removeMote = function(mote) { --- that.transforms[mote.transform] = that.transforms[mote.transform].without(mote); --- that.motes = that.motes.without(mote); }; >>> that.tweenScale = function(scale, cycles) { --- var tween = flux.tweenV({ obj: that, property: 'scale', to: scale, cycles: cycles }); --- that.tweens.append(tween); --- return that; }; >>> that.tweenTranslation = function(translation, cycles) { --- var tween = flux.tweenV({ obj: that, property: 'translation', to: translation, cycles: cycles }); --- that.tweens.append(tween); --- return that; }; >>> that.tweenViewport = function(spec, cycles) { --- if (spec.scale) that.tweenScale(spec.scale, cycles); --- if (spec.translation) that.tweenTranslation(spec.translation, cycles); }; >>> var update = function() { >>> before = now; >>> now = time(); >>> interval = now - before; >>> that.motes.invoke('perceive', that); >>> that.motes.invoke('adjust'); >>> that.tweens = that.tweens.select(function(tween) { --- return tween.cycle(); }); >>> draw(); }; >>> var draw = function() { >>> context.clearRect(0, 0, flux.browser.w, flux.browser.h); >>> that.predraw(context); >>> if (that.transforms['pos']) { >>> context.save(); >>> context.translate(that.translation.o(0), that.translation.o(1)); >>> context.scale(that.scale.o(0), that.scale.o(1)); >>> context.rotate(that.orientation); >>> that.transforms['pos'].invoke('draw', context); >>> context.restore(); } >>> if (that.transforms['screen']) { >>> context.save(); >>> that.transforms['screen'].invoke('draw', context); >>> context.restore(); } >>> that.postdraw(context); }; >>> var mouseEvent = function(event, mouse) { >>> mouse.inside.each(function(mote) { --- mote['mouse'+event](mouse); }); >>> return that; }; >>> var mouseDown = function(e) { >>> mouse.down = true; >>> mouseEvent('Down', mouse); >>> that.down(mouse); }; >>> var mouseUp = function(e) { >>> mouse.down = false; >>> mouseEvent('Up', mouse); >>> that.up(mouse); }; >>> var mouseClick = function(e) { >>> mouseEvent('Click', mouse); }; >>> var mouseMove = function(e) { >>> var scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset; >>> var scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset; >>> var x = (e.clientX - canvas.offsetLeft + scrollX); >>> var y = (e.clientY - canvas.offsetTop + scrollY); >>> mouse.prevscreen = mouse.screen; >>> mouse.screen = $V([x, y]); >>> mouse.prevpos = mouse.pos; >>> mouse.pos = mouse.posify(mouse.screen); // sort out which motes are no longer under the mouse // and which still contain it >>> if (mouse.inside.length > 0) { --- var motion = mouse.inside.partition(function(mote) { --- return mote.contains(mouse[mote.transform]); }); --- mouse.inside = motion[0]; --- mouse.inside.each(function(mote) { --- mote.mouseMove(mouse); }); --- motion[1].each(function(mote) { --- mote.mouseOut(mouse); }); } // find out which motes are newly under the mouse >>> that.motes.each(function(mote) { >>> mote.findIn(mouse, mouse[mote.transform]); }); // call custom mouse move function, if one is defined --- that.move(mouse); }; // parse the mouse wheel event and call wheel with a useful value >>> var readDeltas = function(e) { --- var delta = 0; --- if (!e) { --- e = window.event; } --- if (e.wheelDelta) { --- delta = e.wheelDelta/120; --- } else if (e.detail) { --- delta = -e.detail/3; } --- if (delta) { --- that.wheel(that, delta); } --- if (e.preventDefault) { --- e.preventDefault(); } --- e.returnValue = false; }; >>> var keyDown = function(e) { --- keys.predown(e.keyCode); --- if (that.preventKeys) { --- if (e.preventDefault) e.preventDefault(); --- if (e.stopPropagation) e.stopPropagation(); --- return false; } --- return true; }; >>> var keyUp = function(e) { --- keys.preup(e.keyCode); --- if (that.preventKeys) { --- if (e.preventDefault) e.preventDefault(); --- if (e.stopPropagation) e.stopPropagation(); --- return false; } --- return true; }; // zoom keeping the current mouse position fixed. // works by finding the vector from the mouse position to the top left corner, // then scaling it to the new zoom factor. >>> that.zoom = function(factor) { --- var buffer = mouse.pos.subtract(mouse.posify($V([0, 0]))).x(1.0/factor); --- that.scale = that.scale.x(factor); --- that.translation = that.translation.subtract(mouse.deposify(mouse.pos.subtract(buffer))); }; >>> that.init = function() { // resize >>> var resize = function(e) { --- flux.browser.dim(window.innerWidth, window.innerHeight); --- canvas.width = flux.browser.w; --- canvas.height = flux.browser.h; --- that.resize(flux.browser); }; >>> window.onresize = resize; // mouse wheel >>> if (window.addEventListener) { >>> window.addEventListener('DOMMouseScroll', readDeltas, false); } >>> window.onmousewheel = document.onmousewheel = readDeltas; // canvas >>> canvas = document.getElementById ? document.getElementById(spec.id) : null; >>> if (!canvas || !canvas.getContext) { --- return; } >>> context = canvas.getContext('2d'); >>> CanvasTextFunctions.enable(context); // mouse events >>> canvas.addEventListener('mousedown', mouseDown, false); >>> canvas.addEventListener('mouseup', mouseUp, false); >>> canvas.addEventListener('click', mouseClick, false); >>> canvas.addEventListener('mousemove', mouseMove, false); // key events >>> window.addEventListener('keydown', keyDown, false); >>> window.addEventListener('keyup', keyUp, false); // dimensions >>> flux.browser.dim(window.innerWidth, window.innerHeight); >>> canvas.width = flux.browser.w; >>> canvas.height = flux.browser.h; // provide a reference to the actual canvas object >>> that.canvas = canvas; >>> context.strokeStyle = 'rgba(0, 0, 0, 1)'; >>> context.lineWidth = 5; // timer >>> setInterval(update, 20); }; >>> return that; }; // that.shape = spec.shape || [$V([-20, 0]), $V([20, 20]), $V([30, -10]), $V([-20, -20])]; // that.shape = spec.shape || [$V([0, 0]), $V([100, 10]), $V([200, -10])]; === File file:/Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/homeostasis.js === var homeostasis = function(id) { >>> var above = flux.bounds(-1700, 1700, -450, 250); >>> var below = flux.bounds(-1700, 1700, 1700, 2400); >>> var all = above.copy().union(below); >>> var receptorGrip = 0.996; >>> var attractantRepellentRatio = 0.5; >>> var phosphorylationCycles = 50; >>> var globalVelocity = 5; >>> var timeZoom = 10; >>> var dragging = false; >>> var showingState = false; >>> var defaultRotation = function() {return Math.random() * 0.1 - 0.05;}; >>> var descriptions = { homeostasis: 'Homeostasis is the process of maintaining some kind of balance\n' + 'in the face of endlessly changing external forces. In this case\n' + 'the cell is always seeking to climb the gradient of attractants\n' + 'and oppose the gradient of repellents, leading it to sources of food\n' + 'and away from potentially harmful agents. The system maintains\n' + 'its sensitivity to even the most subtle gradient while compensating\n' + 'for any saturation of either attractants or repellents in the\n' + 'surrounding environment.', about: 'This is an interactive model of cellular chemotaxis. You can drag\n' + 'the model around with the mouse and zoom in and out with the scroll wheel,\n' + 'or the \'i\' and \'o\' keys (for \'in\' and \'out\') if you are missing a scroll wheel.\n' + 'Mousing over one of the components will highlight the corresponding entry\n' + 'in the menu, and clicking will bring up a description of that component\n' + 'and its role in the process of sensing chemical gradients.', '______________________________': 'This is the divider!', membrane: 'The membrane is the enclosing surface that separates\n' + 'the inside of the cell from the outside. The cell\n' + 'maintains an electric potential across this membrane\n' + 'and then harnesses that potential to do work.', flagella: 'When the flagella spin in one direction the cell is\n' + 'propelled forward. In the other direction, the cell tumbles\n' + 'erratically. Because of the chemotaxis system, the cell will\n' + 'travel forwards mostly, and tumble infrequently, unless in the\n' + 'presence of repellents, where it\'s tendency to tumble will\n' + 'lead it away from the potentially harmful source.', column: 'The column spans the membrane, allowing for communication\n' + 'across the otherwise impenetrable barrier. This way also\n' + 'transportation of materials across the membrane is strictly\n' + 'controlled. In this case, receptors in the outer portion\n' + 'of the column bind either attractants or repellents, which\n' + 'act as ligands, and the inner portion is bound to cheW,\n' + 'which can be activated or deactived based on which ligands\n' + 'the outer portion is bound to.', repellent: 'Repellents bind to receptors in a column and\n' + 'increase the activity of cheW, leading to the phosphorylation\n' + 'of cheY and cheB.', attractant: 'Attractants bind to receptors in a column and\n' + 'reduce the activity of cheW.', cheW: 'cheW is activated by repellents binding to the outer portion\n' + 'of the column and deactivated by the binding of attractants,\n' + 'with its sensitivity guided by the number of bound\n' + 'methyl groups attached to the inner portion. When active, cheW\n' + 'enables the phosphorylation of cheY, which triggers activation of the\n' + 'flagellar motors, and of cheB, which removes\n' + 'methyl groups from the column.', phosphate: 'Phosphate groups often act as a tag, or a signal that some condition is present.\n' + 'In the process of binding to various enzymes they trigger conformational\n' + 'changes which expose the enzymes\' active sites. These active sites\n' + 'then trigger some other change, such as splicing or fusing other molecular components.', cheY: 'cheY is an enzyme that when phosphorylated binds to flagellar motors,\n' + 'inducing them to reverse their rotation and send the cell tumbling in a different direction.\n' + 'Most of the time the flagella are rotating in a clockwise direction, which sends\n' + 'the cell travelling in mostly a straight line. The motor can be reversed, causing the cell\n' + 'to tumble more or less randomly, which then travels off in a new direction.', cheZ: 'cheZ removes phosphate groups from cheY. In this way,\n' + 'a balance is struck between the phosphorylation caused by the activation of\n' + 'cheW when the cell is in the presence of repellents, and the steady dephosphorylation\n' + 'that results from interactions with cheZ. This self-limiting cycle\n' + 'results in a sensitivity to chemical gradients, with the cell avoiding repellents\n' + 'and seeking attractants.', methyl: 'Methyl groups are signifiers like phosphates, and are attached to various molecules\n' + 'in order to induce conformational changes. In this case, the methyls are binding\n' + 'to the inner portion of the columns. The more methyl groups bound to the column,\n' + 'the more sensitive the column is to repellents, and the more active cheW will be.', cheB: 'cheB is phosphorylated in the presence of active cheW, just like cheY. cheB\n' + 'removes methyl groups from columns, thereby reducing the activity of cheW and\n' + 'the subsequent phosphorylation of cheB (and cheY). So here we see another layer\n' + 'of self-limitation, the activation of cheW leading to the phosphorylation of cheB\n' + 'leading to the demethylation of columns leading to the DE-activation of cheW.\n' + 'So the activation of cheW entails the eventual deactivation of cheW, cleaning up\n' + 'its own mess so to speak. This process is called *adaptation*, and is common\n' + 'to a mind-boggling cross-section of biological processes. ', cheR: 'cheR adds methyl groups to the inner portion of a column at a\n' + 'steady rate. In this way the rate of cheW activation is steadily\n' + 'increased, offset by the concentration of phosphorylated cheB.\n' + 'This adaptive cycle of methylation and demethylation is on a much\n' + 'longer time-scale than the activation of cheW by repellents and\n' + 'the phosphorylation of cheY. In this way the cell can be\n' + 'immediately responsive while at the same time adaptive to the\n' + 'general fluctuations of attractants and repellents in the\n' + 'surrounding environment.' }; >>> var molecule = function(spec) { >>> var that = flux.mote(spec); >>> var oldVelocity = that.velocity; >>> that.neighbors = [that]; >>> that.state = 'base'; >>> that.base = function(env) {}; >>> that.focus = function() { >>> that.oldColor = that.color.dup(); >>> that.tweenColor($V([255, 255, 255, 1]), 5); >>> that.pause(); }; >>> that.unfocus = function() { --- if (that.oldColor) that.tweenColor(that.oldColor, 5); --- that.unpause(); }; >>> that.mouseIn = spec.mouseIn || function(mouse) { >>> that.focus(); >>> if (that.type) { >>> moleculeKey.itemhash[that.type].activate(); } }; >>> that.mouseOut = spec.mouseOut || function(mouse) { --- that.unfocus(); --- if (that.type) { --- moleculeKey.itemhash[that.type].deactivate(); } }; >>> that.keyItem = function() { --- return moleculeKey.itemhash[that.type]; }; >>> var showDescription = function(mouse) { // only show the deepest submote under the mouse --- var lowest = mouse.inside.inject(that, function(lowest, inside) { --- return lowest.supermotes().length < inside.supermotes().length ? inside : lowest; }); --- if (that === lowest) { // var output = that.type + ' -- ' + that.state + '\n' + that.shape.ops.map(function(s) {return s.to.elements.map(function(x){return Math.round(x);});}) + '\n\n'; --- var state = showingState ? ' -- ' + that.state : ''; --- var output = that.type + state + '\n\n'; --- that.keyItem().showDescription(output); } }; >>> var hideDescription = function(mouse) { --- that.keyItem().hideDescription(true); }; >>> that.findNeighbor = function(condition) { >>> var index = 0; >>> var neighbor = null; >>> var found = null; >>> while (!found && index < that.neighbors.length) { >>> neighbor = that.neighbors[index]; >>> if (condition(neighbor)) { >>> found = neighbor; } >>> index += 1; } >>> return found; }; >>> that.perceive = spec.perceive || function(env) { >>> that[that.state](env); }; >>> that.mouseDown = spec.mouseDown || showDescription; >>> that.mouseUp = spec.mouseUp || hideDescription; >>> return that; }; >>> var randomPos = function(box) { >>> return $V(box.randomPoint()); }; >>> var randomLigand = function() { >>> var up = (Math.random() - 0.5) > 0; >>> var inside = up ? above : below; >>> if (Math.random() * (attractantRepellentRatio + 1) < attractantRepellentRatio) { >>> return {type: 'attractant', ligand: attractant({pos: randomPos(inside)})}; >>> } else { >>> return {type: 'repellent', ligand: repellent({pos: randomPos(inside)})}; } }; >>> var randomColumn = function(box, adjustment) { >>> var up = (Math.random() - 0.5) > 0; >>> var x = box.randomPoint()[0] * 0.6; >>> var y = up ? box[1][0] - 20 : box[1][1] + 20; >>> var orientation = up ? 0 : Math.PI; >>> return column({pos: $V([x, y]), orientation: orientation + adjustment}); }; >>> var randomMolecule = function(type, box) { >>> return type({pos: randomPos(box), bounds: box}); }; >>> var ligand = function(spec) { >>> var that = molecule(spec); >>> var velocityScale = 0.9; >>> that.closestReceptor = null; >>> that.attached = false; >>> that.detached = false; >>> that.polarity = -1; >>> that.state = 'unattached'; >>> that.unattached = function(env) { >>> if (!exists(that.closestReceptor) || that.closestReceptor.taken) { >>> that.closestReceptor = that.findClosest(membranes.first().receptors, function(receptor) { >>> return receptor.taken === false; }); } >>> if (exists(that.closestReceptor)) { >>> var distance = that.closestReceptor.distance(that); >>> if (distance > globalVelocity) { >>> that.future.append(function(self) { >>> that.velocity = that.velocity.add(that.to(that.closestReceptor).x(20/(distance))).scaleTo(velocityScale*globalVelocity); }); >>> } else { >>> that.future.append(function(self) { >>> that.velocity = $V([0, 0]); >>> that.rotation = 0; }); >>> that.closestReceptor.take(that); >>> that.state = 'attached'; } } }; >>> that.attached = function(env) { >>> if (Math.random() > receptorGrip) { --- that.velocity = that.absolute().subtract(that.closestReceptor.column.absolute()).scaleTo(globalVelocity); --- that.rotation = defaultRotation(); --- that.state = 'detached'; --- that.closestReceptor.release(); --- that.closestReceptor = null; } }; >>> that.detached = function(env) { --- if (!all.inside(that.absolute())) { --- var realm = Math.random() - 0.5 < 0 ? above : below; --- that.pos = randomPos(realm); --- that.state = 'unattached'; } }; >>> return that; }; >>> var attractant = function(spec) { >>> spec.type = 'attractant'; >>> spec.color = spec.color || $V([140, 170, 100, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [{op: 'arc', radius: 7}]}); >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = ligand(spec); >>> return that; }; >>> var repellent = function(spec) { >>> spec.type = 'repellent'; >>> spec.color = spec.color || $V([170, 70, 60, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-6, -6])}, {op: 'line', to: $V([6, -6])}, {op: 'line', to: $V([6, 6])}, {op: 'line', to: $V([-6, 6])} ]}); >>> spec.rotation = defaultRotation(); >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = ligand(spec); >>> that.polarity = 1; >>> return that; }; >>> var membrane = function(spec) { >>> spec.type = 'membrane'; >>> spec.fill = 'stroke'; >>> spec.lineWidth = 30; >>> spec.color = spec.color || $V([80, 20, 20, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-1400, -700])}, {op: 'line', to: $V([1400, -700])}, {op: 'bezier', to: $V([1400, 700]), control1: $V([2450, -700]), control2: $V([2450, 700])}, {op: 'line', to: $V([-1400, 700])}, {op: 'bezier', to: $V([-1400, -700]), control1: $V([-2450, 700]), control2: $V([-2450, -700])} ], fill: 'stroke'}); // spec.orientation = Math.random() * Math.PI; >>> var that = molecule(spec); >>> var inside = flux.bounds(that.box[0][0] + 700, that.box[0][1] - 700, that.box[1][0] + 50, that.box[1][1] - 50); >>> that.columns = $R(0, 12).map(function(index) { >>> return randomColumn(that.box, that.orientation); }); // receptors and cheWs are part of columns, but we make a reference for them here >>> that.receptors = that.columns.inject([], function(rs, column) {return rs.concat(column.receptors);}); >>> that.cheWs = that.columns.map(function(column) {return column.cheW;}); // that.flagella = flagella({pos: $V([2190, 0]), orientation: that.orientation}); // that.attach(that.flagella); >>> that.phosphates = $R(0, 20).map(function(index) { >>> return randomMolecule(phosphate, inside); }); >>> that.methyls = $R(0, 20).map(function(index) { >>> return randomMolecule(methyl, inside); }); >>> that.cheYs = $R(0, 10).map(function(index) { >>> return randomMolecule(cheY, inside); }); >>> that.cheBs = $R(0, 10).map(function(index) { >>> return randomMolecule(cheB, inside); }); >>> that.cheZs = $R(0, 10).map(function(index) { >>> return randomMolecule(cheZ, inside); }); >>> that.cheRs = $R(0, 10).map(function(index) { >>> return randomMolecule(cheR, inside); }); >>> that.cheWSeekers = that.cheYs.concat(that.cheBs).concat(that.phosphates); >>> that.receptors.each(function(receptor, index) { >>> receptor.cheW = that.cheWs[index]; }); >>> that.addSubmotes(that.columns .concat(that.phosphates) .concat(that.methyls) .concat(that.cheYs) .concat(that.cheZs) .concat(that.cheBs) .concat(that.cheRs)); // that.submote_pantheon = that.cheWs.concat(that.submotes.clone()); >>> that.submote_pantheon = that.cheWs .concat(that.phosphates) .concat(that.methyls) .concat(that.cheYs) .concat(that.cheZs) .concat(that.cheBs) .concat(that.cheRs); >>> that.perceive = function(env) { >>> that.tree = Math.kdtree(that.submote_pantheon, 'absolute', 0); >>> that.submote_pantheon.each(function(submote) { >>> submote.neighbors = that.tree.nearest(submote.absolute(), 5, function(pod) { >>> return !(pod === that); }); }); >>> that.submotes.each(function(submote) { >>> submote.perceive(env); }); }; >>> return that; }; >>> var column = function(spec) { >>> spec.type = 'column'; >>> spec.color = spec.color || $V([60, 70, 170, 1]); >>> spec.outline = spec.outline || $V([0, 0, 0, 1]); >>> spec.lineWidth = 3; >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-30, -50])}, {op: 'bezier', to: $V([30, -50]), control1: $V([-30, 0]), control2: $V([30, 0])}, {op: 'line', to: $V([50, -50])}, {op: 'bezier', to: $V([10, 0]), control1: $V([60, -50]), control2: $V([40, 0])}, {op: 'line', to: $V([10, 100])}, {op: 'line', to: $V([-10, 100])}, {op: 'line', to: $V([-10, 0])}, {op: 'bezier', to: $V([-50, -50]), control1: $V([-40, 0]), control2: $V([-60, -50])} ]}); >>> var that = molecule(spec); >>> that.cheW = cheW({pos: $V([0, 100]), orientation: that.orientation, column: that}); >>> that.receptors = [ receptor({pos: $V([0, -18]), column: that, cheW: that.cheW}), receptor({pos: $V([-25, -42]), column: that, cheW: that.cheW}), receptor({pos: $V([-17, -26]), column: that, cheW: that.cheW}), receptor({pos: $V([17, -26]), column: that, cheW: that.cheW}), receptor({pos: $V([25, -42]), column: that, cheW: that.cheW}) ]; >>> that.addSubmotes([that.cheW].concat(that.receptors)); >>> that.level = 0; >>> that.state = 'inactive'; >>> that.openMethylSites = [ $V([10, 50]), $V([10, 70]), $V([-10, 70]), $V([-10, 50]) ]; >>> that.takenMethylSites = []; >>> that.claimMethylSite = function() { >>> var site = that.openMethylSites.shift(); >>> that.takenMethylSites.push(site); >>> return that.extrovert(site); }; >>> that.active = function(env) { >>> if (that.level <= 0) { --- that.deactivate(); } }; >>> that.inactive = function(env) { >>> if (that.level > 0) { >>> that.activate(); } }; >>> that.activate = function() { >>> that.state = 'active'; >>> that.cheW.activate(); }; >>> that.deactivate = function() { --- that.state = 'inactive'; --- that.cheW.deactivate(); }; >>> return that; }; >>> var receptor = function(spec) { >>> spec.type = 'receptor'; >>> spec.visible = false; >>> spec.color = $V([0, 0, 0, 0]); >>> spec.shape = flux.shape({ops: [{op: 'arc', to: $V([0, 0]), radius: 7}]}); >>> var that = molecule(spec); >>> that.column = spec.column; >>> that.cheW = spec.cheW; >>> that.taken = false; >>> that.ligand = null; >>> that.delay = 0; >>> that.take = function(ligand) { >>> that.column.level += ligand.polarity; >>> that.ligand = ligand; >>> that.taken = true; >>> that.perceive = that.bound; }; >>> that.release = function() { --- that.column.level -= that.ligand.polarity; --- that.ligand = null; --- that.taken = false; --- that.delay = 50; --- that.perceive = that.closed; }; >>> that.open = function(env) { }; >>> that.bound = function(env) { }; >>> that.closed = function(env) { --- if (that.delay < 1) { --- that.delay = 0; --- that.taken = false; --- that.perceive = that.open; --- } else { --- that.delay -= 1; } }; >>> that.perceive = function(env) { --- if (that.detached < 2) { --- that.detached = 0; --- that.taken = false; --- } else if (that.detached > 1) { --- that.detached = that.detached - 1; } }; >>> return that; }; >>> var cheW = function(spec) { >>> spec.type = 'cheW'; >>> var activeColor = spec.activeColor || $V([210, 220, 130, 1]); >>> var inactiveColor = spec.inactiveColor || $V([40, 40, 40, 1]); >>> spec.color = spec.color || inactiveColor.dup(); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-30, 0])}, {op: 'bezier', to: $V([30, 0]), control1: $V([30, 30]), control2: $V([-30, 30])}, {op: 'bezier', to: $V([-30, 0]), control1: $V([-30, -30]), control2: $V([30, -30])} ]}); >>> var that = molecule(spec); >>> that.active = false; >>> that.column = spec.column; >>> that.activate = function() { >>> that.active = true; >>> that.tweens = []; >>> that.tweenColor(activeColor, 20); >>> membranes.first().cheWSeekers.each(function(seeker) { >>> if (seeker.activeCheW) { --- if (seeker.distance(seeker.activeCheW) > seeker.distance(that)) { --- seeker.activeCheW = that; } } }); }; >>> that.deactivate = function() { --- that.active = false; --- that.tweens = []; --- that.tweenColor(inactiveColor, 20); }; >>> return that; }; >>> var cheWSeeker = function(spec) { >>> var that = molecule(spec); >>> var velocityScale = 5; >>> that.insideRadius = spec.insideRadius || 300; >>> that.tooCloseRadius = spec.tooCloseRadius || 20; >>> that.nearestPhosphate = null; >>> that.phosphate = null; >>> that.activeCheW = null; >>> that.outsideCheW = function() {}; >>> that.insideCheW = function() {}; >>> that.tooCloseCheW = function() {}; >>> that.bound = function(env) {}; >>> that.state = 'identifying'; >>> that.switchedOff = function() { --- that.future.append(function(self) { --- that.velocity = $V([(Math.random()-0.5)*velocityScale, (Math.random()-0.5)*velocityScale]); }); --- that.state = 'identifying'; }; >>> that.identifying = function(env) { >>> that.activeCheW = that.findNeighbor(function(neighbor) { >>> return neighbor.type === 'cheW' && neighbor.active; }); >>> if (that.activeCheW) { >>> that.orient(); >>> that.perceive(env); } }; >>> that.orient = function() { >>> if (!that.activeCheW.active) { --- that.switchedOff(); >>> } else { >>> var distance = that.distance(that.activeCheW); >>> if (distance > that.insideRadius) { --- that.state = 'outside'; >>> } else if (distance > that.tooCloseRadius) { >>> that.state = 'inside'; --- } else { --- that.state = 'tooClose'; } } }; >>> that.outside = function(env) { --- that.orient(); --- var distance = that.distance(that.activeCheW); --- var turning = that.to(that.activeCheW).x(0.2/(distance)); --- that.future.append(function(self) { --- that.velocity = that.velocity.add(turning).scaleTo(velocityScale/3); }); --- that.outsideCheW(); }; >>> that.inside = function(env) { >>> that.orient(); >>> var distance = that.distance(that.activeCheW); >>> var turning = that.to(that.activeCheW).x(0.2/(distance)); >>> that.future.append(function(self) { >>> that.velocity = that.velocity.add(turning).scaleTo(velocityScale*0.5); }); >>> that.insideCheW(); }; >>> that.tooClose = function(self) { --- that.orient(); --- var distance = that.distance(that.activeCheW); --- that.future.append(function(self) { --- that.velocity = that.velocity.scaleTo(distance / 50); }); --- that.tooCloseCheW(); }; >>> return that; }; >>> var phosphate = function(spec) { >>> spec.type = 'phosphate'; >>> spec.color = spec.color || $V([120, 80, 130, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-10, -5])}, {op: 'line', to: $V([10, -5])}, {op: 'line', to: $V([10, 0])}, {op: 'bezier', to: $V([1, 0]), control1: $V([10, 10]), control2: $V([1, 10])}, {op: 'line', to: $V([-10, 0])} ]}); >>> spec.rotation = Math.random()*0.02-0.01; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = cheWSeeker(spec); >>> that.pull = function(enzyme) { --- if (!that.state === 'bound') { --- that.future.append(function(self) { --- self.velocity = self.velocity.add(self.to(enzyme).scaleTo(0.2)); }); } }; >>> that.phosphorylate = function(enzyme) { --- that.enzyme = enzyme; --- that.pos = enzyme.introvert(that.pos); --- that.absolute.expire(); --- that.tweens.append(flux.tweenV({ obj: that, property: 'pos', to: $V([-15, 10]), cycles: phosphorylationCycles })); --- that.tweens.append(flux.tweenN({ obj: that, property: 'orientation', to: Math.PI*0.5, cycles: phosphorylationCycles })); --- that.future = []; --- that.rotation = 0; --- that.velocity = $V([0, 0]); // that.neighbors = []; --- that.state = 'bound'; }; >>> that.dephosphorylate = function() { --- that.rotation = defaultRotation(); --- that.velocity = $V([Math.random()-0.5, Math.random()-0.5]); --- that.pos = that.enzyme.extrovert(that.pos); --- that.absolute.expire(); --- that.enzyme = null; --- that.state = 'identifying'; }; >>> return that; }; >>> var methyl = function(spec) { >>> spec.type = 'methyl'; >>> spec.color = spec.color || $V([130, 110, 70, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-5, 0])}, {op: 'line', to: $V([6, 0])}, {op: 'line', to: $V([13, -4])}, {op: 'line', to: $V([19, 3])}, {op: 'line', to: $V([13, 10])}, {op: 'line', to: $V([6, 6])}, {op: 'line', to: $V([-5, 6])} ]}); >>> spec.rotation = defaultRotation()*0.2; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = molecule(spec); >>> that.state = 'free'; >>> that.enzyme = null; >>> that.bind = function(enzyme, site) { >>> that.state = 'binding'; >>> that.enzyme = enzyme; >>> that.site = site; >>> that.rotation = 0; >>> that.velocity = $V([0, 0]); >>> that.column = that.enzyme.cheWNeighbor.column; >>> var modifier = that.column.introvert(that.site).elements[0] < 0 ? Math.PI : 0; >>> that.tweenPos(that.site, phosphorylationCycles*2, function() { --- that.orientation = that.column.orientation + modifier; --- that.state = 'bound'; }); }; >>> that.cut = function() { --- that.enzyme = null; --- that.site = null; --- that.column = null; --- that.rotation = defaultRotation()*0.2; --- that.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); --- that.state = 'free'; }; >>> that.free = function(env) { }; >>> that.binding = function(env) { }; >>> that.bound = function(env) { }; >>> return that; }; >>> var cheWActor = function(spec) { >>> spec.color = spec.inactiveColor.dup(); >>> spec.shape = spec.inactiveShape.dup(); >>> var that = cheWSeeker(spec); >>> that.inactiveShape = spec.inactiveShape; >>> that.inactiveColor = spec.inactiveColor; >>> that.activeShape = spec.activeShape; >>> that.activeColor = spec.activeColor; >>> var velocityScale = 3; >>> that.insideCheW = function() { --- that.nearestPhosphate = that.findNeighbor(function(neighbor) { --- return neighbor.type === 'phosphate' && !(neighbor.state === 'bound'); }); --- if (exists(that.nearestPhosphate)) { --- var distance = that.distance(that.nearestPhosphate); --- if (distance < 50) { --- that.phosphorylate(that.nearestPhosphate); --- } else { --- that.nearestPhosphate.pull(that); } } }; >>> that.phosphorylate = function(phosph) { --- that.phosphate = phosph; --- that.attach(that.phosphate); --- that.tweenColor(that.activeColor, phosphorylationCycles); --- that.tweenShape(that.activeShape, phosphorylationCycles); --- that.phosphate.phosphorylate(that); --- that.future.append(function(self) { --- self.velocity = self.activeCheW.to(self).scaleTo(velocityScale); }); --- that.state = 'bound'; }; >>> that.hold = function() { --- that.velocity = $V([0, 0]); --- that.state = 'waiting'; }; >>> that.waiting = function(env) { }; >>> that.dephosphorylate = function() { --- that.tweenColor(that.inactiveColor, phosphorylationCycles); --- that.tweenShape(that.inactiveShape, phosphorylationCycles); --- that.phosphate.dephosphorylate(that); --- that.future.append(function(self) { --- self.velocity = $V([Math.random() - 0.5, Math.random() - 0.5]).scaleTo(velocityScale); }); --- that.detach(that.phosphate); --- that.state = 'identifying'; }; >>> return that; }; >>> var cheY = function(spec) { >>> spec.type = 'cheY'; >>> var velocityScale = 3; >>> spec.activeColor = spec.activeColor || $V([150, 180, 190, 1]); >>> spec.inactiveColor = spec.inactiveColor || $V([40, 58, 64, 1]); >>> spec.activeShape = spec.activeShape || flux.shape({ops: [ {op: 'move', to: $V([-20, 0])}, {op: 'bezier', to: $V([0, 3]), control1: $V([-10, 4]), control2: $V([-10, 4])}, {op: 'bezier', to: $V([13, 19]), control1: $V([5, 17]), control2: $V([11, 20])}, {op: 'bezier', to: $V([5, 0]), control1: $V([11, 11]), control2: $V([11, 9])}, {op: 'bezier', to: $V([13, -19]), control1: $V([11, -9]), control2: $V([11, -11])}, {op: 'bezier', to: $V([0, -3]), control1: $V([11, -20]), control2: $V([5, -17])}, {op: 'bezier', to: $V([-20, 0]), control1: $V([-10, -4]), control2: $V([-10, -4])} ]}); >>> spec.inactiveShape = spec.inactiveShape || flux.shape({ops: [ {op: 'move', to: $V([-20, 0])}, {op: 'bezier', to: $V([-8, 0]), control1: $V([-20, 15]), control2: $V([-0, 5])}, {op: 'bezier', to: $V([11, 10]), control1: $V([5, 10]), control2: $V([11, 10])}, {op: 'bezier', to: $V([20, 0]), control1: $V([20, 0]), control2: $V([20, 0])}, {op: 'bezier', to: $V([11, -10]), control1: $V([20, -0]), control2: $V([20, -0])}, {op: 'bezier', to: $V([-8, 0]), control1: $V([11, -10]), control2: $V([5, -10])}, {op: 'bezier', to: $V([-20, 0]), control1: $V([-0, -5]), control2: $V([-20, -15])} ]}); >>> spec.rotation = Math.random()*0.02-0.01; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = cheWActor(spec); >>> return that; }; >>> var cheZ = function(spec) { >>> spec.type = 'cheZ'; >>> spec.inactiveColor = spec.inactiveColor || $V([220, 30, 20, 1]); >>> spec.activeColor = spec.activeColor || $V([250, 140, 50, 1]); >>> spec.inactiveShape = spec.inactiveShape || flux.shape({ops: [ {op: 'move', to: $V([-15, -15])}, {op: 'line', to: $V([15, -15])}, {op: 'line', to: $V([-5, 10])}, {op: 'line', to: $V([15, 10])}, {op: 'line', to: $V([15, 15])}, {op: 'line', to: $V([-15, 15])}, {op: 'line', to: $V([5, -10])}, {op: 'line', to: $V([-15, -10])} ]}); >>> spec.activeShape = spec.activeShape || flux.shape({ops: [ {op: 'move', to: $V([-15, -6])}, {op: 'line', to: $V([15, -6])}, {op: 'line', to: $V([-5, 1])}, {op: 'line', to: $V([15, 1])}, {op: 'line', to: $V([15, 6])}, {op: 'line', to: $V([-15, 6])}, {op: 'line', to: $V([5, -1])}, {op: 'line', to: $V([-15, -1])} ]}); >>> spec.color = spec.inactiveColor.dup(); >>> spec.shape = spec.inactiveShape.dup(); >>> spec.rotation = Math.random()*0.02-0.01; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = molecule(spec); >>> that.inactiveColor = spec.inactiveColor; >>> that.inactiveShape = spec.inactiveShape; >>> that.activeColor = spec.activeColor; >>> that.activeShape = spec.activeShape; >>> that.phosphorylated = null; >>> that.active = function(env) {}; >>> that.avoidCheW = function() { >>> var cheWNeighbor = that.findNeighbor(function(neighbor) { >>> return neighbor.type === 'cheW'; }); >>> if (cheWNeighbor) { >>> that.future.append(function(self) { >>> that.velocity = that.velocity.subtract(that.to(cheWNeighbor)).scaleTo(globalVelocity); }); } >>> return cheWNeighbor; }; >>> that.seek = function(env) { >>> var cheWNeighbor = that.avoidCheW(); >>> if (cheWNeighbor) { >>> } else { >>> that.phosphorylated = that.findNeighbor(function(neighbor) { >>> return neighbor.type === 'phosphate' && neighbor.enzyme ; }); >>> if (that.phosphorylated) { --- that.state = 'target'; } } }; >>> that.target = function(env) { --- var cheWNeighbor = that.avoidCheW(); --- if (cheWNeighbor) { --- } else if (!that.phosphorylated.enzyme || that.phosphorylated.enzyme.state === 'waiting') { --- that.phosphorylated = null; --- that.state = 'seek'; --- } else { --- var distance = that.distance(that.phosphorylated); --- if (distance < 20) { --- that.state = 'cut'; --- that.perceive(env); --- } else { --- that.future.append(function(self) { --- that.velocity = that.velocity.add(that.to(that.phosphorylated)).scaleTo(globalVelocity); }); } } }; >>> that.cut = function(env) { --- that.tweenShape(that.activeShape, phosphorylationCycles/5); --- that.tweenColor(that.activeColor, phosphorylationCycles/5); --- that.tweenEvent(function() {that.state = 'uncut';}, phosphorylationCycles/5); --- that.velocity = $V([0, 0]); --- that.future = []; --- that.phosphorylated.enzyme.hold(); --- that.state = 'active'; }; >>> that.uncut = function() { --- if (that.phosphorylated) { --- that.phosphorylated.enzyme.dephosphorylate(); --- that.tweenShape(that.inactiveShape, phosphorylationCycles); --- that.tweenColor(that.inactiveColor, phosphorylationCycles); --- that.velocity = $V([Math.random() - 0.5, Math.random() - 0.5]).scaleTo(globalVelocity); --- that.phosphorylated = null; --- that.state = 'seek'; } }; >>> that.state = 'seek'; >>> return that; }; >>> var cheB = function(spec) { >>> spec.type = 'cheB'; >>> spec.activeColor = spec.activeColor || $V([100, 140, 230, 1]); >>> spec.inactiveColor = spec.inactiveColor || $V([80, 80, 90, 1]); >>> spec.inactiveShape = spec.inactiveShape || flux.shape({ops: [ {op: 'move', to: $V([-15, -15])}, {op: 'line', to: $V([0, -15])}, {op: 'line', to: $V([15, -15])}, {op: 'bezier', to: $V([0, -5]), control1: $V([15, 15]), control2: $V([0, 15])}, {op: 'bezier', to: $V([-15, -15]), control1: $V([0, 15]), control2: $V([-15, 15])} ]}); >>> spec.activeShape = spec.activeShape || flux.shape({ops: [ {op: 'move', to: $V([-11, -25])}, {op: 'line', to: $V([0, -12])}, {op: 'line', to: $V([11, -25])}, {op: 'bezier', to: $V([0, -5]), control1: $V([25, -16]), control2: $V([30, 25])}, {op: 'bezier', to: $V([-11, -25]), control1: $V([-30, 25]), control2: $V([-25, -16])} ]}); >>> spec.rotation = Math.random()*0.02-0.01; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = cheWActor(spec); >>> that.bound = function(env) { --- that.methylNeighbor = that.findNeighbor(function(neighbor) { --- return neighbor.type === 'methyl' && neighbor.state === 'bound' && neighbor.column.state === 'active' && (neighbor.column != that.lastColumn); }); --- if (that.methylNeighbor) { --- that.state = 'targeting'; --- that.column = methylNeighbor.column; } }; >>> that.targeting = function(env) { --- if (that.methylNeighbor.column.state === 'inactive') { --- that.methylNeighbor = null; --- that.state = 'bound'; --- } else if (that.distance(that.methylNeighbor) < 30) { --- that.methylNeighbor.cut(); --- that.state = 'bound'; --- that.lastColumn = that.column; --- that.column = null; --- } else { --- that.future.append(function(self) { --- self.velocity = self.to(self.methylNeighbor).scaleTo(5); }); } }; >>> return that; }; >>> var cheR = function(spec) { >>> spec.type = 'cheR'; >>> spec.color = spec.color || $V([180, 180, 220, 1]); >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-15, -15])}, {op: 'line', to: $V([15, -15])}, {op: 'line', to: $V([15, -10])}, {op: 'bezier', to: $V([0, -5]), control1: $V([15, 15]), control2: $V([0, 15])}, {op: 'line', to: $V([-10, -5])}, {op: 'line', to: $V([-10, 15])}, {op: 'line', to: $V([-15, 15])} ]}); >>> spec.rotation = Math.random()*0.02-0.01; >>> spec.velocity = $V([Math.random()-0.5, Math.random()-0.5]).x(globalVelocity); >>> var that = molecule(spec); >>> that.methylNeighbor = null; >>> that.cheWNeighbor = null; >>> that.lastCheW = null; >>> that.state = 'looking'; >>> that.looking = function(env) { >>> that.methylNeighbor = that.findNeighbor(function(neighbor) { >>> return neighbor.type === 'methyl' && neighbor.state === 'free'; }); >>> that.cheWNeighbor = that.findNeighbor(function(neighbor) { >>> return neighbor.type === 'cheW' && (neighbor != that.lastCheW); }); >>> if (that.methylNeighbor && that.cheWNeighbor && that.cheWNeighbor.column.openMethylSites.length > 0) { >>> var column = that.cheWNeighbor.column; >>> that.targetSite = column.claimMethylSite(); >>> that.methylNeighbor.bind(that, that.targetSite); >>> that.velocity = $V([0, 0]); >>> that.tweenPos(column.extrovert(that.cheWNeighbor.pos), phosphorylationCycles*2, function() { --- that.state = 'looking'; --- that.future.append(function() { --- that.velocity = $V([Math.random()-0.5, Math.random()-0.5]).scaleTo(globalVelocity); }); }); >>> that.lastCheW = that.cheWNeighbor; >>> that.methylNeighbor = null; >>> that.cheWNeighbor = null; >>> that.state = 'binding'; } }; >>> that.binding = function(env) { }; >>> return that; }; >>> var flagella = function(spec) { --- spec.type = 'flagella'; // spec.color = spec.color || $V([60, 70, 170, 1]); --- spec.color = spec.color || $V([20, 30, 70, 1]); --- spec.revertingshape = spec.shape || flux.shape({ops: [ {op: 'move', to: $V([-50, -110])}, {op: 'line', to: $V([30, -100])}, {op: 'line', to: $V([30, -40])}, {op: 'line', to: $V([60, -40])}, {op: 'line', to: $V([60, -70])}, {op: 'bezier', to: $V([1100, -10]), control1: $V([400, -270]), control2: $V([700, -250])}, {op: 'bezier', to: $V([2700, -60]), control1: $V([1700, 260]), control2: $V([2200, 260])}, {op: 'bezier', to: $V([3400, 0]), control1: $V([2900, -180]), control2: $V([3000, -150])}, {op: 'bezier', to: $V([2700, 50]), control1: $V([3000, -80]), control2: $V([2900, -80])}, {op: 'bezier', to: $V([1100, 150]), control1: $V([2300, 370]), control2: $V([1700, 370])}, {op: 'bezier', to: $V([60, 100]), control1: $V([700, -70]), control2: $V([400, -40])}, {op: 'line', to: $V([60, 40])}, {op: 'line', to: $V([30, 40])}, {op: 'line', to: $V([30, 100])}, {op: 'line', to: $V([-50, 110])} ]}); --- spec.waxingshape = flux.shape({ops: [ {op: 'move', to: $V([-50, -110])}, {op: 'line', to: $V([30, -100])}, {op: 'line', to: $V([30, -40])}, {op: 'line', to: $V([60, -40])}, {op: 'line', to: $V([60, -70])}, {op: 'bezier', to: $V([1100, -50]), control1: $V([400, -80]), control2: $V([700, -80])}, {op: 'bezier', to: $V([2700, -40]), control1: $V([1700, 10]), control2: $V([2200, 10])}, {op: 'bezier', to: $V([3400, -30]), control1: $V([2900, -60]), control2: $V([3000, -50])}, {op: 'bezier', to: $V([2700, 30]), control1: $V([3000, 60]), control2: $V([2900, 80])}, {op: 'bezier', to: $V([1100, 40]), control1: $V([2300, 20]), control2: $V([1700, 30])}, {op: 'bezier', to: $V([60, 50]), control1: $V([700, 80]), control2: $V([400, 80])}, {op: 'line', to: $V([60, 40])}, {op: 'line', to: $V([30, 40])}, {op: 'line', to: $V([30, 100])}, {op: 'line', to: $V([-50, 110])} ]}); --- spec.invertingshape = flux.shape({ops: [ {op: 'move', to: $V([-50, -110])}, {op: 'line', to: $V([30, -100])}, {op: 'line', to: $V([30, -40])}, {op: 'line', to: $V([60, -40])}, {op: 'line', to: $V([60, -70])}, {op: 'bezier', to: $V([1100, 10]), control1: $V([400, 270]), control2: $V([700, 250])}, {op: 'bezier', to: $V([2700, 60]), control1: $V([1700, -260]), control2: $V([2200, -260])}, {op: 'bezier', to: $V([3400, 0]), control1: $V([2900, 180]), control2: $V([3000, 150])}, {op: 'bezier', to: $V([2700, -50]), control1: $V([3000, 80]), control2: $V([2900, 80])}, {op: 'bezier', to: $V([1100, -150]), control1: $V([2300, -370]), control2: $V([1700, -370])}, {op: 'bezier', to: $V([60, -100]), control1: $V([700, 70]), control2: $V([400, 40])}, {op: 'line', to: $V([60, 40])}, {op: 'line', to: $V([30, 40])}, {op: 'line', to: $V([30, 100])}, {op: 'line', to: $V([-50, 110])} ]}); --- spec.waningshape = flux.shape({ops: [ {op: 'move', to: $V([-50, -110])}, {op: 'line', to: $V([30, -100])}, {op: 'line', to: $V([30, -40])}, {op: 'line', to: $V([60, -40])}, {op: 'line', to: $V([60, -70])}, {op: 'bezier', to: $V([1100, 50]), control1: $V([400, 20]), control2: $V([700, 10])}, {op: 'bezier', to: $V([2700, 40]), control1: $V([1700, 80]), control2: $V([2200, 90])}, {op: 'bezier', to: $V([3400, 30]), control1: $V([2900, 0]), control2: $V([3000, 10])}, {op: 'bezier', to: $V([2700, -30]), control1: $V([3000, 0]), control2: $V([2900, 0])}, {op: 'bezier', to: $V([1100, -40]), control1: $V([2300, -90]), control2: $V([1700, -80])}, {op: 'bezier', to: $V([60, 50]), control1: $V([700, -10]), control2: $V([400, -20])}, {op: 'line', to: $V([60, 40])}, {op: 'line', to: $V([30, 40])}, {op: 'line', to: $V([30, 100])}, {op: 'line', to: $V([-50, 110])} ]}); --- spec.shape = spec.revertingshape.dup(); --- var that = molecule(spec); --- var cycle = 3; --- var theta = 0; --- var phases = ['waxing', 'inverting', 'waning', 'reverting']; --- var phase = 0; --- that.state = phases[phase]; --- that.tweenShape(spec[that.state + 'shape'], cycle); --- that.statemaker = function(symbol) { --- var state = function(env) { --- if (theta < cycle) { --- theta += 1; --- } else { --- phase += 1; --- if (phase >= phases.length) { --- phase = 0; } --- that.state = symbol; --- that.tweenShape(spec[that.state + 'shape'], cycle); --- theta = 0; } }; --- return state; }; --- var index = 0; --- phases.each(function(p) { --- index += 1; --- var next = phases[index % phases.length]; --- that[p] = that.statemaker(next); }); --- return that; }; >>> var ligands = { attractant: [], repellent: [] }; >>> $R(0, 30).map(function(index) { >>> var one = randomLigand(); >>> ligands[one.type].append(one.ligand); }); >>> var membranes = [membrane({pos: $V([0, 985]), orientation: 0})]; >>> var visible = { ligand: ligands, membrane: membranes }; >>> var focusGroups = [ {name: 'membrane', path: 'membrane'}, {name: 'column', path: 'membrane.0.columns'}, // {name: 'flagella', path: 'membrane.0.flagella'}, {name: 'repellent', path: 'ligand.repellent'}, {name: 'attractant', path: 'ligand.attractant'}, {name: 'cheW', path: 'membrane.0.cheWs'}, {name: 'phosphate', path: 'membrane.0.phosphates'}, {name: 'cheY', path: 'membrane.0.cheYs'}, {name: 'cheZ', path: 'membrane.0.cheZs'}, {name: 'methyl', path: 'membrane.0.methyls'}, {name: 'cheB', path: 'membrane.0.cheBs'}, {name: 'cheR', path: 'membrane.0.cheRs'} ]; >>> focusGroups.arrange = function() { // arrange the descriptions in a circle >>> var wedge = Math.PI*2*(1.0/focusGroups.length); >>> var third = Math.PI*2.0/3; >>> var outwards = $V([0.42, 0.22]); >>> var zero = $V([0, 0]); >>> var center = $V([0.245, 0.26]); >>> $V([250, 240, 30, 1]); >>> var colorWheel = function(phase) { >>> return Math.floor(140 + (Math.sin(phase)*60)); }; >>> focusGroups.each(function(group, index) { >>> var around = wedge*index; >>> var color = [around, around+(2*third), around+third].map(function(phase) { >>> return colorWheel(phase); }); >>> color.append(1); >>> group.outer = outwards.rotate(around, center).times($V([1, 1.7])); >>> group.descriptionColor = $V(color); }); }; >>> focusGroups.arrange(); // descriptive menu ------------- >>> var moleculeFocus = function(group) { }; >>> var moleculeKey = function() { >>> var keyspec = { pos: $V([0.72, 0.1]), shape: flux.shape({ops: [ {op: 'move', to: $V([0, 0])}, {op: 'line', to: $V([200, 0])}, {op: 'line', to: $V([200, 410])}, {op: 'line', to: $V([0, 410])} ]}), orientation: 0, lineWidth: 2, outline: $V([170, 170, 170, 1]), color: $V([0, 0, 0, 1]), transform: 'screen' }; >>> var key = flux.mote(keyspec); >>> var description = function(spec) { >>> spec.orientation = 0; >>> spec.fill = 'stroke'; >>> spec.lineWidth = 2; >>> spec.transform = 'screen'; >>> var desc = flux.mote(spec); >>> desc.setDescription = function(description) { >>> var text = desc.findText(description); >>> var background = text.box.scale(1.1).shapeFor(); >>> background.color = $V([20, 20, 20, 1]); >>> desc.description = description; >>> desc.shapes = [background, text]; >>> desc.findBox(); }; >>> desc.findText = function(string) { >>> var ops = string.split('\n').map(function(line, index) { >>> return {op: 'text', to: desc.pos.add($V([0, index*23])), size: 12, string: line}; }); >>> return flux.shape({ops: ops, fill: 'stroke'}); }; >>> desc.setDescription(spec.description); >>> desc.item = spec.item; >>> desc.mouseDown = desc.item.hideDescription; >>> return desc; }; >>> var keyitem = function(spec) { >>> var inactiveColor = spec.inactiveColor || $V([110, 130, 210, 1]); >>> var activeColor = $V([230, 230, 230, 1]); >>> spec.color = spec.color || inactiveColor.dup(); >>> spec.orientation = 0; >>> spec.fill = 'stroke'; >>> spec.shape = spec.shape || flux.shape({ops: [ {op: 'text', to: $V([0, 0]), size: 14, string: spec.name} ], fill: 'stroke'}); >>> var item = flux.mote(spec); >>> item.name = spec.name; >>> item.path = spec.path; >>> item.active = false; >>> item.outer = spec.outer || $V([5000, 0]); >>> item.descriptionColor = spec.descriptionColor || $V([250, 240, 30, 1]); >>> item.description = description({ item: item, pos: item.outer, color: item.descriptionColor, description: descriptions[item.name] || '' }); >>> item.changeText = function(text) { --- item.shapes = [flux.shape({ops: [ {op: 'text', to: $V([0, 0]), size: 14, string: text} ], fill: 'stroke'})]; }; >>> item.activate = function() { >>> if (!item.active) { >>> item.tweens = []; >>> item.tweenColor(activeColor, 3); >>> item.tweenScale($V([1.05, 1.05]), 3); >>> item.active = true; } }; >>> item.deactivate = function() { --- if (item.active) { --- item.tweens = []; --- item.tweenColor(inactiveColor, 3); --- item.tweenScale($V([1, 1]), 3); --- item.active = false; } }; >>> item.showDescription = function(info) { --- if (info) { --- item.description.setDescription(info + descriptions[item.name]); } --- world.addActiveDescription(item.description); }; >>> item.hideDescription = function(info) { --- if (info) { --- item.description.setDescription(descriptions[item.name]); } --- world.removeActiveDescription(); }; >>> item.mouseDownDescription = function() { --- item.showDescription(); }; >>> item.mouseUpDescription = function() { --- item.hideDescription(); }; >>> if (!spec.inactive) { >>> item.mouseIn = item.activate; >>> item.mouseOut = item.deactivate; >>> item.mouseDown = item.mouseDownDescription; >>> item.mouseUp = item.mouseUpDescription; } >>> return item; }; >>> var homeostatic = keyitem({ name: 'homeostasis', pos: $V([10, 20]), outer: $V([0.2, 0.05]), inactiveColor: $V([150, 150, 110, 1]), descriptionColor: $V([240, 230, 170, 1]) }); >>> var about = keyitem({ name: 'about', pos: $V([10, 50]), outer: $V([0.2, 0.7]), inactiveColor: $V([150, 150, 110, 1]), descriptionColor: $V([150, 150, 210, 1]) }); >>> var divider = keyitem({ name: '______________________________', pos: $V([-35, 70]), outer: $V([0.5, 0.5]), inactive: true, inactiveColor: $V([210, 110, 110, 1]), descriptionColor: $V([150, 150, 210, 1]) }); >>> divider.activate = function() { --- divider.changeText('__________________hide________'); }; >>> divider.deactivate = function() { --- divider.changeText('______________________________'); }; >>> var hideCycle = 7; >>> divider.hide = function() { --- key.tweenPos($V([0.72, -0.9]), hideCycle); }; >>> divider.show = function() { --- key.tweenPos($V([0.72, 0.1]), hideCycle); }; >>> divider.mouseIn = divider.activate; >>> divider.mouseOut = divider.deactivate; >>> divider.mouseDown = divider.hide; >>> divider.mouseUp = divider.hide; >>> key.itemhash = {}; >>> key.keyitems = [homeostatic, about, divider].concat(focusGroups.map(function(group, index) { >>> group.pos = $V([10, index*30+100]); >>> var item = keyitem(group); >>> key.itemhash[group.name] = item; >>> return item; })); >>> key.addSubmotes(key.keyitems); >>> return key; }(); // creation of flux canvas ------------------- >>> var spec = { id: id, motes: membranes.concat(ligands.attractant).concat(ligands.repellent).append(moleculeKey), scale: $V([0.17, 0.17]), translation: $V([500, 200]), // translation: $V([0, 200]), --- move: function(mouse) { --- if (mouse.down) { --- world.removeActiveDescription(); --- this.translation = this.translation.add(mouse.screen.subtract(mouse.prevscreen)); --- dragging = true; } }, --- keyDown: function(that, key) { --- var base = 1.25; --- if (key == 79) { --- var scale = Math.pow(base, -1); --- that.zoom(scale); } --- if (key == 73) { --- var scale = Math.pow(base, 1); --- that.zoom(scale); } }, // delta is either 1 or -1, which is the exponent of the scaling constant // signifying either the number or its inverse. --- wheel: function(that, delta) { --- var scale = Math.pow(1.007, delta); --- that.zoom(scale); } }; >>> var world = flux.canvas(spec); >>> world.activeDescription = null; >>> world.addActiveDescription = function(description) { --- world.removeActiveDescription(); --- world.addMote(description); --- world.activeDescription = description; }; >>> world.removeActiveDescription = function() { --- if (world.activeDescription) { --- world.removeMote(world.activeDescription); --- world.activeDescription = null; } }; // for testing >>> world.membrane = membranes[0]; >>> world.key = moleculeKey; >>> return world; }; === Inline script in: file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/index.html === >>> h = homeostasis("homeostasis"); >>> window.onload = h.init; Total lines (including un-executable): 4119 Total executable lines: 2037 Covered lines: 1271 Coverage: ~62% Errors:17 errors/warningsh in the script: CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=true, button=1, clientX=175, clientY=155, ctrlKey=true, detail=3, metaKey=true, screenX=1000, screenY=512, shiftKey=true], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=true, button=0, clientX=180, clientY=297, ctrlKey=true, detail=2, metaKey=true, screenX=706, screenY=422, shiftKey=true], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=20, clientY=343, ctrlKey=false, detail=4, metaKey=false, screenX=23, screenY=377, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=246, clientY=7, ctrlKey=true, detail=4, metaKey=false, screenX=422, screenY=272, shiftKey=true], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=261, clientY=319, ctrlKey=true, detail=0, metaKey=false, screenX=316, screenY=347, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=246, clientY=7, ctrlKey=true, detail=4, metaKey=false, screenX=422, screenY=272, shiftKey=true], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=13, clientY=91, ctrlKey=false, detail=3, metaKey=false, screenX=45, screenY=19, shiftKey=true], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=261, clientY=319, ctrlKey=true, detail=0, metaKey=false, screenX=316, screenY=347, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmouseup}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=1, clientX=246, clientY=7, ctrlKey=true, detail=4, metaKey=false, screenX=422, screenY=272, shiftKey=true], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]]CRASH - TypeError: Cannot call method "activate" of undefined (file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307)(file:///Users/simonhj/Documents/workspace/JSTester/test/webapps/ClientSideOnly/homeostasis/enumerable.js#307) Chain: EventChain [event_chain=[EventInfo [evt_handler={element=null, event name=INIT}, evt_input=null], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onclick}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler=Timeout, id: 0, evt_input=EventInput [eventObjectInput=null, formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousedown}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]], EventInfo [evt_handler={element=ElementDescriptor: [1, 1] id: homeostasis, event name=onmousemove}, evt_input=EventInput [eventObjectInput=MouseEventObjectInput [altKey=false, button=0, clientX=0, clientY=0, ctrlKey=false, detail=1, metaKey=false, screenX=0, screenY=0, shiftKey=false], formState={}]]]