var imageLibrary = MACHINE.modules['whalesong/image/private/main.rkt'].privateExports; var isImage = imageLibrary.isImage; var PAUSE = plt.runtime.PAUSE; var EMPTY = plt.baselib.lists.EMPTY; var isString = plt.baselib.strings.isString; var isBoolean = function(x) { return x === true || x === false; } var isSymbol = plt.baselib.symbols.isSymbol; var makePair = plt.baselib.lists.makePair; var makeList = plt.baselib.lists.makeList; var makeRational = plt.baselib.numbers.makeRational; var finalizeClosureCall = plt.baselib.functions.finalizeClosureCall; ////////////////////////////////////////////////////////////////////// var bigBang = function(MACHINE, initW, handlers) { var oldArgcount = MACHINE.argcount; var outerToplevelNode = $('').get(0); MACHINE.params.currentOutputPort.writeDomNode(MACHINE, outerToplevelNode); var toplevelNode = $('').appendTo(outerToplevelNode).get(0); var configs = []; var isOutputConfigSeen = false; for (var i = 0 ; i < handlers.length; i++) { if (isWorldConfigOption(handlers[i])) { configs.push(handlers[i].toRawHandler(MACHINE, toplevelNode)); } else { configs.push(handlers[i]); } if (isOutputConfig(handlers[i])) { isOutputConfigSeen = true; } } // If we haven't seen an onDraw function, use the default one. if (! isOutputConfigSeen) { configs.push(new DefaultDrawingOutput().toRawHandler(MACHINE, toplevelNode)); } PAUSE(function(restart) { // var onBreak = function() { // bigBangController.breaker(); // } // state.addBreakRequestedListener(onBreak); var bigBangController = rawJsworld.bigBang( toplevelNode, initW, configs, {}, function(finalWorldValue) { // state.removeBreakRequestedListener(onBreak); restart(function(MACHINE) { MACHINE.argcount = oldArgcount; finalizeClosureCall( MACHINE, finalWorldValue); }); }); }); }; ////////////////////////////////////////////////////////////////////// // Every world configuration function (on-tick, stop-when, ...) // produces a WorldConfigOption instance. var WorldConfigOption = function(name) { this.name = name; }; WorldConfigOption.prototype.configure = function(config) { throw new Error('unimplemented WorldConfigOption'); }; WorldConfigOption.prototype.toDomNode = function(cache) { var span = document.createElement('span'); span.appendChild(document.createTextNode("(" + this.name + " ...)")); return span; }; WorldConfigOption.prototype.toWrittenString = function(cache) { return "(" + this.name + " ...)"; }; WorldConfigOption.prototype.toDisplayedString = function(cache) { return "(" + this.name + " ...)"; }; var isWorldConfigOption = plt.baselib.makeClassPredicate(WorldConfigOption); ////////////////////////////////////////////////////////////////////// // adaptWorldFunction: Racket-function -> World-CPS // Takes a racket function and converts it to the CPS-style function // that our world implementation expects. var adaptWorldFunction = function(worldFunction) { return function() { // Consumes any number of arguments. var success = arguments[arguments.length - 1]; plt.baselib.functions.internalCallDuringPause.apply( null, [MACHINE, worldFunction, function(v) { success(v); }, function(err) { // FIXME: do error trapping console.log(err); }].concat([].slice.call(arguments, 0, arguments.length - 1))); } }; ////////////////////////////////////////////////////////////////////// // OnTick: racket-function javascript-float -> handler var OnTick = function(handler, aDelay) { WorldConfigOption.call(this, 'on-tick'); this.handler = handler; this.delay = aDelay; }; OnTick.prototype = plt.baselib.heir(WorldConfigOption.prototype); OnTick.prototype.toRawHandler = function(MACHINE, toplevelNode) { var that = this; var worldFunction = adaptWorldFunction(that.handler); return rawJsworld.on_tick(this.delay, worldFunction); }; ////////////////////////////////////////////////////////////////////// var OnKey = function(handler) { WorldConfigOption.call(this, 'on-key'); this.handler = handler; } OnKey.prototype = plt.baselib.heir(WorldConfigOption.prototype); OnKey.prototype.toRawHandler = function(MACHINE, toplevelNode) { var that = this; var worldFunction = adaptWorldFunction(that.handler); return rawJsworld.on_key( function(w, e, success) { worldFunction(w, getKeyCodeName(e), success); }); }; var getKeyCodeName = function(e) { var code = e.charCode || e.keyCode; var keyname; switch(code) { case 16: keyname = "shift"; break; case 17: keyname = "control"; break; case 19: keyname = "pause"; break; case 27: keyname = "escape"; break; case 33: keyname = "prior"; break; case 34: keyname = "next"; break; case 35: keyname = "end"; break; case 36: keyname = "home"; break; case 37: keyname = "left"; break; case 38: keyname = "up"; break; case 39: keyname = "right"; break; case 40: keyname = "down"; break; case 42: keyname = "print"; break; case 45: keyname = "insert"; break; case 46: keyname = String.fromCharCode(127); break; case 106: keyname = "*"; break; case 107: keyname = "+"; break; case 109: keyname = "-"; break; case 110: keyname = "."; break; case 111: keyname = "/"; break; case 144: keyname = "numlock"; break; case 145: keyname = "scroll"; break; case 186: keyname = ";"; break; case 187: keyname = "="; break; case 188: keyname = ","; break; case 189: keyname = "-"; break; case 190: keyname = "."; break; case 191: keyname = "/"; break; case 192: keyname = "`"; break; case 219: keyname = "["; break; case 220: keyname = "\\"; break; case 221: keyname = "]"; break; case 222: keyname = "'"; break; default: if (code >= 96 && code <= 105) { keyname = (code - 96).toString(); } else if (code >= 112 && code <= 123) { keyname = "f" + (code - 111); } else { keyname = String.fromCharCode(code).toLowerCase(); } break; } return keyname; } ////////////////////////////////////////////////////////////////////// var OutputConfig = function() {} OutputConfig.prototype = plt.baselib.heir(WorldConfigOption.prototype); var isOutputConfig = plt.baselib.makeClassPredicate(OutputConfig); // // ToDraw var ToDraw = function(handler) { WorldConfigOption.call(this, 'to-draw'); this.handler = handler; }; ToDraw.prototype = plt.baselib.heir(OutputConfig.prototype); ToDraw.prototype.toRawHandler = function(MACHINE, toplevelNode) { var that = this; var reusableCanvas; var reusableCanvasNode; var adaptedWorldFunction = adaptWorldFunction(this.handler); var worldFunction = function(world, success) { adaptedWorldFunction( world, function(v) { // fixme: once jsworld supports fail continuations, use them // to check the status of the scene object and make sure it's an // image. if (isImage(v) ) { var width = v.getWidth(); var height = v.getHeight(); if (! reusableCanvas) { reusableCanvas = imageLibrary.makeCanvas(width, height); // Note: the canvas object may itself manage objects, // as in the case of an excanvas. In that case, we must make // sure jsworld doesn't try to disrupt its contents! reusableCanvas.jsworldOpaque = true; reusableCanvasNode = rawJsworld.node_to_tree(reusableCanvas); } if (reusableCanvas.width !== width) { reusableCanvas.width = width; } if (reusableCanvas.height !== height) { reusableCanvas.height = height; } var ctx = reusableCanvas.getContext("2d"); v.render(ctx, 0, 0); success([toplevelNode, reusableCanvasNode]); } else { success([toplevelNode, rawJsworld.node_to_tree(plt.baselib.format.toDomNode(v))]); } }); }; var cssFunction = function(w, k) { if (reusableCanvas) { k([[reusableCanvas, ["width", reusableCanvas.width + "px"], ["height", reusableCanvas.height + "px"]]]); } else { k([]); } } return rawJsworld.on_draw(worldFunction, cssFunction); }; var DefaultDrawingOutput = function() { WorldConfigOption.call(this, 'to-draw'); }; DefaultDrawingOutput.prototype = plt.baselib.heir(WorldConfigOption.prototype); DefaultDrawingOutput.prototype.toRawHandler = function(MACHINE, toplevelNode) { var that = this; var worldFunction = function(world, success) { success([toplevelNode, rawJsworld.node_to_tree(plt.baselib.format.toDomNode(world))]); //k(rawJsworld.node_to_tree(plt.baselib.format.toDomNode(world))); }; var cssFunction = function(w, success) { success([]); } return rawJsworld.on_draw(worldFunction, cssFunction); }; ////////////////////////////////////////////////////////////////////// var StopWhen = function(handler) { WorldConfigOption.call(this, 'stop-when'); this.handler = handler; }; StopWhen.prototype = plt.baselib.heir(WorldConfigOption.prototype); StopWhen.prototype.toRawHandler = function(MACHINE, toplevelNode) { var that = this; var worldFunction = adaptWorldFunction(that.handler); return rawJsworld.stop_when(worldFunction); }; // // This needs to be cleaned up! // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // // The real low-level jsworld module: // var _js = jsworld.Jsworld; // var caller; // var setCaller = function(c) { // caller = function(op, args, k) { // c(op, args, k, handleError); // }; // }; // var unsetCaller = function() { // caller = function(op, args, k) { // throw new Error('caller not defined!'); // }; // }; // unsetCaller(); // // The restarted and things to set it // // Note that we never want to restart the same computation // // more than once, so we throw an error if someone tries to do that // var restarter; // var setRestarter = function(r) { // var hasRestarted = false; // restarter = function(v) { // if (hasRestarted) { // throw new Error('Cannot restart twice!'); // } // hasRestarted = true; // r(v); // }; // }; // var unsetRestarter = function() { // restarter = function() { // throw new Error('restarter not defined!'); // }; // }; // unsetRestarter(); // var errorReporter = function(e) { // // default: do nothing. // }; // var terminator; // var setTerminator = function(t) { // terminator = t; // }; // var unsetTerminator = function() { // terminator = function() { // throw new Error('terminator not defined!'); // }; // }; // unsetTerminator(); // // mutateStringsInDeepArray: array -> array // // walks and in-place mutates Scheme strings to primitive strings. // var mutateStringsInDeepArray = function(thing) { // var i, length; // if (typeof(thing) === 'object' && // thing.constructor === Array) { // length = thing.length; // for (i = 0; i < length; i++) { // thing[i] = mutateStringsInDeepArray(thing[i]); // } // } else if (types.isString(thing)) { // return thing.toString(); // } // return thing; // }; // var userConfigs = []; // var startUserConfigs = function(k) { // helpers.forEachK(userConfigs, // function(aConfig, k2) { // caller(aConfig.startup, aConfig.startupArgs, // function(res) { // aConfig.isRunning = true; // aConfig.shutdownArg = res; // k2() // }); // }, // handleError, // k); // } // var shutdownUserConfigs = function(k) { // // console.log('shutting down user configs'); // var theConfigs = userConfigs; // userConfigs = [] // helpers.forEachK(theConfigs, // function(aConfig, k2) { // // console.log(' shutting down a config'); // if (aConfig.isRunning) { // aConfig.isRunning = false; // caller(aConfig.shutdown, [aConfig.shutdownArg], k2); // } else { // k2(); // } // }, // handleError, // k); // } // var expandHandler = function(handler) { // return types.jsValue('function', function() { // var wrappedStimulusArgs = []; // for (var i = 0; i < arguments.length; i++) { // wrappedStimulusArgs.push( helpers.wrapJsValue(arguments[i]) ); // } // Jsworld.updateWorld( // function(w, k) { // var args = [w].concat(wrappedStimulusArgs); // caller(handler, args, k); // }, // function() {}); // }); // }; // // var unwrapWorldEffects = function(w) { // // if ( _js.has_effects(w) ) { // // var unwrappedEffects = // // helpers.map(function(e) { // // if ( types.isEffect(e) ) { // // return types.makeJsworldEffect(function(k) { // // caller(types.effectThunk(e), [], k); // // }); // // } // // else { // // return e; // // } // // }, // // w.getEffects()); // // var returnVal = _js.with_multiple_effects(w.getWorld(), unwrappedEffects); // // return returnVal; // // } // // else { // // return w; // // } // // }; // var deepUnwrapJsValues = function(x, k) { // if ( types.isJsValue(x) ) { // k(x.unbox()); // } // else if ( types.isRenderEffect(x) ) { // x.callImplementation(caller, function(y) { deepUnwrapJsValues(y, k); }); // } // // var effects = helpers.schemeListToArray( types.renderEffectEffects(x) ).reverse(); // // types.setRenderEffectEffects(x, types.EMPTY); // // // // helpers.forEachK(effects, // // function(ef, k2) { caller(ef, [], k2); }, // // handleError, // // function() { deepUnwrapJsValues(types.renderEffectDomNode(x), k); }); // // } // else if ( types.isPair(x) ) { // deepUnwrapJsValues(x.first(), function(first) { // deepUnwrapJsValues(x.rest(), function(rest) { // k( types.cons(first, rest) ); // }); // }); // } // else { // k(x); // } // }; // // isHandler: X -> boolean // // Right now, a handler is a function that consumes and produces // // configs. We should tighten up the type check eventually. // var isHandler = function(x) { // return typeof(x) == 'function'; // } // ////////////////////////////////////////////////////////////////////// // //From this point forward, we define wrappers to integrate jsworld // //with Moby. // // getBigBangWindow: -> window // var getBigBangWindow = function() { // if (window.document.getElementById("jsworld-div") !== undefined) { // return window; // } else { // var newDiv = window.document.createElement("div"); // newDiv.id = 'jsworld-div'; // window.document.appendChild(newDiv); // return window; // } // } // // types are // // sexp: (cons node (listof sexp)) // // css-style: (node (listof (list string string))) // // Exports: // var isPair = types.isPair; // var isEmpty = function(x) { return x === types.EMPTY; }; // var isList = function(x) { return (isPair(x) || isEmpty(x)); }; // // The default printWorldHook will write the written content of the node. // // We probably want to invoke the pretty printer here instead! // Jsworld.printWorldHook = function(world, node) { // var newNode; // if(node.lastChild == null) { // newNode = types.toDomNode(world); // node.appendChild(newNode); // helpers.maybeCallAfterAttach(newNode); // } else { // newNode = types.toDomNode(world); // node.replaceChild(newNode, node.lastChild); // helpers.maybeCallAfterAttach(newNode); // } // }; // // Figure out the target of an event. // // http://www.quirksmode.org/js/events_properties.html#target // var findEventTarget = function(e) { // var targ; // if (e.target) // targ = e.target; // else if (e.srcElement) // targ = e.srcElement; // if (targ.nodeType == 3) // defeat Safari bug // targ = targ.parentNode; // return targ; // } // // isNode: any -> boolean // // Returns true if the thing has a nodeType. // var isNode = function(thing) { // return thing && typeof(thing.nodeType) != 'undefined'; // } // // checkWellFormedDomTree: X X (or number undefined) -> void // // Check to see if the tree is well formed. If it isn't, // // we need to raise a meaningful error so the user can repair // // the structure. // // // // Invariants: // // The dom tree must be a pair. // // The first element must be a node. // // Each of the rest of the elements must be dom trees. // // If the first element is a text node, it must NOT have children. // var checkWellFormedDomTree = function(x, top, index) { // var fail = function(formatStr, formatArgs) { // throw types.schemeError( // types.incompleteExn(types.exnFailContract, // helpers.format(formatStr, formatArgs), // [])); // } // if (_js.isPage(x)) { // return; // } // if (types.isPair(x)) { // var firstElt = x.first(); // var restElts = x.rest(); // if (! isNode(firstElt)) { // fail("on-draw: expected a dom-element, but received ~s instead, the first element within ~s", [firstElt, top]); // } // if (firstElt.nodeType == Node.TEXT_NODE && !restElts.isEmpty() ) { // fail("on-draw: the text node ~s must not have children. It has ~s", [firstElt, restElts]); // } // var i = 2; // while( !restElts.isEmpty() ) { // checkWellFormedDomTree(restElts.first(), x, i); // restElts = restElts.rest(); // i++; // } // } else { // var formatStr = "on-draw: expected a dom-s-expression, but received ~s instead"; // var formatArgs = [x]; // if (index != undefined) { // formatStr += ", the ~a element within ~s"; // formatArgs.push( helpers.ordinalize(index) ); // formatArgs.push(top); // } // formatStr += "."; // fail(formatStr, formatArgs); // } // }; // // Compatibility for attaching events to nodes. // var attachEvent = function(node, eventName, fn) { // if (node.addEventListener) { // // Mozilla // node.addEventListener(eventName, fn, false); // } else { // // IE // node.attachEvent('on' + eventName, fn, false); // } // return function() { // detachEvent(node, eventName, fn); // } // }; // var detachEvent = function(node, eventName, fn) { // if (node.addEventListener) { // // Mozilla // node.removeEventListener(eventName, fn, false); // } else { // // IE // node.detachEvent('on' + eventName, fn, false); // } // } // var preventDefault = function(event) { // if (event.preventDefault) { // event.preventDefault(); // } else { // event.returnValue = false; // } // } // var stopPropagation = function(event) { // if (event.stopPropagation) { // event.stopPropagation(); // } else { // event.cancelBubble = true; // } // } // // bigBang: world dom (listof (list string string)) (arrayof handler) -> world // Jsworld.bigBang = function(initWorld, toplevelNode, handlers, theCaller, theRestarter, onFail) { // // shutdownListeners: arrayof (-> void) // // We maintain a list of thunks that need to be called as soon as we come out of // // bigBang, to do cleanup. // var shutdownListeners = []; // var onTermination = function(w) { // for (var i = 0; i < shutdownListeners.length; i++) { // try { // shutdownListeners[i](); // } catch (e) { } // } // shutdownUserConfigs(function() { // unsetCaller(); // theRestarter(w); // }); // } // //console.log('in high level big-bang'); // errorReporter = onFail; // setCaller(theCaller); // setRestarter(theRestarter); // setTerminator(function(w) { // detachEvent(toplevelNode, 'click', absorber); // shutdownUserConfigs(function() { // unsetCaller(); // unsetTerminator(); // restarter(w); // }); // }); // var attribs = types.EMPTY; // // Ensure that the toplevelNode can be focused by mouse or keyboard // toplevelNode.tabIndex = 0; // // Absorb all click events so they don't bubble up. // var absorber = function(e) { // preventDefault(e); // stopPropagation(e); // return false; // } // attachEvent(toplevelNode, 'click', absorber); // shutdownListeners.push(function() { detachEvent(toplevelNode, 'click', absorber)}); // var config = new world.Kernel.config.WorldConfig(); // for(var i = 0; i < handlers.length; i++) { // if (isList(handlers[i])) { // attribs = handlers[i]; // } // else if (isHandler(handlers[i])) { // config = handlers[i](config); // } // else if ( types.isWorldConfig(handlers[i]) ) { // handlers[i].startupArgs = helpers.map(expandHandler, handlers[i].startupArgs); // userConfigs.push(handlers[i]); // } // } // config = config.updateAll({'changeWorld': Jsworld.updateWorld, // 'shutdownWorld': Jsworld.shutdownWorld}); // var stimuli = new world.Kernel.stimuli.StimuliHandler(config, caller, restarter); // var wrappedHandlers = []; // var wrappedRedraw; // var wrappedRedrawCss; // if (config.lookup('onDraw')) { // wrappedRedraw = function(w, k) { // try { // caller(config.lookup('onDraw'), [w], // function(newDomTree) { // deepUnwrapJsValues(newDomTree, function(unwrappedTree) { // checkWellFormedDomTree(unwrappedTree, unwrappedTree, undefined); // var result = [toplevelNode, // helpers.deepListToArray(unwrappedTree)]; // k(result); // }); // }); // } catch (e) { // handleError(e); // // throw e; // } // } // if (config.lookup('onDrawCss')) { // wrappedRedrawCss = function(w, k) { // try { // caller(config.lookup('onDrawCss'), [w], // function(res) { // var result = helpers.deepListToArray(res); // result = mutateStringsInDeepArray(result); // // plt.Kernel.setLastLoc(undefined); // k(result); // }); // } catch (e) { // handleError(e); // // throw e; // } // } // } // else { // wrappedRedrawCss = function(w, k) { k([]); }; // } // wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); // } else if (config.lookup('onRedraw')) { // var reusableCanvas = undefined; // var reusableCanvasNode = undefined; // wrappedRedraw = function(w, k) { // try { // //console.log('in onRedraw handler'); // caller(config.lookup('onRedraw'), [w], // function(aScene) { // // Performance hack: if we're using onRedraw, we know // // we've got a scene, so we optimize away the repeated // // construction of a canvas object. // if ( world.Kernel.isImage(aScene) ) { // var width = aScene.getWidth(); // var height = aScene.getHeight(); // if (! reusableCanvas) { // reusableCanvas = world.Kernel.makeCanvas(width, height); // // Note: the canvas object may itself manage objects, // // as in the case of an excanvas. In that case, we must make // // sure jsworld doesn't try to disrupt its contents! // reusableCanvas.jsworldOpaque = true; // reusableCanvasNode = _js.node_to_tree(reusableCanvas); // } // reusableCanvas.width = width; // reusableCanvas.height = height; // var ctx = reusableCanvas.getContext("2d"); // aScene.render(ctx, 0, 0); // k([toplevelNode, reusableCanvasNode]); // } else { // k([toplevelNode, _js.node_to_tree(types.toDomNode(aScene))]); // } // }); // } catch (e) { // handleError(e); // // throw e; // } // } // wrappedRedrawCss = function(w, k) { // //console.log('in RedrawCss handler'); // k([[reusableCanvas, // ["width", reusableCanvas.width + "px"], // ["height", reusableCanvas.height + "px"]]]); // } // wrappedHandlers.push(_js.on_draw(wrappedRedraw, wrappedRedrawCss)); // } else { // wrappedHandlers.push(_js.on_world_change // (function(w, k) { // Jsworld.printWorldHook(w, toplevelNode); // k(); // })); // } // if (config.lookup('tickDelay')) { // var wrappedTick = function(w, k) { // caller(config.lookup('onTick'), // [w], // k); // } // var wrappedDelay = jsnums.toFixnum( config.lookup('tickDelay') ); // wrappedHandlers.push(_js.on_tick(wrappedDelay, wrappedTick)); // } // if (config.lookup('stopWhen')) { // wrappedHandlers.push(_js.stop_when( // function(w, k) { // caller(config.lookup('stopWhen'), [w], // function(res) { k(res); }); // })); // } // if (config.lookup('onKey')) { // var wrappedKey = function(w, e, k) { // caller(config.lookup('onKey'), [w, helpers.getKeyCodeName(e)], k); // } // wrappedHandlers.push(_js.on_key(wrappedKey)); // toplevelNode.focus(); // } // if (config.lookup('initialEffect')) { // var updaters = // world.Kernel.applyEffect(config.lookup('initialEffect')); // for (var i = 0 ; i < updaters.length; i++) { // if (config.lookup('stopWhen') && // config.lookup('stopWhen')([initWorld])) { // break; // } else { // initWorld = updaters[i](initWorld); // } // } // } // _js.big_bang(toplevelNode, // initWorld, // wrappedHandlers, // helpers.assocListToHash(attribs), // terminator); // startUserConfigs(function() {}); // return { // breaker: function() { // handleError(types.schemeError( // types.incompleteExn(types.exnBreak, 'user break', []))); // } // }; // } // var handleError = function(e) { // // helpers.reportError(e); // // When something bad happens, shut down // // the world computation. // // helpers.reportError("Shutting down jsworld computations"); // // world.Kernel.stimuli.onShutdown(); // world.Kernel.stimuli.massShutdown(); // shutdownUserConfigs(function() { // errorReporter(e); // // console.log('Got an error, the error was:'); // // console.log(e); // if (typeof(console) !== 'undefined' && console.log) { // if (e.stack) { // console.log(e.stack); // } // else { // console.log(e); // } // } // if ( types.isSchemeError(e) ) { // terminator(e); // } // else if ( types.isInternalError(e) ) { // terminator(e); // } // else if (typeof(e) == 'string') { // terminator( types.schemeError(types.incompleteExn(types.exnFail, e, [])) ); // } // else if (e instanceof Error) { // terminator( types.schemeError(types.incompleteExn(types.exnFail, e.message, [])) ); // } // else { // terminator( types.schemeError(e) ); // } // }); // } // // updateWorld: CPS( CPS(world -> world) -> void ) // Jsworld.updateWorld = function(updater, k) { // var wrappedUpdater = function(w, k2) { // try { // updater(w, k2); // } catch (e) { // if (typeof(console) !== 'undefined' && console.log && e.stack) { // console.log(e.stack); // } // handleError(e); // // k2(w); // } // } // _js.change_world(wrappedUpdater, k); // } // // shutdownWorld: -> void // // Shut down all world computations. // Jsworld.shutdownWorld = function() { // _js.shutdown(); // }; // // var getAttribs = function(args) { // // if (args.length == 0) { // // return [] // // } // // if (args.length == 1) { // // return helpers.assocListToHash(args[0]); // // } else { // // throw new Error("getAttribs recevied unexpected value for args: " // // + args); // // } // // } // Jsworld.p = _js.p; // Jsworld.div = _js.div; // Jsworld.buttonBang = function(updateWorldF, effectF, attribs) { // var wrappedF = function(w, evt, k) { // try { // // FIXME: Get effects back online! // // caller(effectF, [world], // // function(effect) { // caller(updateWorldF, [w], // function(newWorld) { // // world.Kernel.applyEffect(effect); // k(newWorld); // }); // // }); // } catch (e) { // if (typeof(console) !== 'undefined' && console.log && e.stack) { // console.log(e.stack); // } // handleError(e); // // k(w); // } // } // return _js.button(wrappedF, attribs); // }; // Jsworld.input = function(type, updateF, attribs) { // var wrappedUpdater = function(w, evt, k) { // caller(updateF, [w, evt], k); // } // return _js.input(type, wrappedUpdater, attribs); // }; // Jsworld.get_dash_input_dash_value = function(node) { // // plt.Kernel.check(node, // // function(x) { return (plt.Kernel.isString(node) || // // node.nodeType == // // Node.ELEMENT_NODE) }, // // "get-input-value", // // "dom-node", // // 1); // if (types.isString(node)) { // return (document.getElementById(node).value || ""); // } else { // return (node.value || ""); // } // }; // // Images. // Jsworld.img = _js.img; // // text: string -> node // Jsworld.text = _js.text; // Jsworld.select = function(options, updateF, attribs) { // var wrappedUpdater = function(w, e, k) { // // console.log(e); // caller(updateF, [w, e.target.value], k); // } // return _js.select(attribs, options, wrappedUpdater); // }; // ////////////////////////////////////////////////////////////////////// // Jsworld.emptyPage = _js.emptyPage; // Jsworld.placeOnPage = function(elt, left, top, page) { // deepUnwrapJsValues(elt, function(newElt) { // elt = types.toDomNode(newElt);}); // return _js.placeOnPage(elt, left, top, page); // }; // var convertAttribList = function(attribList) { // var nextElt; // var key, val; // var hash = {}; // while (attribList !== EMPTY) { // nextElt = attribList.first; // key = nextElt.first; // val = nextElt.rest.first; // key = String(key); // if (isString(val)) { // val = String(val); // } else if (isBoolean(val)) { // // do nothing: the representation is the same. // } else if (isSymbol(val)) { // if (String(val) === 'true') { // val = true; // } else if (String(val) === 'false') { // val = false; // } else { // val = String(val); // } // } else { // // raise error: neither string nor boolean // throw new Error( // plt.baselib.format.format( // "attribute value ~s neither a string nor a boolean", // [val])); // } // hash[key] = val; // attribList = attribList.rest; // } // return hash; // }