Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.
For the best experience please use the latest Chrome, Safari, or Firefox browser.
digital equipments | |
+ | network everywhere |
+ | sensors everywhere |
+ | big/open/many data |
= | Diffuse Computing |
TOO MANY | TECHNOLOGIES |
---|
LIGHTTPD | 0.08 |
---|---|
JETTY | 0.6 |
VLC | 0.6 |
EMACS | 1.6 |
GCC | 6.2 |
CHROMIUM | 7 |
FIREFOX | 9 |
LINUX | 15.5 |
client html html | server #1 server #2 |
client html | server #1 |
client JS JS JS | server |
H | ::= | JavaScript |
---|---|---|
| | <tag> {name: H, ... ,H }[</tag>] | |
|s | service [id](id, ...){H; ...} | |
| | ~{H} | |
|~ | ${H} |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html"> <SCRIPT src="fib.js" type="application/javascript"/> </HEAD> <BODY> <TABLE> <TR> <TD onclick="alert('fib(1)='+fib(1))">1</TD> </TR> <TR> <TD onclick="alert('fib(2)='+fib(2))">2</TD> </TR> <TR> <TD onclick="alert('fib(3)='+fib(3))">3</TD> </TR> </TABLE> </BODY> </HTML>
<HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { <TR> { <TD> { onclick: ~{alert('fib(1)='+fib(1))}, 1} }, <TR> { <TD> { onclick: ~{alert('fib(2)='+fib(2))}, 2} }, <TR> { <TD> { onclick: ~{alert('fib(3)='+fib(3))}, 3} } } </TABLE> } </BODY> } </HTML>
service fibonacci() { return <HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { <TR> { <TD> { onclick: ~{alert('fib(1)='+fib(1))}, 1} }, <TR> { <TD> { onclick: ~{alert('fib(2)='+fib(2))}, 2} }, <TR> { <TD> { onclick: ~{alert('fib(3)='+fib(3))}, 3} } } </TABLE> } </BODY> } </HTML> }
service fibonacci() { return <HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { <TRFIB> { onclick: ~{alert('fib(1)='+fib(1))}, 1}, <TRFIB> { onclick: ~{alert('fib(2)='+fib(2))}, 2}, <TRFIB> { onclick: ~{alert('fib(3)='+fib(3))}, 3} } </TABLE> } </BODY> } </HTML> } function TRFIB( attrs, nodes ) { return <TR> { <TD> { onclick: attrs.onclick, nodes } }; }
service fibonacci() { return <HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { <TRFIB> { 1 }, <TRFIB> { 2 }, <TRFIB> { 3 } } </TABLE> } </BODY> } </HTML> } function TRFIB( _, i ) { return <TR> { <TD> { onclick: ~{ alert( ${"fib("+i+")="} + fib(${i}) ), i } } } }
service fibonacci() { return <HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { [1, 2, 3].map( function( i ) { return <TRFIB> { i } } ); } </TABLE> } </BODY> } </HTML> } function TRFIB( _, i ) { return <TR> { <TD> { onclick: ~{ alert( ${"fib(" + i + ")="} + fib(${i}) ), i } } } }
service fibonacci() { return <HTML> { <HEAD> { jscript: "fib.js" } <BODY> { <TABLE> { cache } </TABLE> } </BODY> } </HTML> } var cache = [1, 2, 3].map( function( i ) { return <TRFIB> { i } } ) ); function TRFIB( _, i ) { return <TR> { <TD> { onclick: ~{ alert( ${"fib(" + i + ")="} + fib(${i}) ), i } } } }
<HEAD> { jscript: "http://..flipcounter.js" }
type flipcounter = "div[data-hss-tag=flipcounter]"
function FLIPCOUNTER( attrs ) { return <DIV> { "data-hss-tag": "flipcounter", id: attrs.id, ~{ window.addEventListener( "load", function() { return new flipCounter( ${attrs.id} ) } ) } } }
var wmap = <SVG:IMG> { src: "http://wikipedia.org/..."}; var balloon = "HTML4.01"; <DIV> { wmap, balloon, ~{ ${wmap}.addEventListener( "load", function (e) { return canvas.Arrow( ${balloon}.boundingBox(), ${wmap}.france.boundingBox())})}}
URL | |
+ | function |
---|---|
= | service |
service fibonacci( { n: 10 } ) { return <HTML> { <TABLE> { [1, 2, ..., 40] .slice( 0, n ) .map( function( i ) { return <TR> { <TD> { "fib(" i ")=" }, <TD> { fib( i ) } } </TR> } ) } </TABLE> } }
iframe.src = ${fibonacci}( {n: 10} ); img.src = ${getMandelbrotImage}( 1024 );
${fib}( 10 ) .post( function( el ) { body.appendChild( el ) }
${fibarray}( 10 ) .post( function( arr ) { document.body.appendChild( <TABLE> { arr.map( function( i ) { return <TR> { <TD> { i.key }, <TD> { i.data } } } ) } ) };
service fibarray( n ) { return [ 1, 2, ..., 40 ] .slice( 0, n ) .map( function( i ) { return { key: i, data: fib( i ) } } ) }
<TABLE> { <TR> { <TD> { onclick: ~{ ${slidePrev}.post() }, <IMG> { :src "prev.png" } }, <TD> { onclick: ~{ ${slideNext}.post() }, <IMG> { :src "next.png" } } } } service slideNext() { ... } service slidePrev() { ... }
MOUSE | EVENTS |
---|---|
KEYBOARD | EVENTS |
WINDOW | EVENTS |
MULTIMEDIA | EVENTS |
SERVER | EVENTS |
var hop = require( "hop" ); service slidePrev() { hop.broadcast( "goto-slide", -1 ); } service slideNext() { hop.broadcast( "goto-slide", +1 ); }
<HTML> { ~{ server.addEventListener( "goto-slide", function( e ) { gotoSlide( currentSlide().num + e.value ); } ); } ... }
// The code is heavily inspired by Modernizr http://www.modernizr.com/ var pfx = (function () { var style = document.createElement('dummy').style, prefixes = 'Webkit Moz O ms Khtml'.split(' '), memory = {}; return function ( prop ) { if ( typeof memory[ prop ] === "undefined" ) { var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1), props = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' '); memory[ prop ] = null; for ( var i in props ) { if ( style[ props[i] ] !== undefined ) { memory[ prop ] = props[i]; break; } } } return memory[ prop ]; }; })(); // `arraify` takes an array-like object and turns it into real Array // to make all the Array.prototype goodness available. var arrayify = function ( a ) { return [].slice.call( a ); }; // `css` function applies the styles given in `props` object to the element // given as `el`. It runs all property names through `pfx` function to make // sure proper prefixed version of the property is used. var css = function ( el, props ) { var key, pkey; for ( key in props ) { if ( props.hasOwnProperty(key) ) { pkey = pfx(key); if ( pkey !== null ) { el.style[pkey] = props[key]; } } } return el; }; // `toNumber` takes a value given as `numeric` parameter and tries to turn // it into a number. If it is not possible it returns 0 (or other value // given as `fallback`). var toNumber = function (numeric, fallback) { return isNaN(numeric) ? (fallback || 0) : Number(numeric); }; // `byId` returns element with given `id` - you probably have guessed that ;) var byId = function ( id ) { return document.getElementById(id); }; // `$` returns first element for given CSS `selector` in the `context` of // the given element or whole document. var $ = function ( selector, context ) { context = context || document; return context.querySelector(selector); }; // `$$` return an array of elements for given CSS `selector` in the `context` of // the given element or whole document. var $$ = function ( selector, context ) { context = context || document; return arrayify( context.querySelectorAll(selector) ); }; // `triggerEvent` builds a custom DOM event with given `eventName` and `detail` data // and triggers it on element given as `el`. var triggerEvent = function (el, eventName, detail) { var event = document.createEvent("CustomEvent"); event.initCustomEvent(eventName, true, true, detail); el.dispatchEvent(event); }; // `translate` builds a translate transform string for given data. var translate = function ( t ) { return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) "; }; // `rotate` builds a rotate transform string for given data. // By default the rotations are in X Y Z order that can be reverted by passing `true` // as second parameter. var rotate = function ( r, revert ) { var rX = " rotateX(" + r.x + "deg) ", rY = " rotateY(" + r.y + "deg) ", rZ = " rotateZ(" + r.z + "deg) "; return revert ? rZ+rY+rX : rX+rY+rZ; }; // `scale` builds a scale transform string for given data. var scale = function ( s ) { return " scale(" + s + ") "; }; // `perspective` builds a perspective transform string for given data. var perspective = function ( p ) { return " perspective(" + p + "px) "; }; // `getElementFromHash` returns an element located by id from hash part of // window location. var getElementFromHash = function () { // get id from url ` or `slide-id` and "enhanced" `\/?/,"") ); }; // `computeWindowScale` counts the scale factor between window size and size // defined for the presentation in the config. var computeWindowScale = function ( config ) { var hScale = window.innerHeight / config.height, wScale = window.innerWidth / config.width, scale = hScale > wScale ? wScale : hScale; if (config.maxScale && scale > config.maxScale) { scale = config.maxScale; } if (config.minScale && scale < config.minScale) { scale = config.minScale; } return scale; }; // CHECK SUPPORT var body = document.body; var ua = navigator.userAgent.toLowerCase(); var impressSupported = // browser should support CSS 3D transtorms ( pfx("perspective") !== null ) && // and `classList` and `dataset` APIs ( body.classList ) && ( body.dataset ) && // but some mobile devices need to be blacklisted, // because their CSS 3D support or hardware is not // good enough to run impress.js properly, sorry... ( ua.search(/(iphone)|(ipod)|(android)/) === -1 ); if (!impressSupported) { // we can't be sure that `classList` is supported body.className += " impress-not-supported "; } else { body.classList.remove("impress-not-supported"); body.classList.add("impress-supported"); } // GLOBALS AND DEFAULTS // This is were the root elements of all impress.js instances will be kept. // Yes, this means you can have more than one instance on a page, but I'm not // sure if it makes any sense in practice ;) var roots = {}; // some default config values. var defaults = { width: 1024, height: 768, maxScale: 1, minScale: 0, perspective: 1000, transitionDuration: 1000 }; // it's just an empty function ... and a useless comment. var empty = function () { return false; }; // IMPRESS.JS API // And that's where interesting things will start to happen. // It's the core `impress` function that returns the impress.js API // for a presentation based on the element with given id ('impress' // by default). var impress = window.impress = function ( rootId ) { // If impress.js is not supported by the browser return a dummy API // it may not be a perfect solution but we return early and avoid // running code that may use features not implemented in the browser. if (!impressSupported) { return { init: empty, goto: empty, prev: empty, next: empty, current: empty }; } rootId = rootId || "impress"; // if given root is already initialized just return the API if (roots["impress-root-" + rootId]) { return roots["impress-root-" + rootId]; } // data of all presentation steps var stepsData = {}; // element of currently active step var activeStep = null; // current state (position, rotation and scale) of the presentation var currentState = null; // array of step elements var steps = null; // configuration options var config = null; // scale factor of the browser window var windowScale = null; // root presentation elements var root = byId( rootId ); var canvas = document.createElement("div"); var initialized = false; // STEP EVENTS // // There are currently two step events triggered by impress.js // `slideenter` is triggered when the step is shown on the // screen (the transition from the previous one is finished) and // `slideleave` is triggered when the step is left (the // transition to next step just starts). // reference to last entered step var lastEntered = null; // `onStepEnter` is called whenever the step element is entered // but the event is triggered only if the step is different than // last entered step. var onStepEnter = function (step) { if (lastEntered !== step) { triggerEvent(step, "slideenter"); lastEntered = step; } }; // `onStepLeave` is called whenever the step element is left // but the event is triggered only if the step is the same as // last entered step. var onStepLeave = function (step) { if (lastEntered === step) { triggerEvent(step, "slideleave"); lastEntered = null; } }; // `initStep` initializes given step element by reading data from its // data attributes and setting correct styles. var initStep = function ( el, idx ) { var data = el.dataset, step = { translate: { x: toNumber(data.x), y: toNumber(data.y), z: toNumber(data.z) }, rotate: { x: toNumber(data.rotateX), y: toNumber(data.rotateY), z: toNumber(data.rotateZ || data.rotate) }, scale: toNumber(data.scale, 1), el: el }; if ( !el.id ) { el.id = "step-" + (idx + 1); } el.index = idx; stepsData["impress-" + el.id] = step; css(el, { position: "absolute", transform: "translate(-50%,-50%)" + translate(step.translate) + rotate(step.rotate) + scale(step.scale), transformStyle: "preserve-3d" }); }; // `init` API function that initializes (and runs) the presentation. var init = function () { if (initialized) { return; } // First we set up the viewport for mobile devices. // For some reason iPad goes nuts when it is not done properly. var meta = $("meta[name='viewport']") || document.createElement("meta"); meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no"; if (meta.parentNode !== document.head) { meta.name = 'viewport'; document.head.appendChild(meta); } // initialize configuration object var rootData = root.dataset; config = { width: toNumber( rootData.width, defaults.width ), height: toNumber( rootData.height, defaults.height ), maxScale: toNumber( rootData.maxScale, defaults.maxScale ), minScale: toNumber( rootData.minScale, defaults.minScale ), perspective: toNumber( rootData.perspective, defaults.perspective ), transitionDuration: toNumber( rootData.transitionDuration, defaults.transitionDuration ) }; windowScale = computeWindowScale( config ); // wrap steps with "canvas" element arrayify( root.childNodes ).forEach(function ( el ) { canvas.appendChild( el ); }); root.appendChild(canvas); // set initial styles document.documentElement.style.height = "100%"; css(body, { height: "100%", overflow: "hidden" }); var rootStyles = { position: "absolute", transformOrigin: "top left", transition: "all 0s ease-in-out", transformStyle: "preserve-3d" }; css(root, rootStyles); css(root, { top: "50%", left: "50%", transform: perspective( config.perspective/windowScale ) + scale( windowScale ) }); css(canvas, rootStyles); body.classList.remove("impress-disabled"); body.classList.add("impress-enabled"); // get and init steps steps = $$(".step", root); steps.forEach( initStep ); // set a default initial state of the canvas currentState = { translate: { x: 0, y: 0, z: 0 }, rotate: { x: 0, y: 0, z: 0 }, scale: 1 }; initialized = true; triggerEvent(root, "impress:init", { api: roots[ "impress-root-" + rootId ] }); }; // `getStep` is a helper function that returns a step element defined by parameter. // If a number is given, step with index given by the number is returned, if a string // is given step element with such id is returned, if DOM element is given it is returned // if it is a correct step element. var getStep = function ( step ) { if (typeof step === "number") { step = step < 0 ? steps[ steps.length + step] : steps[ step ]; } else if (typeof step === "string") { step = byId(step); } return (step && step.id && stepsData["impress-" + step.id]) ? step : null; }; // used to reset timeout for `slideenter` event var stepEnterTimeout = null; // `goto` API function that moves to step given with `el` parameter (by index, id or element), // with a transition `duration` optionally given as second parameter. var goto = function ( el, duration ) { if ( !initialized || !(el = getStep(el)) ) { // presentation not initialized or given element is not a step return false; } // Sometimes it's possible to trigger focus on first link with some keyboard action. // Browser in such a case tries to scroll the page to make this element visible // (even that body overflow is set to hidden) and it breaks our careful positioning. // // So, as a lousy (and lazy) workaround we will make the page scroll back to the top // whenever slide is selected // // If you are reading this and know any better way to handle it, I'll be glad to hear about it! window.scrollTo(0, 0); var step = stepsData["impress-" + el.id]; if ( activeStep ) { activeStep.classList.remove("active"); body.classList.remove("impress-on-" + activeStep.id); } el.classList.add("active"); body.classList.add("impress-on-" + el.id); // compute target state of the canvas based on given step var target = { rotate: { x: -step.rotate.x, y: -step.rotate.y, z: -step.rotate.z }, translate: { x: -step.translate.x, y: -step.translate.y, z: -step.translate.z }, scale: 1 / step.scale }; // Check if the transition is zooming in or not. // // This information is used to alter the transition style: // when we are zooming in - we start with move and rotate transition // and the scaling is delayed, but when we are zooming out we start // with scaling down and move and rotation are delayed. var zoomin = target.scale >= currentState.scale; if( isNaN( duration ) && el.hasAttribute( "data-duration" ) ) { duration = toNumber( el.getAttribute( "data-duration" ), config.transitionDuration ); } else { duration = toNumber(duration, config.transitionDuration); } var delay = (duration / 2); // if the same step is re-selected, force computing window scaling, // because it is likely to be caused by window resize if (el === activeStep) { windowScale = computeWindowScale(config); } var targetScale = target.scale * windowScale; // trigger leave of currently active element (if it's not the same step again) if (activeStep && activeStep !== el) { onStepLeave(activeStep); } // Now we alter transforms of `root` and `canvas` to trigger transitions. // // And here is why there are two elements: `root` and `canvas` - they are // being animated separately: // `root` is used for scaling and `canvas` for translate and rotations. // Transitions on them are triggered with different delays (to make // visually nice and 'natural' looking transitions), so we need to know // that both of them are finished. css(root, { // to keep the perspective look similar for different scales // we need to 'scale' the perspective, too transform: perspective( config.perspective / targetScale ) + scale( targetScale ), transitionDuration: duration + "ms", transitionDelay: (zoomin ? delay : 0) + "ms" }); css(canvas, { transform: rotate(target.rotate, true) + translate(target.translate), transitionDuration: duration + "ms", transitionDelay: (zoomin ? 0 : delay) + "ms" }); // Here is a tricky part... // // If there is no change in scale or no change in rotation and translation, it means there was actually // no delay - because there was no transition on `root` or `canvas` elements. // We want to trigger `slideenter` event in the correct moment, so here we compare the current // and target values to check if delay should be taken into account. // // I know that this `if` statement looks scary, but it's pretty simple when you know what is going on // - it's simply comparing all the values. if ( currentState.scale === target.scale || (currentState.rotate.x === target.rotate.x && currentState.rotate.y === target.rotate.y && currentState.rotate.z === target.rotate.z && currentState.translate.x === target.translate.x && currentState.translate.y === target.translate.y && currentState.translate.z === target.translate.z) ) { delay = 0; } var dir = 1; if( activeStep && (activeStep.index > el.index) ) dir = -1; // MS: invoke the optional slideleave user hook if (activeStep) { if (("onkeyup" in activeStep) && (activeStep.onkeyup instanceof Function)) { var ev = new HopEvent("slideleave"); ev.target = el; ev.direction = dir; activeStep.onkeyup(ev); } } // store current state currentState = target; activeStep = el; // MS: invoke the optional slideenter user hook el.setAttribute("data-step", "0"); if ("onkeydown" in el) { if (el.onkeydown instanceof Function) { var ev = new HopEvent("slideenter"); ev.target = el; ev.direction = dir; el.onkeydown(ev); } } // And here is where we trigger `slideenter` event. // We simply set up a timeout to fire it taking transition duration (and possible delay) into account. // // I really wanted to make it in more elegant way. The `transitionend` event seemed to be the best way // to do it, but the fact that I'm using transitions on two separate elements and that the `transitionend` // event is only triggered when there was a transition (change in the values) caused some bugs and // made the code really complicated, cause I had to handle all the conditions separately. And it still // needed a `setTimeout` fallback for the situations when there is no transition at all. // So I decided that I'd rather make the code simpler than use shiny new `transitionend`. // // If you want learn something interesting and see how it was done with `transitionend` go back to // version 0.5.2 of impress.js: http://github.com/bartaz/impress.js/blob/0.5.2/js/impress.js window.clearTimeout(stepEnterTimeout); stepEnterTimeout = window.setTimeout(function() { onStepEnter(activeStep); }, duration + delay); return el; }; // `prev` API function goes to previous step (in document order) var prev = function () { var prev = steps.indexOf( activeStep ) - 1; prev = prev >= 0 ? steps[ prev ] : steps[ steps.length-1 ]; return goto(prev); }; // `next` API function goes to next step (in document order) var next = function () { var next = steps.indexOf( activeStep ) + 1; next = next < steps.length ? steps[ next ] : steps[ 0 ]; return goto(next); }; // `home` MS: API function goes to the first step (in document order) var home = function () { return goto(0); }; // `end` MS: API function goes to the last step (in document order) var end = function () { return goto(steps.length-1); }; // `current` MS: API function that returns the current slide var current = function () { return activeStep; }; // Adding some useful classes to step elements. // // All the steps that have not been shown yet are given `future` class. // When the step is entered the `future` class is removed and the `present` // class is given. When the step is left `present` class is replaced with // `past` class. // // So every step element is always in one of three possible states: // `future`, `present` and `past`. // // There classes can be used in CSS to style different types of steps. // For example the `present` class can be used to trigger some custom // animations when step is shown. root.addEventListener("impress:init", function(){ // STEP CLASSES steps.forEach(function (step) { step.classList.add("future"); }); root.addEventListener("slideenter", function (event) { event.target.classList.remove("past"); event.target.classList.remove("future"); event.target.classList.add("present"); }, false); root.addEventListener("slideleave", function (event) { event.target.classList.remove("present"); event.target.classList.add("past"); }, false); }, false); // Adding hash change support. root.addEventListener("impress:init", function(){ // last hash detected var lastHash = ""; // `step-id` to prevent default browser // scrolling to element in hash. // // And it has to be set after animation finishes, because in Chrome it // makes transtion laggy. // BUG: http://code.google.com/p/chromium/issues/detail?id=62820 root.addEventListener("slideenter", function (event) { window.location.hash = lastHash = "' ) { target = document.getElementById( href.slice(1) ); } } if ( api.goto(target) ) { event.stopImmediatePropagation(); event.preventDefault(); } }, false); // delegated handler for clicking on step elements document.addEventListener("click", function ( event ) { var target = event.target; // find closest step element that is not active while ( !(target.classList.contains("step") && !target.classList.contains("active")) && (target !== document.documentElement) ) { target = target.parentNode; } if ( api.goto(target) ) { event.preventDefault(); } }, false); // touch handler to detect taps on the left and right side of the screen // based on awesome work of @hakimel: https://github.com/hakimel/reveal.js document.addEventListener("touchstart", function ( event ) { if (event.touches.length === 1) { var x = event.touches[0].clientX, width = window.innerWidth * 0.3, result = null; if ( x < width ) { result = api.prev(); } else if ( x > window.innerWidth - width ) { result = api.next(); } if (result) { event.preventDefault(); } } }, false); // rescale presentation when window is resized window.addEventListener("resize", throttle(function () { // force going to active step again, to trigger rescaling api.goto( document.querySelector(".active"), 500 ); }, 250), false); }, false); })(document, window); // THAT'S ALL FOLKS! // // Thanks for reading it all. // Or thanks for scrolling down and reading the last part. // // I've learnt a lot when building impress.js and I hope this code and comments // will help somebody learn at least some part of it.
#include <stdio.h> /* a forward definition */ static void hello_world(); /* the entry point of the application */ int main( int argc, char *argv[], char *env[] ) { hello_world(); return 0; } void hello_world() { puts( "hello, world!" ); }
function hello_world() { console.log( "hello, world!" ); } // a top-level expression hello_world();
#include <stdio.h> #include <stdlib.h> int fib( int n ) { if( n < 2 ) { return 1; } else { return fib( n - 1 ) + fib( n - 2 ); } } int main( int argc, char *argv[], char *env[] ) { printf( "fib: %d\n", fib( atoi( argv[ 1 ] ) ) ); }
function fib( n ) { if( n < 2 ) { return 1; } else { return fib( n - 1 ) + fib( n - 2 ); } } var argv = process.argv; console.log( "fib: " + fib( parseInt( argv[ 1 ] ) ) );
// return a new string composed of the scheme of a URL // url_scheme( "http://hop.inria.fr" ) -> "http" char *url_scheme( char *url ) { char *s = url, *res; int i; while( *s++ != ':' ); i = s - url; res = malloc( i ); res[ i - 1 ] = 0; memcpy( res, url, i - 1 ); return res; }
function url_scheme( url ) { for( var i = 0; url.charAt( i ) != ":"; i++ ); return url.substring( 0, i ); }
// more efficient version with regular expressions function url_scheme( url ) { var m = url.match( new Regexp( "(^[^:]+)://" ) ); return m[ 1 ]; }
function url_scheme( url ) { return url.match( /(^[^:]+):[/][/]/ )[ 1 ]; }
#include <stdarg.h> static obj_t generic_entry( obj_t proc, ... ) { va_list argl; obj_t optional = BNIL, runner; va_start( argl, proc ); if( (runner = va_arg( argl, obj_t )) != BEOA ) { obj_t tail; optional = tail = MAKE_PAIR( runner, BNIL ); while( (runner = va_arg( argl, obj_t )) != BEOA ) { SET_CDR( tail, MAKE_PAIR( runner, BNIL ) ); tail = CDR( tail ); } } va_end( argl ); return apply( PROCEDURE_REF( proc, 3 ), optional ); }
function foo( a, b ) { return arguments[ 2 ]; } console.log( foo( 1, 2, 3 ) ) 3
double add( double x, double y ) { return x + y; }
function add( x, y ) { return x + y; }
var add = function( x, y ) { return x + y; }
function add( x, y ) { function plus( i, j ) { return i + j; } return plus( x - 0, y - 0 ); }
function makeAdd( x ) { function plus( y ) { return x + y; } return plus; } var inc = makeAdd( 1 ) inc( 24 ) 25
function o( f, g ) { return function( x ) { return f( g( x ) ); } }
var p1 = { x: 1, y: 2 }; function Point( x, y ) { this.x = x; this.y = y; } var p2 = new Point( 1, 2 ); var p3 = new Point(); { x: undefined, y: undefined } p1 instanceof Point false p2 instanceof Point true
Point.prototype = { norm: function() { return Math.sqrt( this.x*this.x + this.y*this.y ); }, z: 123 } var p4 = new Point( 0, 2 ); var p5 = new Point( 4, 5 ); p4.norm() 2 p4.z 123 p2.z undefined p4.__proto__ === p5.__proto__ === Point.prototype; true p4.z = 200; p4.z 200 p5.z 123 Point.prototype.z = 300; p5.z + p4.z 500
getX() { return this.x; } norm( getX( p4 ) ) undefined p4.getX = getX; p4.getX() 0
var p2 = new Point( 1, 2 ); p6.z = 5; p6[ "z" ] = p6.z + 1; if( "x" in p6 ) { delete p6.x; } p6.norm() NaN delete Point.prototype.norm; p6.norm() TypeError: Object #<Object> has no method 'norm'
var p3 = { get a() { return z - 1 }, set a( v ) { z = v + 1 } }; var z = 0; p3.a -1 p3.a = 5; p3.a 5 z 6
var p3 = new Point( 0, 0 ); Object.defineProperty( p3, "a", { get: function() { return z - 1; }, set: function( v ) { z = v + 1; }, configurable: false } ); p3.a -1 p3.a = 5; p3.a 5 z 6
(define (mapN f . l) (let loop ((l l)) (if (null? (car l)) '() (cons (apply f (map car l)) (loop (map cdr l)))))) (define (addN l) (reduce l (lambda (p c) (+ p c)))) (mapN '((1 2 3 4) (4 3 2 1)) addN) (5 5 5 5)
function mapN( f, vec0 ) { var len = arguments[ 1 ].length; var res = []; var vecs = Array.prototype.slice.call( arguments, 1, arguments.length ); for( var i = 0; i < len; i++ ) { res[ i ] = f.apply( false, vecs.map( function(v) { return v[ i ] } ) ); } return res; } function addN( _ ) { return Array.prototype.reduce.call( arguments, function( p, c ) { return p + c; } ); } mapN( addN, [1,2,3,4], [4,3,2,1] ) [ 5, 5, 5, 5 ]
> var v = 10; v 10 this.v 10 this[ "v" ] 10 // no global variables, global properties! var name = "v" this[ name ] 10 (function () { return this })().v 10
w = 20; w 20 this[ "w" ] 20 x ReferenceError: x is not defined function foo() { x = 4; } foo() undefined x 4
function foo( a, b ) { var c = a + b; try { var c = a - b; } catch( e ) { return -1; } return c; } foo( 1, 2 ) -1
function foo( a, b ) { var e = c + b; try { var c = a + b; } catch( e ) { return -1; } return e; } foo( 1, "2" ) undefined2
function foo( a ) { for( var i = 0; i <= a; i++ ) { var x = i; } return x; } foo( 10 ) 10
function foo( a ) { var t = new Array(); for( var i = 0; i <= a; i++ ) { var x; x = i; t[ i ] = function() { return x; } } return t[ a ]() - t[ 0 ](); } foo( 10 ) 0
function foo( a ) { var t = new Array(); for( var i = 0; i <= a; i++ ) { t[ i ] = (function( x ) { return function() { return x; } })( i ); } return t[ a ]() - t[ 0 ](); } foo( 10 ) 10
var a = new Array(); a[ "1" ] = 3; a[ "1" ] === a[ 1 ]; a[ 1 ] 3 a[ 1.00000000000001 ] undefined a[ 1.000000000000000001 ] 3
"123" + 4 '1234' 4 + "123" '4123' var x = "123"; x++; x 124 var o = { toString: function() {return "4"}}; o++; o 5 {valueOf: function() {return 1}} % 2 1 null % undefined NaN
<HTML> <BODY> <TABLE> <TR><TD onclick="alert( '1' )">1</TD></TR> <TR><TD onclick="alert( '2' )">2</TD></TR> <TR><TD onclick="alert( '3' )">3</TD></TR> </TABLE> </BODY> </HTML>
service() { return <HTML> { <BODY> { <TABLE> { <TR> { <TD> { onclick: ~{ alert( "1" ) }, 1 } }, <TR> { <TD> { onclick: ~{ alert( "2" ) }, 3 } }, <TR> { <TD> { onclick: ~{ alert( "2" ) }, 3 } } } </TABLE> } </BODY> } </HTML> }
<HTML> <BODY> <TABLE> <?php for( $i=1; $i<4; $i++ ) echo "<TR><TD onclick='alert( $i )'>$i</TD></TR>" ?> </TABLE> </BODY> </HTML>
service() { return <HTML> { <BODY> { <TABLE> { [1, 2, 3.map( function( i ) { <TD> { onclick: ~{alert( ${i} )}, i } } ); } </TABLE> } </BODY> } </HTML> }
service dom() { var el = <UL> { <LI> { "foo" }, <LI> { "bar" }, <LI> { "gee" } }; return <HTML> { <HEAD> { css: dom.resource( "iframe.hss" ) }, el, <BUTTON> { onclick: ~{ var c0 = ${el}.childNodes[ 0 ]; var c1 = ${el}.childNodes[ 1 ]; ${el}.replaceChild( c1, c0 ); ${el}.appendChild( c0 ); }, "rotate" } </BUTTON> } </HTML> }
service tower() { return <HTML> { <HEAD> { css: tower.resource( "iframe.hss" ) }, ~{ function clicked (msg) { var but = <BUTTON> { onclick: ~{ clicked( ${msg + "+"} ); }, msg }; document.body.appendChild( but ); } }, <BUTTON> { onclick: ~{ clicked( "click me also" ); }, "click me" } } }
(function (a) {return 1+a})(4) 5
(service (a) {return 1+a})(4) http://localhost:8080/hop/svc-23ab4c7?a=4
(${service (a) {return 1+a}})(4).post(function (v) {return v}) 5
fs = require( 'fs' ); service cmd( path ) { return fs.readdirSync( path ).map( function( p ) { return { name: p.replace( /.*\//g, "" ), size: fs.statSync( p ).size } } ); } service dir( { path: "/tmp" } ) { return <HTML> { <BUTTON> { onclick: ~{ ${cmd}( ${path} ) .post( function ( v ) { document.body.appendChild( <TABLE> { v.map( function( p ) { return <TR> { <TH> { p.name }, <TD> { p.size } }; } ) } </TABLE> ) } ) }, "du -sk" } </BUTTON>, } </HTML> }
service proxy() { return <HTML> { ~{function k(e ) { document.body.appendChild( <DIV> { el } ) }}, <BUTTON> { onclick: ~{${svc}("localhost").post(k)}, "direct call" }, <BUTTON> { onclick: ~{${proxied}("www.foo.org").post(k)}, "proxied call" } } } service proxied(host) { return svc(host) .post( function(v) { return v }, { host: host, sync: true } ); } service svc(name) { return name.toUpperCase(); }
service withurl() { var output = <DIV> {}; var input = <INPUT> {value: "toto n'est pas content"}; var select = <SELECT> { <OPTION> { value: "fr|en", "fr->en" }, <OPTION> { value: "en|fr", "en->fr" } }; var translate = service(text, langpair) { return translateText(text, langpair); }; return <HTML> { <HEAD> { css: withurl.resource("iframe.hss") }, select, input, <BUTTON> { onclick: ~{ ${translate}(${input}.value, ${select}.value) .post(function(v) { ${output}.innerHTML = v; }) }, "translate" } </BUTTON>, output };
var hop = require("hop"); var url_base = "http://mymemory.translated.net/api/get"; function translateText(text, langpair) { var url = url_base + "?q=" + escape(text) + "&langpair=" + (langpair ? langpair : "en|fr"); return hop.withURL( url, function(o) { if(o.responseStatus === 200) { var t = o.responseData.translatedText; return hop.charsetConvert( unescape(t), "UTF-8"); } } ) }
GET|HEAD|POST <path> HTTP/1.0\r\n
..., 2xx success, ..., 4xx error, ...
GET /html/rfc1945 HTTP/1.0 Host: tools.ietf.org User-Agent: Mozilla/5.0 Accept-Encoding: gzip, deflate Accept-Charset: utf-8...
HTTP/1.0 200 OK Server: Apache/2.2.12 (Debian) Content-Length: 174663 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <TITLE>RFC 1945 (rfc1945) - Hypertext Transfer Protocol...
(abstract-class %http-message (seconds::integer read-only (default (current-seconds))) (header::pair-nil (default '())) (content-length::integer read-only (default -1)) (charset (default #f))) (class http-request::%http-message (user::user read-only (default (class-nil user))) (localclientp::boolean (default #f)) (http::symbol (default 'HTTP/1.1)) (host::string (default "localhost")) (scheme::symbol (default 'http)) (port::integer (default 80)) (method::symbol read-only (default 'GET)) (abspath::string (default "")) (connection::symbol (default 'keep-alive))) (final-class http-server-request::http-request (authorization (default #f)) (service::obj (default #unspecified))) (class http-proxy-request::http-request (proxy-authorization (default #f)))
service text1() { return "<html><em>Foo</em></html>"; }
var hop = require('hop'); service text2() { return hop.HTTPResponseString( "<html><em>Foo</em></html>" ); }
var hop = require('hop'); service text3() { return hop.HTTPResponseString( "<html><em>Foo</em></html>", { contentType: "text/html" } ); }
service hop1() { return <HTML> { <EM> { "foo" } }; }
var hop = require('hop'); service hop2() { return hop.HTTPResponseHop( <HTML> { <EM> { "foo" } } ); }
var hop = require("hop"); var fs = require("fs"); service file1() { var fd = fs.openSync( module.filename, "r" ); var sz = fs.statSync( module.filename ).size var buf = new Buffer( sz ); fs.readSync( fd, buf, 0, sz, 0 ); return hop.HTTPResponseString( buf.toString( "ascii", 0, sz ) ); }
var hop = require("hop"); service file2() { return hop.HTTPResponseFile( module.filename ); }
var hop = require( "hop" ); var count = 2; service authenticationAccept() { switch( count-- ) { case 2: return hop.HTTPResponseAuthentication( "I don't know you" ); case 1: return hop.HTTPResponseAuthentication( "Do you really insist?" ); case 0: count = 2; return "Ok for this time"; } } service auth() { return <HTML> { <DIV> { "Click 3 times to get access." }, <BUTTON> { onclick: ~{ ${authenticationAccept}() .post( function( v ) { document.write( v ) }, { fail: function( v ) { ; } } ) }, "click me" } } }
var hop = require( "hop" ); var canvas = <CANVAS> { width: 550, height: 400, style: "border: 1px solid black" }; service event() { return <HTML> { canvas, ~{ var ctx = ${canvas}.getContext( "2d" ); ctx.lineWidth = 10; ${canvas}.addEventListener( "mousedown", function( evt ) { ctx.lineTo( evt.pageX, evt.pageY ); ctx.stroke(); } ); } } }
var hop = require( "hop" ); var canvas = <CANVAS> { width: 550, height: 400, style: "border: 1px solid black" }; service event2() { return <HTML> { canvas, ~{ var ctx = ${canvas}.getContext( "2d" ); ctx.lineWidth = 10; ${canvas}.addEventListener( "mousedown", function( evt ) { ctx.lineTo( evt.pageX, evt.pageY ); ctx.stroke(); ${service( evt ) { hop.broadcast( "draw", evt ); } }( { pageX: evt.pageX, pageY: evt.pageY } ).post(); } ); } } }
var canvas = <CANVAS> { width: 550, height: 400, style: "border: 1px solid black" }; service slave( {red: 200, green: 0, blue: 0} ) { return <HTML> { canvas, ~{ window.onload = function() { var canvas = ${canvas}; var ctx = canvas.getContext( "2d" ); ctx.lineWidth = 15; ctx.strokeStyle = "rgba(" + ${red} + "," + ${green} + "," + ${blue} + ",1)"; server.addEventListener( "draw", function( evt ) { ctx.lineTo( evt.value.pageX, evt.value.pageY ); ctx.stroke(); } ); } } } </HTML> }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>jQuery UI Datepicker - Default functionality</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css"> <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script> <link rel="stylesheet" href="/resources/demos/style.css"> <script> $(function() { $( "#datepicker" ).datepicker(); }); </script> </head> <body> <p>Date: <input type="text" id="datepicker"></p> </body> </html>
service jquery() { return <HTML> { <HEAD> { <TITLE> {"jQuery UI Datepicker - Default functionality"}, <LINK> {rel: "stylesheet", href: "http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css" }, <SCRIPT> {src: "http://code.jquery.com/jquery-1.10.2.js"}, <SCRIPT> {src: "http://code.jquery.com/ui/1.10.4/jquery-ui.js"}, <LINK> {rel: "stylesheet", href: "http://jqueryui.com/resources/demos/style.css" } }, <P> { "Date: ", <DATEPICKER> {} } } } function DATEPICKER( attrs ) { var id = attrs.id || "datepicker"; return [ ~{ $(function() { $("#" + ${id}).datepicker() }) }, <INPUT> { type: "text", id: id } ] }
Use a spacebar or arrow keys to navigate