language-ecmascript 0.9 → 0.9.1
raw patch · 11 files changed
+2590/−6 lines, 11 filesdep ~data-defaultPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: data-default
API changes (from Hackage documentation)
Files
- CHANGELOG +5/−0
- language-ecmascript.cabal +7/−6
- tests/parse-pretty/add.js +1/−0
- tests/parse-pretty/do-while.js +3/−0
- tests/parse-pretty/flapjax-fxinternal-22dec2008.js +2552/−0
- tests/parse-pretty/neg.js +2/−0
- tests/parse-pretty/numbers.js +2/−0
- tests/parse-pretty/object-lit-1.js +4/−0
- tests/parse-pretty/object-lit-2.js +4/−0
- tests/parse-pretty/prefix-chain.js +4/−0
- tests/parse-pretty/strings.js +6/−0
+ CHANGELOG view
@@ -0,0 +1,5 @@+Version change log.++=0.9.1= +Increased the upper bound on data-default in dependencies. See+https://github.com/jswebtools/language-ecmascript/pull/5
language-ecmascript.cabal view
@@ -1,5 +1,5 @@ Name: language-ecmascript-Version: 0.9+Version: 0.9.1 Cabal-Version: >= 1.10 Copyright: (c) 2007-2012 Brown University, (c) 2008-2010 Claudiu Saftoiu, (c) 2012 Stevens Institute of Technology@@ -10,8 +10,9 @@ Maintainer: Andrey Chudnov <oss@chudnov.com> Homepage: http://github.com/jswebtools/language-ecmascript Bug-reports: http://github.com/jswebtools/language-ecmascript/issues-Stability: provisional-Tested-with: GHC==7.0.4, GHC==7.4.1+Stability: experimental+Tested-with: GHC==7.4.1+Extra-Source-Files: tests/parse-pretty/*.js, CHANGELOG Category: Language Build-Type: Simple Synopsis: JavaScript analysis tools@@ -20,7 +21,7 @@ Includes a parser, pretty-printer, and basic building blocks for more sophisticated tools. - This package supercedes package WebBits.+ This package used to be called WebBits. Source-repository head type: git@@ -42,7 +43,7 @@ containers >= 0.1, syb >= 0.1, uniplate >= 1.6 && <1.7,- data-default >= 0.4 && <0.5+ data-default >= 0.4 && <0.6 ghc-options: -fwarn-incomplete-patterns Exposed-Modules:@@ -72,7 +73,7 @@ directory, filepath, HUnit,- data-default >=0.4 && <0.5+ data-default >=0.4 && <0.6 Default-Extensions: DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts Default-Language: Haskell2010 ghc-options:
+ tests/parse-pretty/add.js view
@@ -0,0 +1,1 @@+1+2;;;;
+ tests/parse-pretty/do-while.js view
@@ -0,0 +1,3 @@+do {+ x = y;+} while (element);
+ tests/parse-pretty/flapjax-fxinternal-22dec2008.js view
@@ -0,0 +1,2552 @@+function flapjaxInit(options) {+ // compress via http://alex.dojotoolkit.org/shrinksafe/+ // make sure to change final eval call to use exported library renamed + // name+ + var defaultOptions = {+ includeSynonyms: true,+ exportMisc: true,+ exportCore: true,+ exportDOM: true,+ exportDOMMisc: true,+ exportWS: true,+ hide: [ ],+ show: [ ],+ redefine: false,+ };+ + if (options === false) {+ options = { hide: [ ], show: [ ] };+ }+ else if (options === true || !options) {+ options = { };+ }++ // Fill in any missing options using the defaults.+ for (var option in defaultOptions) {+ if (options[option] === undefined) {+ options[option] = defaultOptions[option];+ }+ };+ + // Transform hide and show lists into tables+ var hideArray = options.hide;+ options.hide = { };+ for (var i = 0; i < hideArray.length; i++) {+ options.hide[hideArray[i]] = true;+ }+ var showArray = options.show;+ options.show = { };+ for (var i = 0; i < showArray.length; i++) {+ options.show[showArray[i]] = true;+ }+ + var warn = function(s) {+ /*if (console && console.warn) {+ console.warn(s);+ }*/+ };+ + + var flapjax = { + version: 4, + base: {}, //pulses+ combinators: {}, // combinators yielding nodes+ behaviours: {},+ dom: {} // dom convenience methods and combinators+ };+ + var d = flapjax.dom;+ + flapjax.pub = {util:flapjax};+ + var annotate = function(fn,names,protoArg,protoObjs,protoNames) {+ for(var i=0; i<names.length;i++) {+ flapjax.pub[names[i]] = fn;+ }+ if(protoArg != undefined) {+ var pf = function() {+ var args = slice(arguments,0);+ args.splice(protoArg,0,this);+ return fn.apply(this,args);+ }+ for(var i=0; i<protoObjs.length; i++) {+ for(var j=0; j<protoNames.length;j++) {+ protoObjs[i][protoNames[j]] = pf;+ }+ }+ }+ }+ + var exports = { };+ var synonyms = { };++ var misc = { }; /* Used as a symbol */+ var core = { }; /* Used as a symbol */+ var dom = { }; /* Used as a symbol */+ var domMisc = { }; /* Used as a symbol */+ var ws = { }; /* Used as a symbol */+ + var fxExport = function(exportCategory,exportVal,+ exportName /* , synonyms */) {+ if (!(exportCategory instanceof Object)) {+ throw 'fxExport: category is ' + exportCategory;+ };++ if (typeof(exportName) != 'string') {+ console.log(exportVal);+ throw 'fxExport: name is ' + exportName; + };++ exportVal.__flapjaxCategory = exportCategory;+ exports[exportName] = exportVal;+ for (var i = 3; i < arguments.length; i++) {+ exports[arguments[i]] = exportVal;+ synonyms[arguments[i]] = true;+ }+ }+ + var fxMethodSynonyms = function(obj,method) {+ if (options.includeSynonyms === true) {+ for (var i = 2; i < arguments.length; i++) {+ obj.prototype[arguments[i]] = obj.prototype[method];+ };+ };+ };+ + //////////////////////////////////////////////////////////////////////////////+ // Miscellaneous functions+ + //credit 4umi+ //slice: Array a * Integer * Integer -> Array a+ var slice = function (arr, start, stop) {+ var i, len = arr.length, r = [];+ if( !stop ) { stop = len; }+ if( stop < 0 ) { stop = len + stop; }+ if( start < 0 ) { start = len - start; }+ if( stop < start ) { i = start; start = stop; stop = i; }+ for( i = 0; i < stop - start; i++ ) { r[i] = arr[start+i]; }+ return r;+ }+ + var isEqual = function (a,b) {+ return (a == b) ||+ ( (((typeof(a) == 'number') && isNaN(a)) || a == 'NaN') &&+ (((typeof(b) == 'number') && isNaN(b)) || b == 'NaN') );+ };++ //member: a * Array b -> Boolean+ var member = function(elt, lst) {+ for (var i = 0; i < lst.length; i++) { + if (isEqual(lst[i], elt)) {return true;} + }+ return false;+ };+ + var zip = function(arrays) {+ if (arrays.length == 0) return [];+ var ret = [];+ for(var i=0; i<arrays[0].length;i++) {+ ret.push([]);+ for(var j=0; j<arrays.length;j++) + ret[i].push(arrays[j][i]);+ }+ return ret;+ }++ //map: (a * ... -> z) * [a] * ... -> [z]+ var map = function (fn) {+ var arrays = slice(arguments, 1);+ if (arrays.length === 0) { return []; }+ else if (arrays.length === 1) {+ var ret = [];+ for(var i=0; i<arrays[0].length; i++) {ret.push(fn(arrays[0][i]));}+ return ret;+ }+ else {+ var ret = zip(arrays);+ var o = new Object();+ for(var i=0; i<ret.length; i++) {ret[i] = fn.apply(o,ret[i]);}+ return ret;+ }+ };+ + //filter: (a -> Boolean) * Array a -> Array a+ var filter = function (predFn, arr) {+ var res = [];+ for (var i = 0; i < arr.length; i++) { + if (predFn(arr[i])) { res.push(arr[i]); }+ }+ return res;+ };+ + //fold: (a * .... * accum -> accum) * accum * [a] * ... -> accum+ //fold over list(s), left to right+ var fold = function(fn, init /* arrays */) {+ var lists = slice(arguments, 2);+ if (lists.length === 0) { return init; }+ else if(lists.length === 1) {+ var acc = init;+ for(var i = 0; i < lists[0].length; i++) {+ acc = fn(lists[0][i],acc);+ }+ return acc;+ }+ else {+ var acc = init;+ for (var i = 0; i < lists[0].length; i++) {+ var args = map( function (lst) { return lst[i];}, + lists);+ args.push(acc);+ acc = fn.apply({}, args);+ }+ return acc;+ }+ };+ + //foldR: (a * .... * accum -> accum) * accum * [a] * ... -> accum+ //fold over list(s), right to left, fold more memory efficient (left to right)+ var foldR = function (fn, init /* arrays */) {+ var lists = slice(arguments, 2);+ if (lists.length === 0) { return init; }+ else if(lists.length === 1) {+ var acc = init;+ for(var i=lists[0].length - 1; i > -1; i--)+ acc = fn(lists[0][i],acc);+ return acc;+ }+ else {+ var acc = init;+ for (var i = lists[0].length - 1; i > -1; i--) {+ var args = map( function (lst) { return lst[i];}, + lists);+ args.push(acc);+ acc = fn.apply({}, args);+ }+ return acc; + }+ };+ + var pushAll = function(destArray,srcArray) {+ for (var i = 0; i < srcArray.length; i++) {+ destArray.push(srcArray[i]);+ }+ return destArray;+ };+ + fxExport(misc,slice,'slice');+ fxExport(misc,member,'member');+ fxExport(misc,map,'map');+ fxExport(misc,map,'forEach');+ fxExport(misc,filter,'filter');+ fxExport(misc,fold,'fold');+ fxExport(misc,foldR,'foldR');+ + //////////////////////////////////////////////////////////////////////////////+ // Flapjax core+ + //Pulse: Stamp * Path * Obj+ var Pulse = function (stamp, value) {+ this.stamp = stamp;+ this.value = value;+ };+++ //Probably can optimize as we expect increasing insert runs etc+ var PQ = function () {+ var ctx = this;+ ctx.val = [];+ this.insert = function (kv) {+ ctx.val.push(kv);+ var kvpos = ctx.val.length-1;+ while(kvpos > 0 && kv.k < ctx.val[Math.floor((kvpos-1)/2)].k) {+ var oldpos = kvpos;+ kvpos = Math.floor((kvpos-1)/2);+ ctx.val[oldpos] = ctx.val[kvpos];+ ctx.val[kvpos] = kv;+ }+ };+ this.isEmpty = function () { + return ctx.val.length === 0; + };+ this.pop = function () {+ if(ctx.val.length == 1) {+ return ctx.val.pop();+ }+ var ret = ctx.val.shift();+ ctx.val.unshift(ctx.val.pop());+ var kvpos = 0;+ var kv = ctx.val[0];+ while(1) {+ var leftChild = (kvpos*2+1 < ctx.val.length ? ctx.val[kvpos*2+1].k : kv.k+1);+ var rightChild = (kvpos*2+2 < ctx.val.length ? ctx.val[kvpos*2+2].k : kv.k+1);+ if(leftChild > kv.k && rightChild > kv.k)+ break;+ else if(leftChild < rightChild) {+ ctx.val[kvpos] = ctx.val[kvpos*2+1];+ ctx.val[kvpos*2+1] = kv;+ kvpos = kvpos*2+1;+ }+ else {+ ctx.val[kvpos] = ctx.val[kvpos*2+2];+ ctx.val[kvpos*2+2] = kv;+ kvpos = kvpos*2+2;+ }+ }+ return ret;+ };+ };+ + var lastRank = 0;+ var stamp = 1;+ var nextStamp = function () { return ++stamp; };+ + //propagatePulse: Pulse * Array Node -> + //Send the pulse to each node + var propagatePulse = function (pulse, node) {+ var queue = new PQ(); //topological queue for current timestep+ queue.insert({k:node.rank,n:node,v:pulse});+ while(!(queue.isEmpty())) {+ var qv = queue.pop();+ qv.n.updater(function(nextPulse) {+ for(var i=0; i<qv.n.sendsTo.length;i++)+ queue.insert({k:qv.n.sendsTo[i].rank,n:qv.n.sendsTo[i],v:nextPulse});+ },new Pulse(qv.v.stamp,qv.v.value));+ }+ };+ + //Event: Array Node b * ( (Pulse a -> Void) * Pulse b -> Void)+ var EventStream = function (nodes,updater) {+ this.updater = updater;+ + this.sendsTo = []; //forward link+ + for (var i = 0; i < nodes.length; i++) {+ nodes[i].sendsTo.push(this);+ }+ + this.rank = ++lastRank;+ };+ EventStream.prototype = new Object();+ + fxExport(core,EventStream,'EventStream');+ + + //createNode: Array Node a * ( (Pulse b ->) * (Pulse a) -> Void) -> Node b+ var createNode = function (nodes, updater) {+ return new EventStream(nodes,updater);+ };+ + //attachListenerNode: Node * Node -> Voids+ //flow from node to dependent+ //note: does not add flow as counting for rank nor updates parent ranks+ var attachListener = function (node, dependent) {+ if (!(node instanceof EventStream)) { throw 'attachListenenerNode: expects event as first arg';} //SAFETY+ if (!(dependent instanceof EventStream)) { throw 'attachListenenerNode: expects event as second arg';} //SAFETY+ + node.sendsTo.push(dependent);+ if(node.rank > dependent.rank) {+ var lowest = lastRank+1;+ var q = [dependent];+ while(q.length) {+ var cur = q.splice(0,1)[0];+ cur.rank = ++lastRank;+ q = q.concat(cur.sendsTo);+ }+ }+ };+ + //removeListenerNode: Node * Node -> Boolean+ //remove flow from node to dependent+ //note: does not remove flow as counting for rank nor updates parent ranks+ var removeListener = function (node, dependent)+ {+ if (!(node instanceof EventStream)) { throw 'removeListenerNode: expects event as first arg';} //SAFETY+ if (!(dependent instanceof EventStream)) { throw 'removeListenenerNode: expects event as second arg';} //SAFETY+ + var foundSending = false;+ for (var i = 0; i < node.sendsTo.length && !foundSending; i++) {+ if (node.sendsTo[i] == dependent) {+ node.sendsTo.splice(i, 1);+ foundSending = true;+ }+ }+ + return foundSending;+ };+ + // An internal_e is a node that simply propagates all pulses it receives. It's used internally by various + // combinators.+ var internal_e = function(dependsOn) {+ return createNode(dependsOn || [ ],function(send,pulse) { send(pulse); });+ }+ + var zero_e = function() {+ return createNode([],function(send,pulse) {+ throw ('zero_e : received a value; zero_e should not receive a value; the value was ' + pulse.value);+ });+ };+ fxExport(core,zero_e,'zero_e');+ + var one_e = function(val) {+ var sent = false;+ var evt = createNode([],function(send,pulse) {+ if (sent) {+ throw ('one_e : received an extra value');+ }+ sent = true;+ send(pulse);+ });+ window.setTimeout(function() { sendEvent(evt,val); },0);+ return evt;+ };+ fxExport(core,one_e,'one_e');+ + // a.k.a. mplus; merge_e(e1,e2) == merge_e(e2,e1)+ var merge_e = function() {+ if (arguments.length == 0) {+ return zero_e();+ }+ else {+ var deps = slice(arguments,0);+ return internal_e(deps);+ }+ };+ fxExport(core,merge_e,'merge_e');++ EventStream.prototype.merge_e = function() {+ var deps = slice(arguments,0);+ deps.push(this);+ return internal_e(deps);+ };+ fxMethodSynonyms(EventStream,'merge_e','merge');++ EventStream.prototype.constant_e = function(constantValue) {+ return createNode([this],function(send,pulse) {+ pulse.value = constantValue;+ send(pulse);+ });+ };+ fxMethodSynonyms(EventStream,'constant_e','constant','replaceValue_e','replaceValue');+ + var constant_e = function(e) { return e.constant_e(); };+ fxExport(core,constant_e,'constant_e','replaceValue_e');+ + var createTimeSyncNode = function(nodes) {+ var nqs = map(function(n) {+ var qpulse = [];+ return {q:qpulse,v:createNode([n],function(s,p) {qpulse.push(p.value); s(p);},nodes)};+ },nodes);+ return createNode(+ map(function(n) {return n.v;},nqs), function(s,p) {+ var allfull = fold(function(n,acc) {return n.q.length && acc;},true,nqs);+ if(allfull) {+ p.value = map(function(n) {return n.q.shift();},nqs);+ s(p);+ }});+ };+ + //This is up here so we can add things to its prototype that are in flapjax.combinators+ var Behaviour = function (event, init, updater) {+ if (!(event instanceof EventStream)) { + throw 'Behaviour: expected event as second arg'; + }+ + var behave = this;+ this.last = init;+ + //sendEvent to this might impact other nodes that depend on this event+ //sendBehaviour defaults to this one+ this.underlyingRaw = event;+ + //unexposed, sendEvent to this will only impact dependents of this behaviour+ this.underlying =+ createNode(+ [event], + (updater ? + function (s, p) {behave.last = updater(p.value); p.value = behave.last; s(p);} : + function (s, p) {behave.last = p.value; s(p);}));+ };+ Behaviour.prototype = new Object();+ fxExport(core,Behaviour,'Behaviour');+ fxExport(core,Behaviour,'Behavior');+ + var receiver_e = function() {+ var evt = internal_e();+ evt.sendEvent = function(value) {+ propagatePulse(new Pulse(nextStamp(), value),evt);+ };+ return evt;+ };+ fxExport(core,receiver_e,'receiver_e');+ + //note that this creates a new timestamp and new event queue+ var sendEvent = function (node, value) {+ if (!(node instanceof EventStream)) { throw 'sendEvent: expected Event as first arg'; } //SAFETY+ + propagatePulse(new Pulse(nextStamp(), value),node);+ };+ fxExport(core,sendEvent,'sendEvent');+ synonyms['sendEvent'] = true; // Hack: sendEvent simply should not be exported; calling it a synonym deprecates it.+ + // bind_e :: EventStream a * (a -> EventStream b) -> EventStream b+ EventStream.prototype.bind_e = function(k) {+ /* m.sendsTo result_e+ * result_e.sendsTo prev_e+ * prev_e.sendsTo return_e+ */+ var m = this;+ var prev_e = false;+ + var out_e = createNode([],function(send,pulse) { send(pulse); });+ out_e.name = "bind out_e";+ + var in_e = createNode([m], function (send,pulse) {+ if (prev_e) { + removeListener(prev_e,out_e);+ }+ prev_e = k(pulse.value);+ if (prev_e instanceof EventStream) {+ attachListener(prev_e,out_e);+ }+ else {+ throw "bind_e : expected EventStream";+ }+ });+ in_e.name = "bind in_e";+ + return out_e;+ };++ /* Could be written as:+ *+ * e.bind_e(function(v) { return one_e(f(v)); })+ */+ EventStream.prototype.lift_e = function(f) {+ if (!(f instanceof Function)) {+ throw ('lift_e : expected a function as the first argument; received ' + f);+ };+ + return createNode([this],function(send,pulse) {+ pulse.value = f(pulse.value);+ send(pulse);+ });+ };+ fxMethodSynonyms(EventStream,'lift_e',+ 'transform_e','map_e','apply_e','lift','transform','map','apply');+ + EventStream.prototype.not_e = function() { return this.lift_e(function(v) { return !v; }); };+ fxMethodSynonyms(EventStream,'not_e','not');+ + var not_e = function(e) { return e.not_e(); };+ fxExport(core,not_e,'not_e','not');+ + EventStream.prototype.filter_e = function(pred) {+ if (!(pred instanceof Function)) {+ throw ('filter_e : expected predicate; received ' + pred);+ };+ + // Can be a bind_e+ return createNode([this],+ function(send,pulse) {+ if (pred(pulse.value)) { send(pulse); }+ });+ };+ fxMethodSynonyms(EventStream,'filter_e','filter');+ + var filter_e = function(e,p) { return e.filter_e(p); };+ fxExport(core,filter_e,'filter_e');+ + // Fires just once.+ EventStream.prototype.once_e = function() {+ var done = false;+ // Alternately: this.collect_e(0,\n v -> (n+1,v)).filter_e(\(n,v) -> n == 1).lift_e(fst)+ return createNode([this],function(send,pulse) {+ if (!done) { done = true; send(pulse); }+ });+ };+ fxMethodSynonyms(EventStream,'once_e','once')+ + var once_e = function(e) { return e.once_e(); };+ fxExport(core,once_e,'once_e');+ + EventStream.prototype.skipFirst_e = function() {+ var skipped = false;+ return createNode([this],function(send,pulse) {+ if (skipped)+ { send(pulse); }+ else+ { skipped = true; }+ });+ };+ fxMethodSynonyms(EventStream,'skipFirst_e','skipFirst');+ + var skipFirst_e = function(e) { return e.skipFirst_e(); };+ fxExport(core,skipFirst_e,'skipFirst_e');+ + EventStream.prototype.collect_e = function(init,fold) {+ var acc = init;+ return this.lift_e(+ function (n) {+ var next = fold(n, acc);+ acc = next;+ return next;+ });+ };+ fxMethodSynonyms(EventStream,'collect_e','collect','transformWithMemory');+ + var collect_e = function(e,i,f) { return e.collect_e(i,f); };+ fxExport(core,collect_e,'collect_e');+ + // a.k.a. join+ EventStream.prototype.switch_e = function() {+ return this.bind_e(function(v) { return v; });+ };+ fxMethodSynonyms(EventStream,'switch_e','forwardLatest');+ + var switch_e = function(e) { return e.switch_e(); };+ fxExport(core,switch_e,'switch_e');+ + EventStream.prototype.if_e = function(thenE,elseE) {+ var testStamp = -1;+ var testValue = false;+ + createNode([this],function(_,pulse) { testStamp = pulse.stamp; testValue = pulse.value; });+ + return merge_e(+ createNode([thenE],function(send,pulse) { if (testValue && (testStamp == pulse.stamp)) { send(pulse); } }),+ createNode([elseE],function(send,pulse) { if (!testValue && (testStamp == pulse.stamp)) { send(pulse); } }));+ };+ fxMethodSynonyms(EventStream,'if_e','choose_e','choose');+ + var if_e = function(test,thenE,elseE) {+ if (test instanceof EventStream)+ { return test.if_e(thenE,elseE); }+ else+ { return test ? thenE : elseE; }+ };+ fxExport(core,if_e,'if_e','choose_e');+ + var cond_e = function (/*. predValArrays */) {+ var predValArrays = slice(arguments, 0);+ var acc = zero_e();+ for (var i = predValArrays.length - 1; i > -1; i--) {+ acc = if_e(predValArrays[i][0],predValArrays[i][1], acc);+ }+ return acc; + };+ fxExport(core,cond_e,'cond_e');+ + var and_e = function (/* . nodes */) {+ var nodes = slice(arguments, 0);+ + var acc = (nodes.length > 0)? + nodes[nodes.length - 1] : one_e(true);+ + for (var i = nodes.length - 2; i > -1; i--) {+ acc = if_e(+ nodes[i], + acc, + nodes[i].constant_e(false));+ }+ return acc;+ };+ fxExport(core,and_e,'and_e');+ + EventStream.prototype.and_e = function( /* others */ ) {+ var deps = [this].concat(slice(arguments,0));+ return and_e.apply(this,deps);+ };+ fxMethodSynonyms(EventStream,'and_e','and');+ + var or_e = function () {+ var nodes = slice(arguments, 0);+ var acc = (nodes.length > 2)? + nodes[nodes.length - 1] : one_e(false); + for (var i = nodes.length - 2; i > -1; i--) {+ acc = if_e(+ nodes[i],+ nodes[i],+ acc);+ }+ return acc;+ };+ fxExport(core,or_e,'or_e');+ + EventStream.prototype.or_e = function(/*others*/) {+ var deps = [this].concat(slice(arguments,0));+ return or_e.apply(this,deps);+ };+ fxMethodSynonyms(EventStream,'or_e','or');+ + var delayStatic_e = function (event, time) {+ + var resE = internal_e();+ + createNode(+ [event],+ function (s, p) { + setTimeout( + function () { sendEvent(resE, p.value);}, + time ); });+ + return resE;+ };+ + //delay_e: Event a * [Behaviour] Number -> Event a+ EventStream.prototype.delay_e = function (time) {+ var event = this;+ + if (time instanceof Behaviour) {+ + var receiverEE = internal_e();+ var link = + {+ from: event, + towards: delayStatic_e(event, valueNow(time))+ };+ + //TODO: Change semantics such that we are always guaranteed to get an event going out?+ var switcherE = + createNode(+ [changes(time)],+ function (s, p) {+ removeListener(link.from, link.towards); + link =+ {+ from: event, + towards: delayStatic_e(event, p.value)+ };+ sendEvent(receiverEE, link.towards);+ });+ + var resE = receiverEE.switch_e();+ + sendEvent(switcherE, valueNow(time));+ return resE;+ + } else { return delayStatic_e(event, time); }+ };+ fxMethodSynonyms(EventStream,'delay_e','delay');+ + var delay_e = function(sourceE,interval) {+ return sourceE.delay_e(interval);+ };+ fxExport(core,delay_e,'delay_e');+ + //lift_e: ([Event] (. Array a -> b)) . Array [Event] a -> [Event] b+ var lift_e = function (fn /*, [node0 | val0], ...*/) {+ // if (!(fn instanceof Function)) { throw 'lift_e: expected fn as second arg'; } //SAFETY+ + var valsOrNodes = slice(arguments, 0);+ //selectors[i]() returns either the node or real val, optimize real vals+ var selectors = [];+ var selectI = 0;+ var nodes = [];+ for (var i = 0; i < valsOrNodes.length; i++) {+ if (valsOrNodes[i] instanceof EventStream) {+ nodes.push(valsOrNodes[i]);+ selectors.push( + (function(ii) {+ return function(realArgs) { + return realArgs[ii];+ };+ })(selectI));+ selectI++;+ } else {+ selectors.push( + (function(aa) { + return function () {+ return aa;+ }; + })(valsOrNodes[i]));+ } + }+ + var context = this;+ var nofnodes = slice(selectors,1);+ + if (nodes.length === 0) {+ return one_e(fn.apply(context, valsOrNodes));+ } else if ((nodes.length === 1) && (fn instanceof Function)) {+ return nodes[0].lift_e(+ function () {+ var args = arguments;+ return fn.apply(+ context, + map(function (s) {return s(args);}, nofnodes));+ });+ } else if (nodes.length === 1) {+ return fn.lift_e(+ function (v) {+ var args = arguments;+ return v.apply(+ context, + map(function (s) {return s(args);}, nofnodes));+ }); + } else if (fn instanceof Function) {+ return createTimeSyncNode(nodes).lift_e(+ function (arr) {+ return fn.apply(+ this,+ map(function (s) { return s(arr); }, nofnodes));+ });+ } else if (fn instanceof EventStream) {+ return createTimeSyncNode(nodes).lift_e(+ function (arr) {+ return arr[0].apply(+ this, + map(function (s) {return s(arr); }, nofnodes));+ });+ } else {throw 'unknown lift_e case';}+ };+ fxExport(core,lift_e,'lift_e','transform_e','map_e','apply_e');+ + EventStream.prototype.snapshot_e = function (valueB) {+ return createNode(+ [this],+ function (s, p) {+ p.value = valueNow(valueB);+ s(p);+ }+ ); + };+ fxMethodSynonyms(EventStream,'snapshot_e','snapshot','takeSnapshot');++ var snapshot_e = function(triggerE,valueB) {+ return triggerE.snapshot_e(valueB);+ };+ fxExport(core,snapshot_e,'snapshot_e');++ EventStream.prototype.filterRepeats_e = function(optStart) {+ var hadFirst = optStart === undefined ? false : true;+ var prev = optStart;+ + return this.filter_e(function (v) {+ if (!hadFirst || !(isEqual(prev,v))) {+ hadFirst = true;+ prev = v;+ return true;+ }+ else {+ return false;+ }+ });+ };+ fxMethodSynonyms(EventStream,'filterRepeats_e','filterRepeats');++ var filterRepeats_e = function(sourceE,optStart) {+ return sourceE.filterRepeats_e(optStart);+ };+ fxExport(core,filterRepeats_e,'filterRepeats_e','filterRepeats');++ //credit Pete Hopkins+ var calmStatic_e = function (triggerE, time) {+ var out = internal_e();+ createNode(+ [triggerE],+ function() {+ var towards = null;+ return function (s, p) {+ if (towards !== null) { clearTimeout(towards); }+ towards = setTimeout( function () { towards = null; sendEvent(out,p.value) }, time );+ };+ }());+ return out;+ };+ + //calm_e: Event a * [Behaviour] Number -> Event a+ EventStream.prototype.calm_e = function(time) {+ if (time instanceof Behaviour) {+ var out = internal_e();+ createNode(+ [this],+ function() {+ var towards = null;+ return function (s, p) {+ if (towards !== null) { clearTimeout(towards); }+ towards = setTimeout( function () { towards = null; sendEvent(out,p.value) }, valueNow(time));+ };+ }());+ return out;+ } else {+ return calmStatic_e(this,time); + }+ };+ fxMethodSynonyms(EventStream,'calm_e','calm');+ + var calm_e = function(sourceE,interval) {+ return sourceE.calm_e(interval);+ };+ fxExport(core,calm_e,'calm_e');+ + EventStream.prototype.blind_e = function (time) {+ return createNode(+ [this],+ function () {+ var intervalFn = + time instanceof Behaviour?+ function () { return valueNow(time); }+ : function () { return time; };+ var lastSent = (new Date()).getTime() - intervalFn() - 1;+ return function (s, p) {+ var curTime = (new Date()).getTime();+ if (curTime - lastSent > intervalFn()) {+ lastSent = curTime;+ s(p);+ }+ };+ }());+ };+ fxMethodSynonyms(EventStream,'blind_e','blind');+ + var blind_e = function(sourceE,interval) {+ return sourceE.blind_e(interval);+ };+ fxExport(core,blind_e,'blind_e');+ + EventStream.prototype.hold = function(init) {+ return new Behaviour(this,init);+ };+ fxMethodSynonyms(EventStream,'hold','startsWith','toBehavior');++ var hold = function(e,init) {+ if (!(e instanceof EventStream)) {+ throw 'hold: expected EventStream; received ' + e;+ }+ return e.hold(init); + };+ fxExport(core,hold,'hold');+ + Behaviour.prototype.valueNow = function() {+ return this.last;+ };+ var valueNow = function(behavior) { return behavior.valueNow(); };+ fxExport(core,valueNow,'valueNow');++ Behaviour.prototype.changes = function() {+ return this.underlying;+ };+ fxMethodSynonyms(Behaviour,'changes','toEvent');+ + var changes = function (behave) { return behave.changes(); }+ fxExport(core,changes,'changes');+ + Behaviour.prototype.switch_b = function() {+ var behaviourCreatorsB = this;+ var init = valueNow(behaviourCreatorsB);+ + var prevSourceE = null;+ + var receiverE = new internal_e();+ + //XXX could result in out-of-order propagation! Fix!+ var makerE = + createNode(+ [changes(behaviourCreatorsB)],+ function (_, p) {+ if (!(p.value instanceof Behaviour)) { throw 'switch_b: expected Behaviour as value of Behaviour of first argument'; } //SAFETY+ if (prevSourceE != null) {+ removeListener(prevSourceE, receiverE);+ }+ + prevSourceE = changes(p.value);+ attachListener(prevSourceE, receiverE);+ + sendEvent(receiverE, valueNow(p.value));+ });+ + if (init instanceof Behaviour) {+ sendEvent(makerE, init);+ }+ + return hold(+ receiverE,+ init instanceof Behaviour? valueNow(init) : init);+ };+ fxMethodSynonyms(Behaviour,'switch_b','forwardLatest');+ + var switch_b = function (b) { return b.switch_b(); };+ fxExport(core,switch_b,'switch_b');+ + //TODO test, signature+ var timer_b = function(interval) {+ return hold(timer_e(interval), (new Date()).getTime());+ };+ fxExport(dom,timer_b,'timer_b','asTimer_b');+ + //TODO test, signature+ var delayStatic_b = function (triggerB, time, init) {+ return hold(delayStatic_e(changes(triggerB), time), init);+ };+ + //TODO test, signature+ Behaviour.prototype.delay_b = function (time, init) {+ var triggerB = this;+ if (time instanceof Behaviour) {+ return hold(+ delay_e(+ changes(triggerB), + time),+ arguments.length > 3 ? init : valueNow(triggerB));+ } else {+ return delayStatic_b(+ triggerB, + time,+ arguments.length > 3 ? init : valueNow(triggerB));+ }+ };+ fxMethodSynonyms(Behaviour,'delay_b','delay');+ + var delay_b = function(srcB, timeB, init) { + return srcB.delay_b(timeB,init); + };+ fxExport(core,delay_b,'delay_b');+ + //artificially send a pulse to underlying event node of a behaviour+ //note: in use, might want to use a receiver node as a proxy or an identity map+ Behaviour.prototype.sendBehaviour = function(val) {+ sendEvent(this.underlyingRaw,val);+ };+ Behaviour.prototype.sendBehavior = Behaviour.prototype.sendBehaviour;+ + var sendBehaviour = function (b,v) { b.sendBehaviour(v); };+ fxExport(core,sendBehaviour,'sendBehaviour');+ fxExport(core,sendBehaviour,'sendBehavior');++ Behaviour.prototype.if_b = function(trueB,falseB) {+ var testB = this;+ //TODO auto conversion for behaviour funcs+ if (!(trueB instanceof Behaviour)) { trueB = constant_b(trueB); }+ if (!(falseB instanceof Behaviour)) { falseB = constant_b(falseB); }+ return lift_b(function(te,t,f) { return te ? t : f; },testB,trueB,falseB);+ };+ fxMethodSynonyms(Behaviour,'if_b','choose_b','choose');+ + var if_b = function(test,cons,altr) {+ if (!(test instanceof Behaviour)) { test = constant_b(test); };+ + return test.if_b(cons,altr);+ };+ fxExport(core,if_b,'if_b','choose_b');+ ++ //cond_b: . [Behaviour boolean, Behaviour a] -> Behaviour a+ var cond_b = function (/* . pairs */ ) {+ var pairs = slice(arguments, 0);+ return lift_b.apply({},[function() {+ for(var i=0;i<pairs.length;i++) {+ if(arguments[i]) return arguments[pairs.length+i];+ }+ return undefined;+ }].concat(map(function(pair) {return pair[0];},pairs).concat(map(function(pair) {return pair[1];},pairs))));+ };+ fxExport(core,cond_b,'cond_b');+ + //TODO optionally append to objects+ //createConstantB: a -> Behaviour a+ var constant_b = function (val) {+ return new Behaviour(internal_e(), val);+ };+ fxExport(core,constant_b,'constant_b','receiver_b');+ + var lift_b = function (fn /* . behaves */) {+ var args = slice(arguments, 1);++ //dependencies+ var constituentsE =+ map(changes,+ filter(function (v) { return v instanceof Behaviour; },+ arguments));+ + //calculate new vals+ var getCur = function (v) {+ return v instanceof Behaviour ? v.last : v;+ };+ + var ctx = this;+ var getRes = function () {+ return getCur(fn).apply(ctx, map(getCur, args));+ };+ + if(constituentsE.length == 1) {+ return new Behaviour(constituentsE[0],getRes(),getRes);+ }+ + //gen/send vals @ appropriate time+ var prevStamp = -1;+ var mid = createNode(constituentsE, function (s, p) {+ if (p.stamp != prevStamp) {+ prevStamp = p.stamp;+ s(p);+ }});+ return new Behaviour(mid,getRes(),getRes);+ };+ fxExport(core,lift_b,'lift_b','transform_b','apply_b');+ + Behaviour.prototype.lift_b = function(/* args */) {+ var args= slice(arguments,0).concat([this]);+ return lift_b.apply(this,args);+ };+ fxMethodSynonyms(Behaviour,'lift_b','transform_b','apply_b','transform',+ 'lift');+ + var and_b = function (/* . behaves */) {+ return lift_b.apply({},[function() {+ for(var i=0; i<arguments.length; i++) {if(!arguments[i]) return false;}+ return true;+ }].concat(slice(arguments,0)));+ };+ fxExport(core, and_b, 'and_b');+ + Behaviour.prototype.and_b = function() {+ return and_b([this].concat(arguments));+ };+ fxMethodSynonyms(Behaviour,'and_b','and');+ + var or_b = function (/* . behaves */ ) {+ return lift_b.apply({},[function() {+ for(var i=0; i<arguments.length; i++) {if(arguments[i]) return true;}+ return false;+ }].concat(slice(arguments,0)));+ };+ fxExport(core,or_b,'or_b');+ + Behaviour.prototype.or_b = function () {+ return or_b([this].concat(arguments));+ };+ fxMethodSynonyms(Behaviour, 'or_b', 'or');+ + Behaviour.prototype.not_b = function() {+ return this.lift_b(function(v) { return !v; });+ };+ fxMethodSynonyms(Behaviour,'not_b','not');+ + var not_b = function(b) { return b.not_b(); };+ fxExport(core,not_b,'not_b');+ + Behaviour.prototype.blind_b = function (intervalB) {+ return changes(this).blind_e(intervalB).hold(this.valueNow());+ };+ fxMethodSynonyms(Behaviour,'blind_b','blind');+ + var blind_b = function(srcB,intervalB) {+ return srcB.blind_b(intervalB);+ };+ fxExport(core,blind_b,'blind_b');+ + Behaviour.prototype.calm_b = function (intervalB) {+ return this.changes().calm_e(intervalB).hold(this.valueNow());+ };+ fxMethodSynonyms(Behaviour,'calm_b','calm');+ + var calm_b = function (srcB,intervalB) { + return srcB.calm_b(intervalB);+ };+ fxExport(core,calm_b,'calm_b');+ + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+ // DOM Utilities+ + //credit Scott Andrew+ //usage: addEvent(myDomObj, "mouseover", event->void )+ //warning: do not use 'this' as meaning depends on browser (myDomObj vs window)+ //addEvent: Dom * String DomEventEnum * (DomEvent -> a) -> Void+ var addEvent = function (obj, evType, fn) {+ //TODO encode mouseleave evt, formalize new evt interface+ + if (obj.addEventListener) {+ obj.addEventListener(evType, fn, false); //TODO true fails on Opera+ return true;+ } else if (obj.attachEvent) {+ //some reason original had code bloat here+ return obj.attachEvent("on"+evType, fn); + } else {+ return false; + }+ };+ fxExport(domMisc,addEvent,'addEvent');++ // The Flapjax library does not use this function + //credit Dustin Diaz + //note: node/tag optional+ //getElementsByClass: Regexp CSSSelector * Dom * String DomNodeEnum -> Array Dom+ var getElementsByClass = function (searchClass, node, tag) {+ var classElements = [];+ if ( (node === null) || (node === undefined) ) { node = document; }+ if ( (tag === null) || (tag === undefined) ) { tag = '*'; }+ var els = node.getElementsByTagName(tag);+ var elsLen = els.length;+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");+ for (var i = 0, j = 0; i < elsLen; i++) {+ if ( pattern.test(els[i].className) ) {+ classElements.push(els[i]);+ }+ }+ return classElements;+ };+ fxExport(domMisc,getElementsByClass,'getElementsByClass','$$');+ + //assumes IDs already preserved+ //swapDom: (Dom a U String) [* (Dom b U String)] -> Dom a+ var swapDom = function(replaceMe, withMe) {+ if ((replaceMe === null) || (replaceMe === undefined)) { throw ('swapDom: expected dom node or id, received: ' + replaceMe); } //SAFETY+ + var replaceMeD = getObj(replaceMe);+ if (!(replaceMeD.nodeType > 0)) { throw ('swapDom expected a Dom node as first arg, received ' + replaceMeD); } //SAFETY+ + if (withMe) {+ var withMeD = getObj(withMe);+ if (!(withMeD.nodeType > 0)) { throw 'swapDom: can only swap with a DOM object'; } //SAFETY+ try {+ if(withMeD != replaceMeD) replaceMeD.parentNode.replaceChild(withMeD, replaceMeD);+ } catch (e) {+ throw('swapDom error in replace call: withMeD: ' + withMeD + ', replaceMe Parent: ' + replaceMeD + ', ' + e + ', parent: ' + replaceMeD.parentNode); + }+ } else {+ replaceMeD.parentNode.removeChild(replaceMeD); //TODO isolate child and set innerHTML to "" to avoid psuedo-leaks?+ }+ return replaceMeD;+ };+ fxExport(domMisc,swapDom,'swapDom');+ + //getObj: String U Dom -> Dom+ //throws + // 'getObj: expects a Dom obj or Dom id as first arg'+ // 'getObj: flapjax: cannot access object'+ // 'getObj: no obj to get+ //also known as '$'+ //TODO Maybe alternative?+ var getObj = function (name) {+ if (typeof(name) == 'object') { return name; }+ else if ((typeof(name) == 'null') || (typeof(name) == 'undefined')) {+ throw 'getObj: expects a Dom obj or Dom id as first arg';+ } else {+ + var res = + document.getElementById ? document.getElementById(name) :+ document.all ? document.all[name] :+ document.layers ? document.layers[name] :+ (function(){ throw 'getObj: flapjax: cannot access object';})();+ if ((res === null) || (res === undefined)) { + throw ('getObj: no obj to get: ' + name); + }+ return res;+ }+ };+ fxExport(domMisc,getObj,'getObj');+ fxExport(domMisc,getObj,'$');+ + //helper to reduce obj look ups+ //getDynObj: domNode . Array (id) -> domObj+ //obj * [] -> obj+ //obj * ['position'] -> obj+ //obj * ['style', 'color'] -> obj.style+ var getMostDom = function (domObj, indices) {+ var acc = getObj(domObj);+ if ( (indices === null) || (indices === undefined) || (indices.length < 1)) {+ return acc;+ } else {+ for (var i = 0; i < indices.length - 1; i++) {+ acc = acc[indices[i]];+ }+ return acc;+ } + };+ + var getDomVal = function (domObj, indices) {+ var val = getMostDom(domObj, indices);+ if (indices && indices.length > 0) {+ val = val[indices[indices.length - 1]];+ }+ return val;+ };+ + //TODO: manual timer management stinks.+ // TODO: Name turn off or somethin+ var ___timerID = 0;+ var __getTimerId = function () { return ++___timerID; }; + var timerDisablers = [];+ + var disableTimerNode = function (node) { timerDisablers[node.__timerId](); };+ + var disableTimer = function (v) {+ if (v instanceof Behaviour) { + disableTimerNode(v.underlyingRaw); + } else if (v instanceof EventStream) {+ disableTimerNode(v);+ }+ };+ fxExport(dom,disableTimer,'disableTimer');+ + var createTimerNodeStatic = function (interval) {+ var node = internal_e();+ node.__timerId = __getTimerId();+ var fn = function () { sendEvent(node, (new Date()).getTime());};+ var timer = setInterval(fn, interval);+ timerDisablers[node.__timerId] = function () {clearInterval(timer); };+ return node;+ };+ + var timer_e = function (interval) {+ if (interval instanceof Behaviour) {+ var receiverE = internal_e();+ + //the return+ var res = receiverE.switch_e();+ + //keep track of previous timer to disable it+ var prevE = createTimerNodeStatic(valueNow(interval));+ + //init+ sendEvent(receiverE, prevE);+ + //interval changes: collect old timer+ createNode(+ [changes(interval)],+ function (_, p) {+ disableTimerNode(prevE); + prevE = createTimerNodeStatic(p.value);+ sendEvent(receiverE, prevE);+ });+ + res.__timerId = __getTimerId();+ timerDisablers[res.__timerId] = function () {+ disableTimerNode[prevE]();+ return;+ };+ + return res;+ } else {+ return createTimerNodeStatic(interval);+ }+ };+ fxExport(dom,timer_e,'timer_e','asTimer_e');++ d.TagB = function(tagName,args) {+ this.resE = internal_e();+ this.currentTag = document.createElement(tagName);+ this.extractParameters(args);+ this.insertChildrenNodes();+ this.styleHooks = [];+ this.styleChangedE = internal_e();+ var ctx = this;+ this.styleChangedE.lift_e(function(_) {+ var oldTag = ctx.currentTag;+ ctx.currentTag = document.createElement(tagName);+ while (oldTag.firstChild) {+ ctx.currentTag.appendChild(oldTag.removeChild(oldTag.firstChild));+ }+ while(ctx.styleHooks.length) removeListener(ctx.styleHooks.pop(),ctx.styleChangedE);+ ctx.enstyle(ctx.currentTag,ctx.attribs);+ sendEvent(ctx.resE, ctx.currentTag);+ });+ this.enstyle(this.currentTag,this.attribs);+ this.resB = hold(this.resE, this.currentTag);+ };+ d.TagB.prototype = {+ // Array [[Behaviour] Object *] [[Behaviour] Array] [Behaviour] Dom U String U undefined+ // --> {attribs: Array [Behaviour] Object, arrs: Array [Behaviour] Array [Behaviour] Dom }+ // split an arguments array into:+ // 1. arrs: (coalesced, and possibly time varying) arrays of dom objects + // 2. attribs: attribute objects+ extractParameters: function(args) {+ this.arrs = [];+ var attribs = [];+ + var curarr = [];+ this.arrs.push(curarr);+ for (var i = 0; i < args.length; i++) {+ if (args[i] instanceof Behaviour) {+ var vn = valueNow(args[i]);+ if (vn instanceof Array) { + this.arrs.push(args[i]);+ curarr = [];+ this.arrs.push(curarr);+ } else {+ if ( ((typeof(vn) == 'object') && (vn.nodeType == 1)) ||+ (typeof(vn) == 'string') || (vn == undefined)) {+ curarr.push(args[i]);+ } else if (typeof(vn) == 'object') {+ attribs.push(args[i]);+ }+ else { throw ('createParameterizedTagB: unknown behaviour argument argument ' + i); } //SAFETY+ }+ } else {+ if (args[i] instanceof Array) {+ var arr = args[i];+ for (var j = 0; j < arr.length; j++) { curarr.push(arr[j]); }+ } else {+ var vn = args[i];+ if ( ((typeof(vn) == 'object') && (vn.nodeType == 1)) ||+ (typeof(vn) == 'string') || (vn == undefined)) {+ curarr.push(args[i]);+ } else if (typeof(vn) == 'object') {+ attribs.push(args[i]);+ }+ }+ }+ };+ if(attribs.length > 1) throw ('createParameterizedTagB ' + tagName + ': more than one attribute (' + attribs.length + ')');+ this.attribs = attribs.length > 0 ? attribs[0] : {};+ },+ insertChildrenNodes: function() {+ var ctx = this;+ + function quickNode(e) { + if ((typeof(e) == 'object') && (e.nodeType))+ return e; + else if ( e == undefined )+ return document.createTextNode(''); + else + return document.createTextNode(e); + }+ + function unBehaviourize(arr) {+ return map(function(n) {return (n instanceof Behaviour) ? valueNow(n) : n;},arr)+ }+ + var lnodes = map(function() {return [];},this.arrs);+ var arrLastVals = map(unBehaviourize,unBehaviourize(this.arrs));+ + var arrChangesE = internal_e();+ var nodeChangesE = internal_e();+ + function attachNodes(i,arr) {+ for(var j=0;j<arr.length;j++) {+ var cnode = arr[j];+ if(cnode instanceof Behaviour) {+ var newnode = (function(jj) {+ return changes(cnode).lift_e(function(n) {return {index:i,jdex:jj,val:n};});+ })(j);+ lnodes[i].push(newnode);+ attachListener(newnode,nodeChangesE);+ cnode = valueNow(cnode);+ }+ }+ }+ + var childChangesE = merge_e(+ // Behaviour arrays change+ arrChangesE.lift_e(function(ai) {+ var i = ai.index;+ var newarr = ai.val;+ while(lnodes[i].length) {+ var ln = lnodes[i].pop();+ removeListener(ln,nodeChangesE);+ }+ var newvals = map(function(n) {return quickNode(n);},unBehaviourize(newarr));+ for(var j=0;j<arrLastVals[i].length;j++)+ try {+ ctx.currentTag.removeChild(arrLastVals[i][j]);+ }+ catch(e) {}+ if(newvals.length) {+ var nextNode = null;+ for(ii = i+1; ii < arrLastVals.length && !(arrLastVals[ii].length) ; ii++);+ if(ii < arrLastVals.length) nextNode = arrLastVals[ii][0];+ for(var j=0; j<newvals.length; j++) ctx.currentTag.insertBefore(newvals[j],nextNode);+ }+ arrLastVals[i] = newvals;+ attachNodes(i,newarr);+ return ctx.currentTag;+ }),+ // Behaviour nodes change+ nodeChangesE.lift_e(function(ni) {+ var i = ni.index;+ var j = ni.jdex;+ var newnode = quickNode(ni.val);+ swapDom(arrLastVals[i][j],newnode);+ arrLastVals[i][j] = newnode;+ return ctx.currentTag;+ }));+ childChangesE.lift_e(function(cc) {sendEvent(ctx.resE,cc);});+ + for(var i=0; i<this.arrs.length;i++) {+ for(var j=0; j<arrLastVals[i].length; j++) {+ arrLastVals[i][j] = quickNode(arrLastVals[i][j]);+ this.currentTag.appendChild(arrLastVals[i][j]);+ }+ if(this.arrs[i] instanceof Behaviour) {+ attachNodes(i,valueNow(this.arrs[i]));+ var newnode = (function(ii) {return changes(ctx.arrs[ii]).lift_e(function(na) {return {index:ii,val:na};});})(i);+ attachListener(newnode,arrChangesE);+ }+ else {+ attachNodes(i,this.arrs[i]);+ }+ }+ },+ enstyle: function(obj,vals) {+ //build & record hook if dynamic collection+ if (vals instanceof Behaviour) {+ if (!(typeof(valueNow(vals)) == 'object')) { throw 'enstyle: expected object literal as behaviour value'; } //SAFETY+ this.styleHooks.push(changes(vals));+ attachListener(changes(vals),this.styleChangedE);+ }+ var valsV = vals instanceof Behaviour ? valueNow(vals) : vals;+ if (typeof(valsV) == 'object') {+ for (var i in valsV) {+ if (!(Object.prototype) || !(Object.prototype[i])) {+ this.enstyleProperty(obj,valsV, i);+ }+ }+ } + else { throw 'enstyle: expected object literals'; } //SAFETY+ },+ enstyleProperty: function (obj, vals, i) {+ if (vals[i] instanceof Behaviour) {+ if (typeof(valueNow(vals[i])) == 'object') {+ this.enstyle(obj[i], vals[i]);+ }+ else {+ obj[i] = valueNow(vals[i]);+ changes(vals[i]).lift_e(function(v) {obj[i] = v;});+ }+ }+ else {+ if (typeof(vals[i]) == 'object') {+ this.enstyle(obj[i], vals[i]);+ } else {+ obj[i] = vals[i];+ }+ }+ }+ };+ + d.createParameterizedTagB = function(tagName) {+ return new d.TagB(tagName,slice(arguments,1)).resB;+ }+ + d.enstyleStaticProperty = function (obj, props, index) {+ if (typeof(props[index]) == 'object') {+ for (var i in props[index]) {+ if (!(Object.prototype) || !(Object.prototype[i])) {+ d.enstyleStaticProperty(obj[index], props[index], i);+ }+ }+ } else {+ obj[index] = props[index];+ if (index == 'checked') obj['defaultChecked'] = props[index]; /* TODO: this should maybe be elsewhere? */+ if (index == 'selected') obj['defaultSelected'] = props[index]; /* TODO: this should maybe be elsewhere? */+ }+ };+ + d.staticTagMaker = function (tagName) {+ + return function () {+ + var tagD = document.createElement(tagName);+ if (!(tagD.nodeType > 0)) { throw (tagName + ': invalid tag name'); } //SAFETY+ + //partition input+ + // if (arguments[1] === null || arguments[1] === undefined) { arguments[1] = {}; }+ var attribs = [];+ for (var i = 0; i < arguments.length; i++) {+ if (arguments[i] instanceof Array) {+ for (var j = 0; j < arguments[i].length; j++) {+ if (arguments[i][j]) {+ tagD.appendChild(+ (typeof(arguments[i][j]) == 'object' &&+ arguments[i][j].nodeType > 0)?+ arguments[i][j] :+ document.createTextNode(arguments[i][j]));+ }+ }+ } else if (!arguments[i]) {+ //ignore+ } else if ((typeof(arguments[i]) == 'object') && + (arguments[i].nodeType > 0)) {+ tagD.appendChild(arguments[i]);+ } else if (typeof(arguments[i]) == 'object') {+ attribs.push(arguments[i]);+ } else {+ tagD.appendChild(document.createTextNode(arguments[i])); + }+ }+ + if (attribs.length == 1) { + for (var k in attribs[0]) {+ if (!(Object.prototype) || !(Object.prototype[k])) {+ d.enstyleStaticProperty(tagD, attribs[0], k); + }+ }+ } else if (attribs.length > 0) { + throw 'static enstyle: expected object literals'; //SAFETY+ } /* else {+ alert('no attribs on: ' + tagName);+ } */+ + + return tagD;+ };+ };+ + + + var generatedTags = + [ "a", "b", "blockquote", "br", "button", "canvas", "div", "fieldset", + "form", "font", "h1", "h2", "h3", "h4", "hr", "img", "iframe", "input", + "label", "legend", "li", "ol", "optgroup", "option", + "p", "pre", "select", "span", "strong", "table", "tbody", + "td", "textarea", "tfoot", "th", "thead", "tr", "tt", "ul" ];+ + map(+ function (tagName) { + + var upper = tagName.toUpperCase();+ + //d.<TAG>B+ d[upper + 'B'] = function () { + return d.createParameterizedTagB.apply(this, [tagName].concat(slice(arguments,0)));+ }; + annotate(d[upper+'B'],[upper+'B']);+ + //d.<TAG>+ d[upper] = d.staticTagMaker(tagName); //faster, simple+ /* function () {+ // 8/16/06 - leo - arguments bug+ // more forgiving: allows reactive children (just doesn't propagate them)+ var args = [b.maybeEmpty].concat(slice(arguments, 0)); + return valueNow(d[upper + 'B'].apply(this, args));+ }; */+ annotate(d[upper],[upper]);+ },+ generatedTags);+ + //TEXTB: Behaviour a -> Behaviour Dom TextNode + d.TEXTB = function (strB) {+ // if (!(strB instanceof Behaviour || typeof(strB) == 'string')) { throw 'TEXTB: expected Behaviour as second arg'; } //SAFETY+ if (!(strB instanceof Behaviour)) { strB = constant_b(strB); }+ + return hold(+ changes(strB).lift_e(+ function (txt) { return document.createTextNode(txt); }),+ document.createTextNode(valueNow(strB)));+ };+ annotate(d.TEXTB,['TEXTB']);+ + var TEXT = function (str) {+ return document.createTextNode(str);+ };+ fxExport(dom,TEXT,'TEXT');+ + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+ // Reactive DOM+ + //tagRec: Array (EventName a) * + // ( .Array (Event a) * Array (Event a) -> Behaviour Dom) -> Behaviour Dom+ var tagRec = function (eventNames, maker) {+ if (!(eventNames instanceof Array)) { throw 'tagRec: expected array of event names as first arg'; } //SAFETY+ if (!(maker instanceof Function)) { throw 'tagRec: expected function as second arg'; } //SAFETY+ + var numEvents = eventNames.length;+ var internals = [ ];+ var switches = [ ];+ for (var i = 0; i < numEvents; i++) {+ internals[i] = internal_e();+ switches[i] = internals[i].switch_e();+ };+ + var domB = maker.apply(this,switches);+ + var prevValue;+ + var interceptE = createNode([domB.changes()],function (_,p) {+ if (isEqual(p.value,prevValue)) { return; }+ + prevValue = p.value;+ for (var i = 0; i < numEvents; i++) {+ sendEvent(internals[i],extractEvent_e(prevValue,eventNames[i]));+ };+ });+ + sendEvent(interceptE,domB.valueNow());+ + return domB;+ };+ fxExport(dom,tagRec,'tagRec','nodeWithOwnEvents');+ + //extractEventStatic_e: Dom * String -> Event+ var extractEventStatic_e = function (domObj, eventName) {+ if (!eventName) { throw 'extractEvent_e : no event name specified'; }+ if (!domObj) { throw 'extractEvent_e : no DOM element specified'; }+ + domObj = getObj(domObj);+ + var primEventE = internal_e();+ addEvent(domObj,eventName,function(evt) {+ sendEvent(primEventE, evt || window.event);+ // Important for IE; false would prevent things like a checkbox actually+ // checking.+ return true;+ });+ + return primEventE;+ };++ //extractEvent_e: [Behaviour] Dom * String -> Event+ var extractEvent_e = function (domB, eventName) {+ if (!(domB instanceof Behaviour)) {+ return extractEventStatic_e(domB,eventName);+ }+ else {+ var domE = domB.changes();+ + var eventEE = domE.lift_e(function(dom) {+ return extractEventStatic_e(dom,eventName);+ });+ + var resultE = eventEE.switch_e();+ + sendEvent(domE,domB.valueNow());+ + return resultE;+ };+ };+ fxExport(dom,extractEvent_e,'extractEvent_e','$EVT');+ + //extractEvents_e: + // [Behaviour] Dom + // . Array String+ // -> Event+ // ex: extractEvents_e(m, 'body', 'mouseover', 'mouseout')+ d.extractEvents_e = function (domObj /* . eventNames */) {+ var eventNames = slice(arguments, 1);+ + var events = map(+ function (eventName) {+ return extractEvent_e(domObj, eventName); + },+ eventNames.length === 0 ? [] : eventNames);+ + return merge_e.apply(this, events);+ };+ annotate(d.extractEvents_e,['extractEvents_e'],0,[Behaviour.prototype],['extractEvents_e']);+ + //value of dom form object during trigger+ d.extractValueOnEvent_e = function (triggerE, domObj) {+ if (!(triggerE instanceof EventStream)) { throw 'extractValueOnEvent_e: expected Event as first arg'; } //SAFETY+ + return changes(d.extractValueOnEvent_b.apply(this, arguments));+ + };+ annotate(d.extractValueOnEvent_e,['extractValueOnEvent_e']);+ + //extractDomFieldOnEvent_e: Event * Dom U String . Array String -> Event a+ d.extractDomFieldOnEvent_e = function (triggerE, domObj /* . indices */) {+ if (!(triggerE instanceof EventStream)) { throw 'extractDomFieldOnEvent_e: expected Event as first arg'; } //SAFETY+ var indices = slice(arguments, 2);+ var res =+ triggerE.lift_e(+ function () { return getDomVal(domObj, indices); });+ return res;+ };+ + d.extractValue_e = function (domObj) {+ return changes(d.extractValue_b.apply(this, arguments));+ };+ annotate(d.extractValue_e,['extractValue_e','$E']);+ + //extractValueOnEvent_b: Event * DOM -> Behaviour+ // value of a dom form object, polled during trigger+ d.extractValueOnEvent_b = function (triggerE, domObj) {+ return d.extractValueStatic_b(domObj, triggerE);+ };+ annotate(d.extractValueOnEvent_b,['extractValueOnEvent_b']);+ + //extractValueStatic_b: DOM [ * Event ] -> Behaviour a+ //If no trigger for extraction is specified, guess one+ d.extractValueStatic_b = function (domObj, triggerE) {+ + var objD;+ try {+ objD = getObj(domObj);+ //This is for IE+ if(typeof(domObj) == 'string' && objD.id != domObj) {+ throw 'Make a radio group';+ }+ } catch (e) {+ objD = {type: 'radio-group', name: domObj};+ }+ + var getter; // get value at any current point in time+ + + switch (objD.type) {+ + //TODO: checkbox.value instead of status?+ case 'checkbox': + + return hold(+ filterRepeats_e(+ d.extractDomFieldOnEvent_e(+ triggerE ? triggerE : + d.extractEvents_e(+ objD, + 'click', 'keyup', 'change'),+ objD,+ 'checked'),objD.checked),+ objD.checked);+ + case 'select-one':+ + getter = function (_) { + return objD.selectedIndex > -1 ? + (objD.options[objD.selectedIndex].value ?+ objD.options[objD.selectedIndex].value :+ objD.options[objD.selectedIndex].innerText)+ : undefined;+ };+ + return hold(+ filterRepeats_e(+ (triggerE ? triggerE :+ d.extractEvents_e(+ objD,+ 'click', 'keyup', 'change')).lift_e(getter)),getter(),+ getter());+ + case 'select-multiple':+ //TODO ryan's cfilter adapted for equality check+ + getter = function (_) {+ var res = [];+ for (var i = 0; i < objD.options.length; i++) {+ if (objD.options[i].selected) {+ res.push(objD.options[i].value ? objD.options[i].value : objD.options[i].innerText);+ }+ }+ return res;+ };+ + + return hold(+ (triggerE ? triggerE : + d.extractEvents_e(+ objD,+ 'click', 'keyup', 'change')).lift_e(getter),+ getter());+ + case 'text':+ case 'textarea':+ case 'hidden':+ case 'password':+ + return hold(+ filterRepeats_e(+ d.extractDomFieldOnEvent_e(+ triggerE ? triggerE :+ d.extractEvents_e(+ objD, + 'click', 'keyup', 'change'),+ objD,+ 'value'),objD.value),+ objD.value);+ + case 'button': //same as above, but don't filter repeats+ + return hold(+ d.extractDomFieldOnEvent_e(+ triggerE ? triggerE :+ d.extractEvents_e(+ objD, + 'click', 'keyup', 'change'),+ objD,+ 'value'),+ objD.value);+ + + case 'radio': + case 'radio-group':+ + //TODO returns value of selected button, but if none specified,+ // returns 'on', which is ambiguous. could return index,+ // but that is probably more annoying+ + var radiosAD = filter(+ function (elt) { + return (elt.type == 'radio') &&+ (elt.getAttribute('name') == objD.name); + },+ document.getElementsByTagName('input'));+ + getter = + objD.type == 'radio' ?+ + function (_) {+ return objD.checked;+ } :+ + function (_) {+ for (var i = 0; i < radiosAD.length; i++) {+ if (radiosAD[i].checked) {+ return radiosAD[i].value; + }+ }+ return undefined; //TODO throw exn? + };+ + var actualTriggerE = triggerE ? triggerE :+ merge_e.apply(+ this,+ map(+ function (radio) { + return d.extractEvents_e(+ radio, + 'click', 'keyup', 'change'); },+ radiosAD));+ + return hold(+ filterRepeats_e(+ actualTriggerE.lift_e(getter),getter()),+ getter());+ + default:+ + throw ('extractValueStatic_b: unknown value type "' + objD.type + '"');+ }+ };+ + d.extractValue_b = function (domObj) {+ if (domObj instanceof Behaviour) {+ return lift_b(function (dom) { return d.extractValueStatic_b(dom); },+ domObj)+ .switch_b();+ } else {+ return d.extractValueStatic_b(domObj);+ }+ };+ annotate(d.extractValue_b,['extractValue_b','$B'],0,[Behaviour.prototype],['extractValue_b','$B']);+ + //into[index] = deepValueNow(from) via descending from object and mutating each field+ d.deepStaticUpdate = function (into, from, index) {+ var fV = (from instanceof Behaviour)? valueNow(from) : from;+ if (typeof(fV) == 'object') {+ for (var i in fV) {+ if (!(Object.prototype) || !(Object.prototype[i])) {+ d.deepStaticUpdate(index? into[index] : into, fV[i], i);+ }+ }+ } else {+ var old = into[index];+ into[index] = fV;+ }+ };+ + //note: no object may be time varying, just the fields+ //into[index] = from+ //only updates on changes+ d.deepDynamicUpdate = function (into, from, index) {+ var fV = (from instanceof Behaviour)? valueNow(from) : from;+ if (typeof(fV) == 'object') {+ if (from instanceof Behaviour) {+ throw 'deepDynamicUpdate: dynamic collections not supported';+ }+ for (var i in fV) {+ if (!(Object.prototype) || !(Object.prototype[i])) {+ d.deepDynamicUpdate(index? into[index] : into, fV[i], i);+ }+ }+ } else {+ if (from instanceof Behaviour) {+ createNode(+ [changes(from)],+ function (s, p) {+ if (index) { + var old = into[index];+ into[index] = p.value;+ }+ else { into = p.value; } //TODO notify topE?+ });+ }+ }+ };+ + + d.insertValue = function (val, domObj /* . indices */) {+ var indices = slice(arguments, 2);+ var parent = getMostDom(domObj, indices);+ d.deepStaticUpdate(parent, val, indices ? indices[indices.length - 1] : undefined); + };+ annotate(d.insertValue,['insertValue']);+ + //TODO convenience method (default to firstChild nodeValue) + d.insertValueE = function (triggerE, domObj /* . indices */) {+ if (!(triggerE instanceof EventStream)) { throw 'insertValueE: expected Event as first arg'; } //SAFETY+ + var indices = slice(arguments, 2);+ var parent = getMostDom(domObj, indices);+ + triggerE.lift_e(function (v) {+ d.deepStaticUpdate(parent, v, indices? indices[indices.length - 1] : undefined);+ });+ };+ annotate(d.insertValueE,['insertValueE'],0,[EventStream.prototype],['insertValueE']);+ + //insertValueB: Behaviour * domeNode . Array (id) -> void+ //TODO notify adapter of initial state change?+ d.insertValueB = function (triggerB, domObj /* . indices */) { + + var indices = slice(arguments, 2);+ var parent = getMostDom(domObj, indices);+ + + //NOW+ d.deepStaticUpdate(parent, triggerB, indices ? indices[indices.length - 1] : undefined);+ + //LATER+ d.deepDynamicUpdate(parent, triggerB, indices? indices[indices.length -1] : undefined);+ + };+ annotate(d.insertValueB,['insertValueB'],0,[Behaviour.prototype],['insertValueB']);+ + //TODO copy dom event call backs of original to new? i don't thinks so+ // complication though: registration of call backs should be scoped+ d.insertDomE = function (triggerE, domObj) {+ + if (!(triggerE instanceof EventStream)) { throw 'insertDomE: expected Event as first arg'; } //SAFETY+ + var objD = getObj(domObj);+ + var res = triggerE.lift_e(+ function (newObj) {+ //TODO safer check+ if (!((typeof(newObj) == 'object') && (newObj.nodeType == 1))) { + newObj = d.SPAN({}, newObj);+ }+ swapDom(objD, newObj);+ objD = newObj;+ return newObj; // newObj;+ });+ + return res;+ };+ annotate(d.insertDomE,['insertDomE'],0,[EventStream.prototype],['insertDomE']);+ + //insertDom: dom + // * dom + // [* (null | undefined | 'over' | 'before' | 'after' | 'leftMost' | 'rightMost' | 'beginning' | 'end']+ // -> void+ // TODO: for consistency, switch replaceWithD, hookD argument order+ d.insertDom = function (hookD, replaceWithD, optPosition) {+ switch (optPosition)+ {+ case undefined:+ case null:+ case 'over':+ swapDom(hookD,replaceWithD);+ break;+ case 'before': + hookD.parentNode.insertBefore(replaceWithD, hookD);+ break;+ case 'after':+ if (hookD.nextSibling) {+ hookD.parentNode.insertBefore(replaceWithD, hookD.nextSibling);+ } else {+ hookD.parentNode.appendChild(replaceWithD);+ }+ break;+ case 'leftMost':+ if (hookD.parentNode.firstChild) { + hookD.parentNode.insertBefore(+ replaceWithD, + hookD.parentNode.firstChild);+ } else { hookD.parentNode.appendChild(replaceWithD); }+ break;+ case 'rightMost':+ hookD.parentNode.appendChild(replaceWithD);+ break;+ case 'beginning':+ if (hookD.firstChild) { + hookD.insertBefore(+ replaceWithD, + hookD.firstChild);+ } else { hookD.appendChild(replaceWithD); }+ break;+ case 'end':+ hookD.appendChild(replaceWithD);+ break;+ default:+ throw ('domInsert: unknown position: ' + optPosition);+ }+ };+ + //insertDom: dom + // * dom U String domID + // [* (null | undefined | 'over' | 'before' | 'after' | 'leftMost' | 'rightMost' | 'beginning' | 'end']+ // -> void+ d.insertDomClean = function (replaceWithD, hook, optPosition) {+ //TODO span of textnode instead of textnode?+ d.insertDom(+ getObj(hook), + ((typeof(replaceWithD) == 'object') && (replaceWithD.nodeType > 0)) ? replaceWithD :+ document.createTextNode(replaceWithD), + optPosition); + };+ annotate(d.insertDomClean,['insertDom']);+ + //TODO test+ //insertDomB: + // [Behaviour] String U Dom + // [* ( id U null U undefined ) + // [* ('before' U 'after' U 'leftMost' U 'rightMost' U 'over' U 'beginning' U 'end')]]+ // -> Behaviour a+ //if optID not specified, id must be set in init val of trigger+ //if position is not specified, default to 'over'+ //performs initial swap onload + d.insertDomB = function (initTriggerB, optID, optPosition) {+ + if (!(initTriggerB instanceof Behaviour)) { + initTriggerB = constant_b(initTriggerB);+ }+ + var triggerB = + lift_b(+ function (d) { + if ((typeof(d) == 'object') && (d.nodeType > 0)) {+ return d;+ } else {+ var res = document.createElement('span'); //TODO createText instead+ res.appendChild(document.createTextNode(d));+ return res;+ }+ },+ initTriggerB);+ + var initD = valueNow(triggerB);+ if (!((typeof(initD) == 'object') && (initD.nodeType == 1))) { throw ('insertDomB: initial value conversion failed: ' + initD); } //SAFETY + + d.insertDom(+ optID === null || optID === undefined ? getObj(initD.getAttribute('id')) : getObj(optID), + initD, + optPosition);+ + var resB = hold(+ d.insertDomE(+ changes(triggerB),+ initD), + initD);+ + return resB;+ };+ annotate(d.insertDomB,['insertDomB'],0,[Behaviour.prototype],['insertDomB']);+ + + d.extractId_b = function (id, start)+ {+ return hold(+ createNode( start instanceof Behaviour? [changes(start)] :+ [],+ function (s, p) {+ p.value = getObj(id);+ s(p);+ }),+ getObj(id));+ };+ annotate(d.insertDomB,['extractId_b'],1,[Behaviour.prototype],['extractId_b']);+ + var mouse_e = function(elem) {+ return extractEvent_e(elem,'mousemove')+ .lift_e(function(evt) {+ if (evt.pageX | evt.pageY) {+ return { left: evt.pageX, top: evt.pageY };+ }+ else if (evt.clientX || evt.clientY) {+ return { left : evt.clientX + document.body.scrollLeft,+ top: evt.clientY + document.body.scrollTop };+ }+ else {+ return { left: 0, top: 0 };+ }+ });+ };+ + var mouse_b = function(elem) {+ return mouse_e(elem).hold({ left: 0, top: 0 });+ }+ fxExport(dom,mouse_b,'mouse_b');+ + var mouseLeft_b = function(elem) {+ return lift_b(function(v) { return v.left; },mouse_b(elem));+ };+ fxExport(dom,mouseLeft_b,'mouseLeft_b');+ + var mouseTop_b = function(elem) {+ return mouse_b(elem).lift_b(function(v) { return v.top; });+ };+ + fxExport(dom,mouseTop_b,'mouseTop_b');+ + var clicks_e = function(elem) {+ return extractEvent_e(elem,'click');+ };+ fxExport(dom,clicks_e,'clicks_e');+ + //////////////////////////////////////////////////////////////////////////////+ // Combinators for web services+ + + //credit Matt White+ var getURLParam = function (param) {+ var lparam = param.toLowerCase();+ var aReturn = [];+ var strHref = window.location.href;+ var endstr = (strHref.indexOf('#') > -1) ? strHref.indexOf('#') : strHref.length;+ if ( strHref.indexOf("?") > -1 ) {+ var strQueryString = strHref.substring(strHref.indexOf("?")+1,endstr);+ map(function(qp) {+ var eq = qp.indexOf('=');+ var qname = qp.substr(0,eq+1).toLowerCase();+ if(qname == lparam+"=") aReturn.push(decodeURIComponent(qp.substr(eq+1)));+ },strQueryString.split("&"));+ }+ if (aReturn.length == 0) return undefined;+ else if(aReturn.length == 1) return aReturn[0];+ else return aReturn;+ };+ fxExport(domMisc,getURLParam,'getURLParam','$URL');+ + //credit Quirksmode+ //readCookie: String -> String U Undefined+ var readCookie = function (name) {+ var nameEQ = name + "=";+ var ca = document.cookie.split(';');+ for (var i=0; i < ca.length; i++) {+ var co = ca[i];+ while (co.charAt(0) == ' ') { co = co.substring(1, co.length); }+ if (co.indexOf(nameEQ) === 0) { + return co.substring(nameEQ.length, co.length);+ }+ }+ return undefined; + };+ fxExport(domMisc,readCookie,'readCookie');+ + //========== dynamic scripts ==========+ var scriptCounter = 0;+ var deleteScript = function (scriptID) {+ var scriptD = getObj(scriptID);+ scriptD.parentNode.removeChild(scriptD); //TODO isolate child and set innerHTML to "" to avoid psuedo-leaks?+ };+ + // optional fn/param that gets polled until parm is defined+ var runScript = function (url, fn, param) {+ var script = document.createElement("script");+ script.src = url;+ var scriptID = 'scriptFnRPC' + scriptCounter++;+ script.setAttribute('id', scriptID);+ document.getElementsByTagName("head").item(0).appendChild(script);+ var timer = {};+ var check = + function () {+ eval("try { if (" + param + "!== undefined) {var stat = " + param + ";}} catch (e) {}");+ if (stat !== undefined) {+ eval(param + " = undefined;");+ clearInterval(timer.timer);+ clearInterval(timer.timeout);+ if (fn instanceof Function) {+ fn(stat); + }+ deleteScript(scriptID);+ }+ };+ timer.timer = setInterval(check, 3500);+ timer.timeout = + setTimeout( + function () { + try { clearInterval(timer.timer); }+ catch (e) {}+ },+ 5000); //TODO make parameter?+ };+ + // Node {url, globalArg} -> Node a+ //load script @ url and poll until param is set, then pass it along+ var evalForeignScriptVal_e = function(urlArg_e) {+ var result = receiver_e();+ urlArg_e.lift_e(function(urlArg) {+ runScript(urlArg.url,+ function(val) { result.sendEvent(val); }, + urlArg.globalArg);+ });+ + return result;+ };+ fxExport(ws,evalForeignScriptVal_e,'evalForeignScriptVal_e');+ + var ajaxRequest = function(method,url,body,async,useFlash,callback) {+ var xhr;+ if (useFlash) {+ xhr = new FlashXMLHttpRequest();+ xhr.onload = function() { callback(xhr); };+ }+ else if (window.XMLHttpRequest && !(window.ActiveXObject)) {+ xhr = new window.XMLHttpRequest();+ xhr.onload = function() { callback(xhr); };+ }+ else if (window.ActiveXObject) {+ try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }+ catch(e) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }+ + xhr.onreadystatechange = function() {+ if (xhr.readyState == 4) { callback(xhr); }+ };+ };+ + xhr.open(method,url,async);+ + if (method == 'POST') {+ xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');+ }+ + xhr.send(body);+ return xhr;+ };++ var encodeREST = function(obj) {+ var str = "";+ for (var field in obj) {+ if (typeof(obj[field]) !== 'function') { // skips functions in the object+ if (str != '') { str += '&'; }+ str += field + '=' + encodeURIComponent(obj[field]);+ }+ }+ return str;+ };++ // From json.org+ var parseJSON = function(str) {+ try {+ return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(+ str.replace(/"(\\.|[^"\\])*"/g, ''))) &&+ eval('(' + str + ')');+ } catch (e) {+ throw 'cannot parse JSON string: ' + e;+ }+ };++ var toJSONString = (function() {+ var m = {+ '\b': '\\b',+ '\t': '\\t',+ '\n': '\\n',+ '\f': '\\f',+ '\r': '\\r',+ '"' : '\\"',+ '\\': '\\\\'+ };+ var s = {+ array: function (x) {+ var a = ['['], b, f, i, l = x.length, v;+ for (i = 0; i < l; i += 1) {+ v = x[i];+ f = s[typeof v];+ if (f) {+ v = f(v);+ if (typeof v == 'string') {+ if (b) {+ a[a.length] = ',';+ }+ a[a.length] = v;+ b = true;+ }+ }+ }+ a[a.length] = ']';+ return a.join('');+ },+ 'boolean': function (x) {+ return String(x);+ },+ 'null': function (x) {+ return "null";+ },+ number: function (x) {+ return isFinite(x) ? String(x) : 'null';+ },+ object: function (x) {+ if (x) {+ if (x instanceof Array) {+ return s.array(x);+ }+ var a = ['{'], b, f, i, v;+ for (i in x) {+ v = x[i];+ f = s[typeof v];+ if (f) {+ v = f(v);+ if (typeof v == 'string') {+ if (b) {+ a[a.length] = ',';+ }+ a.push(s.string(i), ':', v);+ b = true;+ }+ }+ }+ a[a.length] = '}';+ return a.join('');+ }+ return 'null';+ },+ string: function (x) {+ if (/["\\\x00-\x1f]/.test(x)) {+ x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {+ var c = m[b];+ if (c) {+ return c;+ }+ c = b.charCodeAt();+ return '\\u00' ++ Math.floor(c / 16).toString(16) ++ (c % 16).toString(16);+ });+ }+ return '"' + x + '"';+ }+ };+ return function(val) {+ var f = s[typeof val];+ if (f) { return f(val); }+ else { throw 'parseJSON: unknown object type: ' + (typeof val); }+ };+ })();+ + var serverRequest_e = function(useFlash,requestE) {+ var response_e = receiver_e();+ + requestE.lift_e(function (obj) {+ var body = '';+ var method = 'GET';+ var url = obj.url;+ + var reqType = obj.request ? obj.request : (obj.fields ? 'post' : 'get');+ if (obj.request == 'get') {+ url += "?" + encodeREST(obj.fields);+ body = '';+ method = 'GET';+ } else if (obj.request == 'post') {+ body = toJSONString(obj.fields); + method = 'POST';+ } else if (obj.request == 'rawPost') {+ body = obj.body;+ method = 'POST';+ }+ else if (obj.request == 'rest') {+ body = encodeREST(obj.fields);+ method = 'POST';+ }+ else {+ raise ("Invalid request type: " + obj.request);+ }+ + var async = obj.async;+ + var xhr;+ + // Branch on the response type to determine how to parse it+ if (obj.response == 'json') {+ xhr = ajaxRequest(method,url,body,async,useFlash,+ function(xhr) {+ response_e.sendEvent(parseJSON(xhr.responseText)); + });+ }+ else if (obj.response == 'xml') {+ ajaxRequest(method,url,body,async,useFlash,+ function(xhr) {+ response_e.sendEvent(xhr.responseXML);+ });+ }+ else if (obj.response == 'plain' || !obj.response) {+ ajaxRequest(method,url,body,async,useFlash,+ function(xhr) {+ response_e.sendEvent(xhr.responseText);+ });+ }+ else {+ raise('Unknown response format: ' + obj.response);+ }+ });+ + return response_e;+ };+ + var getWebServiceObject_e = function(requestE) {+ return serverRequest_e(false,requestE);+ };+ fxExport(ws,getWebServiceObject_e,'getWebServiceObject_e');+ + var getForeignWebServiceObject_e = function(requestE) {+ return serverRequest_e(true,requestE);+ };+ fxExport(ws,getForeignWebServiceObject_e,'getForeignWebServiceObject_e');++ var cumulativeOffset = function(element) {+ var valueT = 0, valueL = 0;+ do {+ valueT += element.offsetTop || 0;+ valueL += element.offsetLeft || 0;+ element = element.offsetParent;+ } while (element);+ return { left: valueL, top: valueT };+ };+fxExport(domMisc,cumulativeOffset,'cumulativeOffset');++ ///////// OPTIONALLY EXPORT PUBLIC FUNCTIONS TO GLOBAL NAMESPACE+ if (!options.hideAll) {+ for (var zz in flapjax.pub) {+ if (!options[zz]) {+ window[zz] = flapjax.pub[zz]; // use eval instead so as to achieve Flash compatibility+ }+ }+ }+ + for (var id in exports) {+ if (window[id]) {+ if (options.redefine === false) {+ warn('window.' + id + ' is already defined; Flapjax will not ' ++ 'redefine it.');+ }+ else {+ warn('Flapjax is redefining window.' + id + '.');+ }+ }++ if (window[id] && options.redefine === false) {+ // Don't redefine id+ }+ else if (options.show && options.hide && options.show[id] === true && + options.hide[id] === true) {+ throw('flapjaxInit: invalid options: ' + id + " specified as 'show' and 'hide'"); + }+ else if (options.show && options.show[id]) {+ window[id] = exports[id];+ }+ else if (options.hide && options.hide[id]) {+ // do nothing -- don't export+ }+ // Default behavior--check if it is a synonym first ...+ else if (!synonyms[id] || options.includeSynonyms) {+ // ... then export if its of the right category+ if (options.exportMisc && exports[id].__flapjaxCategory === misc) {+ window[id] = exports[id];+ }+ else if (options.exportDOMMisc && exports[id].__flapjaxCategory === domMisc) {+ window[id] = exports[id];+ }+ else if (options.exportDOM && exports[id].__flapjaxCategory === dom) {+ window[id] = exports[id];+ }+ else if (options.exportCore && exports[id].__flapjaxCategory === core) {+ window[id] = exports[id];+ }+ else if (options.exportWS && exports[id].__flapjaxCategory === ws) {+ window[id] = exports[id];+ }+ }+ }+ + return exports;+}
+ tests/parse-pretty/neg.js view
@@ -0,0 +1,2 @@+var foo = -x;+var bar = +y;
+ tests/parse-pretty/numbers.js view
@@ -0,0 +1,2 @@+var x = 23;+var y = 23.0;
+ tests/parse-pretty/object-lit-1.js view
@@ -0,0 +1,4 @@+var x = { // avoid ambiguity with BlockStmt+ foo : 23, + bar : 50 +}
+ tests/parse-pretty/object-lit-2.js view
@@ -0,0 +1,4 @@+var x = { // avoid ambiguity with BlockStmt+ foo : 23, + bar : 50, +}
+ tests/parse-pretty/prefix-chain.js view
@@ -0,0 +1,4 @@+var w = typeof typeof 34;+var x = ! -- x; // derived from jQuery+var y = ! !x; // derived from Prototype+var z = !! -- x;
+ tests/parse-pretty/strings.js view
@@ -0,0 +1,6 @@+var x = '\b';+var z = {+ '\b': '\\b' // lhs is a PropString, not a StringLit, but must be printed+ // as a StringLit+};+var w = "\\s";