In a type contract, an '->' denotes a function. For example, the function that describes length would take in a string and return a number, described as String -> Number. A function that takes in the length function and returns true would be described as (String -> Number) -> Boolean.
A function may have multiple arguments. For example, the max function takes in two numbers and returns one, described as Number * Number -> Number.
Some types may be parameterized by other types. For example, a function may expect an array of numbers and return boolean: Array Number -> Boolean. Sometimes this parameter type is generic, and there may be multiple. In such cases, a lowercase letter is used, starting at 'a', with each new type getting a new letter. A function to return the first element of an array would be represented by Array a -> a.
Sometimes, multiple types are valid for an argument. For example, length is applicable to both Strings and Arrays, described as: String U Array -> Number.
An argument may be optional. Slice will take an array, a starting index, and an ending index, returning the subarray defined by that interval. The ending index is optional: Array a * Number [* Number]
Often an argument may be either of a specific type, or an event or behaviour carrying a value of that type. Instead of writing Behaviour a U a, we write [Behaviour] a. Max may be defined for numbers and behaviours that are numbers, described as [Behaviour] Number * [Behaviour] Number -> [Behaviour] Number. Additionally, entire arguments may be optional. Max may be defined for two or three numbers, described as Number * Number [* Number] -> Number.
A function may take a homogeneous array as a parameter. MaxLen may be defined on an array composed of both arrays and strings (unioned), described as Array (String U Array) -> Number.
A function may expect an object with certain fields. DrawLine may expect two posn objects that have x and y fields that are numbers, described as {x: Number, y: Number} * {x: Number, y: Number} -> Void.
A function may take a variable number of arguments. The max function may take one or more numbers and returns the greatest, described as Number . Array Number -> Number.
If a library object is marked as global, and the library is set to use the global namespace, this object will be defined in the global namespace. In such cases, one can refer to the function directly without prefix, e.g.,
length('asdf'). Alternatively, the same function is included as
a field of the object returned from flapjax initialization,
so one could write
var flapjax = flapjaxInit(...);
flapjax.length('asdf');
In this case, one can write length('asdf'). The functions in the
returned object will be constructed in the same way as the public functions.
The raw form of the functions are available from the 'util' field of the returned
object, but this is only for expert users.
If a function is marked as being in the prototype of a particular object, it can be used with dot syntax for that object. For instance, because length is in the String prototype, you can write 'asdf'.length().
If a method is in an object's prototype, that object may be used as an argument for that method, specified by this annotation. For length, this would be argument 0, so instead of length('asdf') it would be 'asdf'.length().
length('asdf');
-
Base
- filter
- fold
- foldR
- Hashtable
- forEach
- isCommonPath
- isCyclePath
- map
- Maybe
- MaybeEmpty
- maybeEmpty
- MaybeFull
- mmt
- member
- slice
-
DOM
- $
- $$
- $A
- $B
- $E
- $L
- $O
- addEvent
- extractEvent_e
- extractEvents_e
- extractId_b
- extractValueOnEvent_b
- extractValueOnEvent_e
- extractValue_b
- extractValue_e
- getElementsByClass
- getLabeledObjs
- getObjs
- getObjsA
- getObj
- insertDomB
- insertDomE
- insertValueB
- insertValueE
- insertValuesB
- mouseLeft_b
- mouseTop_b
- mouse_b
- nodeWithOwnEvents
- swapDom
- tagRec
- topE
-
DOM tags
- A
- AB
- BR
- BRB
- BUTTON
- BUTTONB
- CANVAS
- CANVASB
- DIV
- DIVB
- FIELDSET
- FIELDSETB
- FORM
- FORMB
- H1
- H1B
- H2
- H2B
- H3
- H3B
- HR
- HRB
- IMG
- IMGB
- INPUT
- INPUTB
- LABEL
- LABELB
- LEGEND
- LEGENDB
- LI
- LIB
- OL
- OLB
- OPTGROUP
- OPTGROUPB
- OPTION
- OPTIONB
- P
- PB
- PRE
- PREB
- SELECT
- SELECTB
- SPAN
- SPANB
- STRONG
- STRONGB
- TABLE
- TABLEB
- TBODY
- TBODYB
- TD
- TDB
- TEXT
- TEXTAREA
- TEXTAREAB
- TEXTB
- TFOOT
- TFOOTB
- TH
- THB
- THEAD
- THEADB
- TR
- TRB
- TT
- TTB
- UL
- ULB
-
Reactive core
- changes
- Behavior
- Behaviour
- collect_e
- Event
- hold
- lift_b
- lift_e
- snapshot_e
- switch_b
- switch_e
- valueNow
-
Basic Event combinators
- and
- and_e
- apply_e
- asTimer_e
- blind
- blind_e
- calm
- calm_e
- choose
- choose_e
- collect
- cond_e
- constant
- constant_e
- delay
- delay_e
- if_e
- filter
- filterRepeats
- filterRepeats_e
- filter_e
- forwardLatest
- lift
- map_e
- merge
- merge_e
- not
- not_e
- once
- once_e
- or
- or_e
- receiver_e
- replaceValue
- replaceValue_e
- sendEvent
- skipFirst
- skipFirst_e
- snapshot
- startsWith
- takeSnapshot
- timer_e
- toBehavior
- toBehaviour
- transform
- transformWithMemory
- transform_e
-
Basic Behaviour combinators
- and
- and_b
- apply_b
- asTimer_b
- blind
- blind_b
- calm
- calm_b
- choose
- choose_b
- cond_b
- constant
- delay
- delay_b
- forwardLatest
- if_b
- lift
- not
- not_b
- or
- or_b
- receiver_b
- sendBehavior
- sendBehaviour
- timer_b
- toEvent
- transform
- transform_b
- valueChanges
-
Additional helpers
- disableTimer
-
Web services
- getWebServiceObject_e
-
Library extension for advanced use
- $___defs
- attachListener
- combinePulse
- combinePulseFull
- event_e
- key_e
- Node
- Path
- PathBranch
- PathEnd
- PathLink
- priorityQueue
- propagatePulse
- Pulse
- raise
- raise_e
- removeListener
- sync
- sync_e
- topological
- topological_e
- updateParentRanks
- waitTopologically
-
Server library
- $___sdefs
- pushUrl
- popUrl
- getUrl
- readCookie
- getSharingConsoleLink
- rpcSchemas
- postLogin
- getLogin
- jsonLogin
- postCheck
- getCheck
- jsonCheck
- postLogout
- getLogout
- jsonLogout
- postGetMyHome
- getGetMyHome
- jsonGetMyHome
- postInspect
- getInspect
- jsonInspect
- postRead
- getRead
- jsonRead
- postDeepRead
- getDeepRead
- jsonDeepRead
- postWrite
- getWrite
- jsonWrite
- postDeepWrite
- getDeepWrite
- jsonDeepWrite
- postCreate
- getCreate
- jsonCreate
- postRemove
- getRemove
- jsonRemove
- postSendAuthEmail
- getSendAuthEmail
- jsonSendAuthEmail
- postVerifyEmail
- getVerifyEmail
- jsonVerifyEmail
- postPickUsernameAndPassword
- getPickUsernameAndPassword
- jsonPickUsernameAndPassword
- postGetDomain
- getGetDomain
- jsonGetDomain
- postMigrate
- getMigrate
- jsonMigrate
- postGetPermissions
- getGetPermissions
- jsonGetPermissions
- readPersistentObject
- readPermissionsB
- writePersistentObject
- bindPersistentBehaviour
Internal library function used for labeling functions for construction of the library. Useful for creating new libraries.
An Annotation is an object literal:
{
[np: Boolean] - not public - do not add function to flapjax.pub, default false
[b: Boolean] - behaviour - add function to behaviour prototype, default false
[e: Boolean] - event - add function to event prototype, default false
[c: Boolean] - context - first parameter to function is context, default false
[a: Number] - argument - parameter position to replace with object when used in prototype, default: don't do it
}
$___defs.push([{}, 'identity', function (v} { return v;}])
Make a time varying HTML anchor tag. More generally, <tag>B will create a time varying dom tag of type <tag>.
One argument, potentially a time varying one, may be an object containing the properties (and nested properties) of the tag. If an argument is a string or a time varying string, it is automatically turned into a TextNode. Arguments that are DOM nodes or time varying DOM nodes are inserted as children of the tag and updating is automatically handled.
Note: while AB may take arguments of type Behaviour, A cannot. AB is an optimized lift_b(A, ...).
AB();
A({href: 'http://www.site.com'}, 'link text');
AB({href: 'http://www.site.com'}, 'link text');
AB({href: 'http://www.site.com'}, 'link text');
linkB = constant_b('http://www.site.com');
textB = constant_b('start text');
AB({href: linkB}, textB);
linkB = constant_b('http://www.site.com');
textB = constant_b('start text');
PB(AB({href: linkB}, textB));
new Behavior(timer_e(1), 0);
receiver_e() instanceof Event;
timer_b() instanceof Event;
new Event(
[receiver_e()],
function (sendNextPulse, pulse) {
if (pulse.value > 0) { sendNextPulse(pulse); }
});
- get: 'a -> 'b U Undefined
- set: 'a * 'b -> Void
- get variant put: 'a * 'b -> Void
- clear: Void -> Void
- remove: 'a -> Void
var h = new Hashtable();
var k = {}; var v = function () {};
h.set(k,v);
h.get(k);
x instanceof Maybe
Variant of Maybe without a value.
Commonly used when explicitly specifying contexts.
var x = new MaybeEmpty();
x instanceof Maybe;
x instanceof MaybeEmpty;
x instanceof MaybeFull;
var x = new MaybeFull('1');
x instanceof Maybe;
x instanceof MaybeFull;
if (!(x instanceof Maybe)) { throw 'x not maybe type'; }
return (x instanceof MaybeFull)? x.value : 'x is MaybeEmpty so no value';
priorityQueue.insert({k: -1, v: function () { alert('hit'); });
When a Pulse reaches a Node, the Pulse has a history of Nodes it has previously encoutered, represented by a Path.
Path is in the prototype of PathEnd, PathLink and PathBranch
A path with the most recent entry being a, and a history of previous elements recursively defined with Path
Typically, the first argument would be a Node in a dependency graph.
new PathLink(1, new PathEnd());
new PathLink(1, new PathLink(2, new PathEnd()));
When a value changes in the dependency graph, it propagates to nodes dependent upon it so they can recompute.
Information beyond the actual value may be useful:
- Pulse(stamp, path, accuracy, value)
- stamp: the time step the event occurred
- path: nodes encountered previous to this node in the same timestep causing the current value
- accuracy: number between 0 and 1 describing accuracy of value
- value: the actual value being propagated
(new Pulse(0, new PathEnd(), .5, 'hello')).value
var someStream_e = receiver();
var add1_e =
function (evt_e) {
return event_e(
[evt_e],
function (sendNextPulse, pulse_a) {
var pulse_b =
new Pulse(
pulse_a.stamp,
pulse_a.path,
pulse_a.accuracy,
pulse_a.value + 1);
sendNextPulse(pulse_b);
});
};
add1_e(someStream_e);
addEvent(document.getElementById('x'), 'mouseover', function (_) { alert('foo')});
var constituent1B = constant_b(true); var constituent2B = constant_b(true); var constituent3B = constant_b(true); var form1ValidB = and_b(constituent1B, constituent2B, constituent3B);
var a = receiver_e(); var b = receiver_e(); a.attachListener(b);
var a = receiver_e(); var b = receiver_e(); attachListener(a, b);
var window = 10; var keyStreamE = receiver_e(); keyStreamE.calm_e(window);
var windowB = hold(receiver_e(), 10); var keyStreamE = receiver_e(); keyStreamE.calm_e(windowB);
slice([1,2,3], 1, [1,2,3].length)
slice([1,2,3], 1)
getURLParam('name')
$URL('name')
Note: This function is in a separate library, called fjws.js. To use it, you need to include the following tag in the head of your document:
< script type="text/javascript" src="/fjws/fjws.js" >PATH is the path to the Flapjax source directory. You also need to include the following call at the beginning of your JavaScript loader function:
initFlapjaxWebServiceAPIs(flapjax, '#888888');The first argument is the Flapjax object, i.e. the result of the call to flapjaxInit(). The second argument is the background color of your page.
initFlapjaxWebServiceAPIs also takes an optional third parameter. If you are running your own server, and the fjws directory is in a different location, then the third parameter is the path to the directory which contains fjws.js and the two necessary SWF files.
Given an eventstream of "WebServiceInfoObj"s, returns an eventstream consisting of the responses to each request. The type of request and type of response depend on the parameters of the WebServiceInfoObj. The library will either use a server-side proxy or a Flash object as a client-side proxy, as appropriate. As a result, requests can be made across domains, since using Flash and/or a proxy server effectively bypasses XmlHttpRequest's security policies.
WebServiceInfoObj is an object which obeys the following type signature:
url: string
[request: ("get" | "post" | "rawPost" | undefined)]
[fields: (object | undefined)]
[body: (string | undefined)]
[serviceType: ( "xml" | "jsonLiteral" | "plaintext" )]
[returnType: ( "xml" | "object" | undefined)]
[asynchronous: (boolean | undefined)]
Url is the simple URL for the web service. It should not include a question mark or any fields.
Fields is optional. If specified, and if the request-type is 'get' or 'post', then the request will automatically include them in the URL (for 'get') or the request (for 'post'). If request-type is 'get', 'post', or unspecified, then the value associated with each key must be a string, and will be automatically escaped.
Request is optional. If fields is not specified or is equal to {}, then request defaults to 'get'. If fields are given and non-empty, then request defaults to 'post'. If request is specified as 'get' or 'post', then the associated request is generated and used. If request is 'rawPost', then fields will be ignored, and body is sent as the body of the POST. If request is anything else, then it is treated as if it were not specified.
Body is optional. If specified, and if the request-type is 'rawPost', then it is sent as the body of the POST. If the request-type is anything else, it will be ignored.
ServiceType is optional. If not specified, it defaults to "object". If serviceType is "plaintext", then the response will not be parsed, but will be returned in an object of the form {value: string}.
ReturnType is optional. If not specified, it defaults to "object", which is a JavaScript value. "xml" can be specified if serviceType is "xml", in which case an XML object will be returned. If serviceType is not "xml" and return type is "xml", then the call is an error.
Asynchronous is optional. If not specified, it defaults to true. If false, then a method fetching this request will not return until the request is complete.
var rssServiceInfoE = apply_e(function(v) {
return {
url: v,
serviceType: 'xml'
};
},extractValue_e("urlTextField");
var rssFeedE = getWebServiceObject_e(rssServiceInfoE);
var rssFeedB = rssFeedE.hold({title:'No page yet', items: {}});
var yahooServiceInfoE = apply_e(function (lcn,q) {
return {
url: 'http://api.local.yahoo.com/LocalSearchService/V1/localSearch',
fields: {
appid: 'flapjaxmashup',
location: lcn,
query: q},
serviceType: 'xml',
request: 'get'
};
},extractValue_e('location'),extractValue_e('query'));
var yahooLocalE = getWebServiceObject_e(yahooServiceInfoE.calm(500));
var yahooLocalB = yahooLocalE.hold({ResultSet:{Result:[{'Title':'No results yet.'}]}});
readCookie('username');
getElementsByClass('speeches')
getElementsByClass('speeches', document, 'p')
swapDom('x')
var z = swapDom(document.getElementById('x'), 'y')
member(2, [224,2,4]);
map(function (x, y) { return x + y}, [1,2,3], [3,5,3]);
map(function (x) { return typeof(x) == 'string'}, [1,'hello',2]);
UL.apply(this, map(LI, ['first string', 'second', 'last string']));
filter(function (v) { return v >= 0; }, [2,-3,0,2,-3]
fold(function (_, acc) { return 1 + acc;}, 0, [1,2,3])
fold(function (v, acc) { return v + acc;}, 0, [1,2,3])
fold(function (v1, v2, acc) { return v1 * v2 + acc;}, 0, [1,2,3], [3,4,5])
getObj('myform');
$('myform');
$($('myform'));
getObjs('x', 'y').y.value
getObjs(LI({id: 'y'}, 'some node..')).y.value
document.appendChild(DIV({id: 'aVeryLongAndSillyName'}, 'my node'));
document.appendChild(DIV({id: 'okName'}, 'another node'));
getLabeledObjs('okName', ['aVeryLongAndSillyName', 'short']).short.value
getObjsA['x', 'y', 'z'][1].value
isCommonPath( new PathLink(1, new PathLink(2, new PathEnd())), new PathLink(2, new PathEnd()));
isCommonPath(new PathEnd(), new PathEnd());
Returns true if a value occurs repeatadly on a path
Useful for detecting tight cycles propagating in the dependency graph
isCyclePath(new PathLink(1, new PathLink(1, new PathEnd())));
isCyclePath(new PathLink(1, new PathLink(2, new PathEnd())));
When a node has a new value, it generates a pulse that should be sent to nodes dependent upon it
Additionally, this method supports the opt-in topological evaluation strategy by checking the pulse queue when the recursive call finishes.
receiver_e().updateParentRanks();
updateParentRanks(receiver_e());
event_e([], function (_, __) {}) instanceof Event;
event_e([], function (_, __) {}) instanceof Behaviour;
var someEvent = receiver_e();
event_e(
[someEvent],
(function () {
var prevAccepted = 0;
return function (send, pulse) {
if (p.value > prevAccepted) {
prevAccepted = p.value;
send(pulse);
}
};
})());
receiver_e().raise_e([]);
raise_e(receiver_e(), []);
var a = receiver_e(); var b = receiver_e(); a.attachListener(b); a.removeListener(b);
var a = receiver_e(); var b = receiver_e(); attachListener(a, b); removeListener(a, b);
var inputStreamE = receiver_e();
var helloStreamE = inputStreamE.constant_e('hello');
var inputStreamE = receiver_e(); var helloStreamE = constant_e(inputStreamE, 'hello');
var inputStreamE = receiver_e();
var helloStreamE = inputStreamE.constant('hello');
var inputStreamE = receiver_e();
var helloStreamE = inputStreamE.replaceValue('hello');
var mouseoverTimeE =
receiver_e().transform_e(function(_){return (new Date()).getTime();});
var mouseoutTimeE =
receiver_e().transform_e(function(_){return (new Date()).getTime();});
var resultE =
sync_e(
[mouseoverTimeE, mouseoutTimeE]).transform_e(
function(arr){return arr[1] - arr[0];});
var someTimesE = receiver_e();
var fn = function () { someTimesE.sendEvent((new Date()).getTime()); };
setInterval(fn, 1000);
var doubledTimesE = someTimesE.transform_e(function (v) { return v * 2; });
var someTimesE = receiver_e();
var fn = function () { sendEvent(someTimesE, (new Date()).getTime()); };
setInterval(fn, 1000);
var doubledTimesE = someTimesE.transform_e(function (v) { return v * 2; });
var doublerE = receiver_e().transform_e(function(v){return v * 2; });
doublerE.sendEvent(2);
var doublerE = receiver_e().transform_e(function(v){return v * 2; });
sendEvent(doublerE, 2);
var sameE = receiver_e().not_e().not_e();
var positiveE = receiver_e().filter_e(function (v) { return v > 0; });
var mouseoverE = receiver_e();
var mouseoutE = receiver_e();
var colorChangeE =
merge_e(
mouseoverE.constant_e('#F00'),
mouseoutE.constant_e('#0F0'));
var someEventE = receiver_e(); someEventE.skipFirst_e().skipFirst_e();
var originalE = receiver_e();
var countE = originalE.collect_e(0, function (_, prevCount) { return prevCount + 1; });
var originalE = receiver_e();
var countE =
originalE.collect_e(
'off',
function (_, prevVal) { return prevVal == 'on' ? 'off' : 'on'; });
var originalE = receiver_e();
var countE =
originalE.collect_e(
0,
function (curVal, prevGreatest) {
return curVal > prevGreatest? curVal : prevGreatest ;
});
var originalE = receiver_e();
var countE =
originalE.collect_e(
[],
function (curName, prevNames) { return [curName].concat(prevNames); });
var originalE = receiver_e();
var countE =
originalE.collect_e(
[],
function (curName, prevNames) {
prevNames.push(curName);
return prevNames;
});
var domStreamE = receiver_e(); // every event is a DOM object
domStreamE.
switch_e().
extractEvent_e('mouseover').
transform_e(function(_) { alert('hit!'); });