зеркало из https://github.com/mozilla/reflex.git
Remove old examples.
This commit is contained in:
Родитель
ae9dc41b2f
Коммит
d2bfc075a1
|
@ -1,4 +0,0 @@
|
|||
# Examples
|
||||
|
||||
Index of examples that demonstrate role and use of individual building block
|
||||
provided by the reflex library.
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.5
|
||||
- 0.6
|
|
@ -1,5 +0,0 @@
|
|||
# Changes
|
||||
|
||||
## 0.0.1 / 2012-11-06
|
||||
|
||||
- Initial release
|
|
@ -1,18 +0,0 @@
|
|||
Copyright 2012 Irakli Gozalishvili. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
|
@ -1,12 +0,0 @@
|
|||
# drag-writer
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/Gozala/drag-writer.png)](http://travis-ci.org/Gozala/drag-writer)
|
||||
|
||||
Drag & drop example
|
||||
|
||||
## Try / Hack
|
||||
|
||||
npm install
|
||||
npm start
|
||||
|
||||
And open `./index.html` in your browser.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,53 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var writer = require("reflex/writer")
|
||||
var map = require("reducers/map")
|
||||
var open = require("dom-reduce/event")
|
||||
var merge = require("reducers/merge")
|
||||
var takeWhile = require("reducers/take-while")
|
||||
var expand = require("reducers/expand")
|
||||
var reactor = require("reflex/reactor")
|
||||
|
||||
function dragReader(view) {
|
||||
// Get a signal of mouse down events.
|
||||
var mousedown = open(view, "mousedown")
|
||||
|
||||
// And signals for mouse up and move events.
|
||||
var mouseup = open(view, "mouseup")
|
||||
var mousemove = open(view, "mousemove")
|
||||
|
||||
// Relocation signal can be expressed as events from mixed **move** & **up**
|
||||
// events until firs **up** occurs.
|
||||
var relocate = takeWhile(merge([ mousemove, mouseup ]), function(event) {
|
||||
return event.type !== "mouseup"
|
||||
})
|
||||
|
||||
|
||||
// Item drag signal can be expressed as expansion of mousedown events
|
||||
// to a followup relocation events.
|
||||
var drag = expand(mousedown, function(event) {
|
||||
// Calculate offset.
|
||||
var offsetX = event.offsetX || event.layerX
|
||||
var offsetY = event.offsetY || event.layerY
|
||||
|
||||
// Map relocation events to an axis with offset being applied.
|
||||
return map(relocate, function(event) {
|
||||
return { x: event.clientX - offsetX, y: event.clientY - offsetY }
|
||||
})
|
||||
})
|
||||
|
||||
return drag
|
||||
}
|
||||
|
||||
// Create a writer for a our box element which will
|
||||
// apply drag axis to it.
|
||||
var positionWriter = writer(function swap(view, state) {
|
||||
view.style.left = state.x + "px"
|
||||
view.style.top = state.y + "px"
|
||||
}, function open(options) {
|
||||
return document.getElementById("box")
|
||||
})
|
||||
|
||||
|
||||
var draggable = reactor(positionWriter, dragReader)
|
||||
draggable()
|
|
@ -1,12 +0,0 @@
|
|||
<html lang=en>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Drag & drop example</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:100px; width:100px; border:4px dotted black; padding:10px; float:left">
|
||||
<div id="box" style="position:absolute; height:100px; width:100px; background:red"></div>
|
||||
<p></div><h3 style="margin: 50px; float: left">← Try it out!</h3></p>
|
||||
</body>
|
||||
<script src="build/drag-writer.js"></script>
|
||||
</html>
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "drag-writer",
|
||||
"id": "drag-writer",
|
||||
"version": "0.0.1",
|
||||
"description": "Drag & drop example",
|
||||
"keywords": [
|
||||
"drag-writer"
|
||||
],
|
||||
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||
"homepage": "https://github.com/Gozala/drag-writer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gozala/drag-writer.git",
|
||||
"web": "https://github.com/Gozala/drag-writer"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Gozala/drag-writer/issues/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"test": "~0.x.0",
|
||||
"repl-utils": "~1.0.0",
|
||||
"phantomify": "~0.x.0",
|
||||
"browserify": "~1.x.0"
|
||||
},
|
||||
"main": "./drag-writer.js",
|
||||
"scripts": {
|
||||
"test": "npm run test-node && npm run test-browser",
|
||||
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/index.js",
|
||||
"test-node": "node ./test/index.js",
|
||||
"repl": "node node_modules/repl-utils",
|
||||
"start": "node ./node_modules/browserify/bin/cmd.js --exports require --watch --debug --entry ./drag-writer.js --outfile ./build/drag-writer.js",
|
||||
"postinstall": "npm dedup"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/Gozala/drag-writer/License.md"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"dom-reduce": "~1.0.0",
|
||||
"reflex": "git://github.com/Gozala/reflex#future",
|
||||
"reducers": "~2.0.0"
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
"use strict";
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.5
|
||||
- 0.6
|
|
@ -1,5 +0,0 @@
|
|||
# Changes
|
||||
|
||||
## 0.0.1 / 2012-11-04
|
||||
|
||||
- Initial release
|
|
@ -1,18 +0,0 @@
|
|||
Copyright 2012 Irakli Gozalishvili. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
|
@ -1,12 +0,0 @@
|
|||
# html-writer
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/Gozala/html-writer.png)](http://travis-ci.org/Gozala/html-writer)
|
||||
|
||||
Example of html element writer.
|
||||
|
||||
## Develope / Try
|
||||
|
||||
npm install
|
||||
npm start
|
||||
|
||||
And open `./index.html` in your browser.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,50 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var writer = require("reflex/writer")
|
||||
var map = require("reducers/map")
|
||||
var filter = require("reducers/filter")
|
||||
var delay = require("reducers/delay")
|
||||
var open = require("dom-reduce/event")
|
||||
|
||||
function html(tagName) {
|
||||
return writer(function swap(element, state) {
|
||||
element.textContent = state
|
||||
}, function open(state) {
|
||||
var element = document.createElement(tagName)
|
||||
document.documentElement.appendChild(element)
|
||||
return element
|
||||
}, function close(element) {
|
||||
if (element.parentElement)
|
||||
element.parentElement.removeChild(element)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Take all keyup events that propagate to the document element.
|
||||
var keyupEvents = open(document.documentElement, "keyup")
|
||||
// Filter only to an events on the elements who's type is "text"
|
||||
var inputChangeEvents = filter(keyupEvents, function(event) {
|
||||
return event.target.type === "text"
|
||||
})
|
||||
// Map input change events to current values of the input element.
|
||||
var inputs = map(inputChangeEvents, function(event) {
|
||||
return event.target.value
|
||||
})
|
||||
|
||||
// Create `h1` html writer & italic html writer.
|
||||
var h1 = html("h1")
|
||||
var h2 = html("h2")
|
||||
var h3 = html("h3")
|
||||
var h4 = html("h4")
|
||||
var h5 = html("h5")
|
||||
var italic = html("i")
|
||||
|
||||
// And write inputs into both of them
|
||||
h1(inputs)
|
||||
|
||||
var offest = 35
|
||||
h2(delay(inputs, offest * 1))
|
||||
h3(delay(inputs, offest * 2))
|
||||
h4(delay(inputs, offest * 3))
|
||||
h5(delay(inputs, offest * 4))
|
||||
italic(delay(inputs, offest * 5))
|
|
@ -1,10 +0,0 @@
|
|||
<html lang=en>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>html-writer</title>
|
||||
<script src="build/html-writer.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<input type="text"/>
|
||||
</body>
|
||||
</html>
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "html-writer",
|
||||
"id": "html-writer",
|
||||
"version": "0.0.1",
|
||||
"description": "Example of html element writer",
|
||||
"keywords": [
|
||||
"html-writer"
|
||||
],
|
||||
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||
"homepage": "https://github.com/Gozala/html-writer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gozala/html-writer.git",
|
||||
"web": "https://github.com/Gozala/html-writer"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Gozala/html-writer/issues/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"test": "~0.x.0",
|
||||
"repl-utils": "~1.0.0",
|
||||
"phantomify": "~0.x.0",
|
||||
"browserify": "~1.x.0"
|
||||
},
|
||||
"main": "./html-writer.js",
|
||||
"scripts": {
|
||||
"test": "npm run test-node && npm run test-browser",
|
||||
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/index.js",
|
||||
"test-node": "node ./test/index.js",
|
||||
"repl": "node node_modules/repl-utils",
|
||||
"start": "node ./node_modules/browserify/bin/cmd.js --exports require --watch --debug --entry ./html-writer.js --outfile ./build/html-writer.js",
|
||||
"postinstall": "npm dedup"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/Gozala/html-writer/License.md"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"dom-reduce": "~1.0.0",
|
||||
"reflex": "git://github.com/Gozala/reflex#future",
|
||||
"reducers": "~2.0.0"
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
"use strict";
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.5
|
||||
- 0.6
|
|
@ -1,5 +0,0 @@
|
|||
# Changes
|
||||
|
||||
## 0.0.1 / 2012-11-26
|
||||
|
||||
- Initial release
|
|
@ -1,18 +0,0 @@
|
|||
Copyright 2012 Irakli Gozalishvili. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
|
@ -1,12 +0,0 @@
|
|||
# list-model
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/Gozala/list-model.png)](http://travis-ci.org/Gozala/list-model)
|
||||
|
||||
list-model example
|
||||
|
||||
## Try / Hack
|
||||
|
||||
npm install
|
||||
npm start
|
||||
|
||||
And open `./index.html` in your browser.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,30 +0,0 @@
|
|||
<html lang=en>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>list-model</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1 class="title"> List demo! </h1>
|
||||
<ul id="list">
|
||||
<li class="items">
|
||||
<p>Key: <span class="name"></span></p>
|
||||
<label>
|
||||
Value:
|
||||
<input class="text" name="text"/>
|
||||
</label>
|
||||
<button id="update">update</button>
|
||||
<button id="delete">delete</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="controls">
|
||||
<label>
|
||||
Enter new item:\
|
||||
<input name="text" id="text" />
|
||||
</label>
|
||||
<button id="button">Add item</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="build/list-model.js"></script>
|
||||
</html>
|
|
@ -1,101 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var model = require("../../model")
|
||||
var fold = require("reducers/fold")
|
||||
|
||||
var event = require("event")
|
||||
var send = require("event/send")
|
||||
|
||||
var delay = require("reducers/delay")
|
||||
var hub = require("reducers/hub")
|
||||
|
||||
// Now `property` and `attribute` return things previously known as
|
||||
// writers! In fact they may use writer abstraction if they desire
|
||||
// or not it really up to them.
|
||||
|
||||
function property(name) {
|
||||
return function(options) {
|
||||
var query = [""].concat(options.context).join(" .")
|
||||
var view = options.target.querySelector(query)
|
||||
fold(options.input, function(value) {
|
||||
view[name] = value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function attribute(name) {
|
||||
return function writeAttribute(options) {
|
||||
var query = [""].concat(options.context).join(" .")
|
||||
var view = options.target.querySelector(query)
|
||||
fold(options.input, function(value) {
|
||||
if (value == void(0)) view.setAttribute(name, value)
|
||||
else view.removeAttribute(name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var list = model({
|
||||
title: property("textContent"),
|
||||
// TODO: Clean up collections as this API is obviously a mess,
|
||||
// although idea is good I think. collection will invoke function
|
||||
// with input, target, context and will expect normal writer back.
|
||||
// Sugar can be added later.
|
||||
items: [function(options) {
|
||||
var query = [""].concat(options.context).join(" .")
|
||||
var template = options.target.querySelector(query)
|
||||
var root = template.parentElement
|
||||
root.innerHTML = ""
|
||||
var reactor = model({
|
||||
name: property("textContent"),
|
||||
text: property("value"),
|
||||
hidden: attribute("hidden")
|
||||
})
|
||||
return function(options) {
|
||||
var view = template.cloneNode(true)
|
||||
view.id = options.context.slice(-1).join("")
|
||||
var output = reactor({ input: options.input, target: view })
|
||||
root.appendChild(view)
|
||||
return output
|
||||
}
|
||||
}]
|
||||
/*
|
||||
items: [{
|
||||
name: property("textContent"),
|
||||
text: property("value"),
|
||||
hidden: attribute("hidden")
|
||||
}]
|
||||
*/
|
||||
})
|
||||
|
||||
|
||||
var input = event()
|
||||
var output = list({
|
||||
input: hub(delay(input, 800)),
|
||||
target: document.body
|
||||
})
|
||||
|
||||
fold(output, console.log.bind(console))
|
||||
|
||||
send(input, {
|
||||
title: "Hello there!",
|
||||
items: {
|
||||
"1": {
|
||||
name: "Jake",
|
||||
text: "Hello Jake"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
send(input, {
|
||||
title: "Bye there",
|
||||
items: {
|
||||
"1": {
|
||||
name: "Raynos",
|
||||
text: "What's up Jake"
|
||||
},
|
||||
"2": {
|
||||
name: "Irakli",
|
||||
text: "Hello Irakli"
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "list-model",
|
||||
"id": "list-model",
|
||||
"version": "0.0.1",
|
||||
"description": "list-model example",
|
||||
"keywords": [
|
||||
"list-model"
|
||||
],
|
||||
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||
"homepage": "https://github.com/Gozala/list-model",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gozala/list-model.git",
|
||||
"web": "https://github.com/Gozala/list-model"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Gozala/list-model/issues/"
|
||||
},
|
||||
"dependencies": {
|
||||
"reflex": "git://github.com/Gozala/reflex#future",
|
||||
"event": "~1.0.0",
|
||||
"reducers": "~2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"test": "~0.x.0",
|
||||
"repl-utils": "~1.0.0",
|
||||
"phantomify": "~0.x.0",
|
||||
"browserify": "~1.x.0"
|
||||
},
|
||||
"main": "./list-model.js",
|
||||
"scripts": {
|
||||
"test": "npm run test-node && npm run test-browser",
|
||||
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/index.js",
|
||||
"test-node": "node ./test/index.js",
|
||||
"repl": "node node_modules/repl-utils",
|
||||
"start": "node ./node_modules/browserify/bin/cmd.js --exports require --watch --debug --entry ./list-model.js --outfile ./build/list-model.js",
|
||||
"postinstall": "npm dedup"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/Gozala/list-model/License.md"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
"use strict";
|
||||
|
|
@ -1,819 +0,0 @@
|
|||
;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
var reflex = require("../../reflex");
|
||||
|
||||
// Arguments reperesent cells (like in spreadsheet) that user may change. We can
|
||||
// define derived cells that react to changes on cells they derived from and change
|
||||
// as well.
|
||||
var main = reflex(function(loan, down, price, interest, tax, hazard, other) {
|
||||
var due = reflex.lift(function(loan) {
|
||||
return loan * 12;
|
||||
}, loan);
|
||||
|
||||
var downAmount = reflex.lift(function(price, down) {
|
||||
return price * down / 100;
|
||||
}, price, down);
|
||||
|
||||
var loanAmount = reflex.lift(function(price, downAmount) {
|
||||
return price - downAmount;
|
||||
}, price, downAmount);
|
||||
|
||||
var monthlyMortgage = reflex.lift(function(loan, interest, due) {
|
||||
return Math.round(loan * interest / (1 - (Math.pow(1 / (1 + interest), due))));
|
||||
}, loanAmount, interest, due);
|
||||
|
||||
var estateTax = reflex.lift(function(tax) {
|
||||
return Math.round(tax / 12);
|
||||
}, tax);
|
||||
|
||||
var sum = function() {
|
||||
var total = 0;
|
||||
var index = 0;
|
||||
while (index < arguments.length) {
|
||||
total = total + arguments[index];
|
||||
index = index + 1;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
var totalMonthly = reflex.lift(sum, hazard, other, estateTax, monthlyMortgage);
|
||||
|
||||
// Finally we return record of named cells. Changes on either one of them going to be reflected
|
||||
// on the rendering target. Name of the cell is assumed to be mapped to an id of the element it
|
||||
// is bound to.
|
||||
this.loan = loan;
|
||||
this.down = down;
|
||||
this.price = price;
|
||||
this.interest = interest;
|
||||
this.tax = tax;
|
||||
this.hazardInsurance = hazard;
|
||||
this.otherFinancing = other;
|
||||
this.due = due;
|
||||
this.downAmount = downAmount;
|
||||
this.loanAmount = loanAmount;
|
||||
this.monthlyMortgage = monthlyMortgage;
|
||||
this.estateTax = estateTax;
|
||||
this.totalMonthly = totalMonthly;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
main.render(document.documentElement);
|
||||
}
|
||||
|
||||
|
||||
|
||||
},{"../../reflex":2}],2:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
var signal = require("./signal");
|
||||
var Input = signal.Input,
|
||||
start = signal.start,
|
||||
receive = signal.receive,
|
||||
merge = signal.merge,
|
||||
lift = signal.lift,
|
||||
source = signal.source,
|
||||
merges = signal.merges;
|
||||
|
||||
// Signal that given `target` element and hash of `outputs` signals
|
||||
// will dispatch to an output from hash that is mapped to
|
||||
// `event.type + "/" + event.target.id`. If such output is found
|
||||
// received value will be send to it.
|
||||
// Note: Right now it only deals with `change` events but likely in
|
||||
// future it's going be to extended to add support for more event
|
||||
// types.
|
||||
var EventBus = function(outputs, target) {
|
||||
this.outputs = outputs;
|
||||
this.target = target;
|
||||
Input.call(this);
|
||||
};
|
||||
EventBus.start = function(bus) {
|
||||
bus.target.addEventListener("change", function(event) {
|
||||
receive(bus, event);
|
||||
});
|
||||
Object.keys(bus.outputs).forEach(function(address) {
|
||||
var output = bus.outputs[address];
|
||||
var source = bus.target.ownerDocument.getElementById(output.id);
|
||||
output.value = source && source.value;
|
||||
});
|
||||
};
|
||||
EventBus.receive = function(bus, event) {
|
||||
var target = event.target;
|
||||
var type = event.type;
|
||||
var address = type + "/" + target.id;
|
||||
var output = bus.outputs[address];
|
||||
if (output instanceof Cell) {
|
||||
receive(output, event);
|
||||
}
|
||||
};
|
||||
EventBus.prototype = new Input();
|
||||
EventBus.prototype.constructor = EventBus;
|
||||
EventBus.prototype[start] = EventBus.start;
|
||||
EventBus.prototype[receive] = EventBus.receive;
|
||||
|
||||
// Signal that represents input given to `Reflex` initializer.
|
||||
// It basically represents last state of the input declared in
|
||||
// the reflex.
|
||||
var Cell = function() {
|
||||
Input.call(this);
|
||||
};
|
||||
Cell.start = function() {};
|
||||
Cell.receive = function(cell, event) {
|
||||
Input.receive(cell, event.target.value);
|
||||
};
|
||||
Cell.prototype = new Input();
|
||||
Cell.prototype.constructor = Cell;
|
||||
Cell.prototype[start] = Cell.start;
|
||||
Cell.prototype[receive] = Cell.receive;
|
||||
Cell.prototype.type = "change";
|
||||
|
||||
// Signal constructor takes `id` and `source` signal and returns
|
||||
// signal that will receive value of the source in form of hash
|
||||
// where `value` is mapped to `id`. Reflex joins all outputs using
|
||||
// this, to produce changes that are structured same as hash returned
|
||||
// by an initializer.
|
||||
var
|
||||
Writer = function(id, source) {
|
||||
this.id = id;
|
||||
Input.call(this, source);
|
||||
};
|
||||
Writer.prototype = new Input();
|
||||
Writer.prototype.constructor = Writer;
|
||||
Writer.receive = function(writer, value) {
|
||||
var record = {};
|
||||
record[writer.id] = value;
|
||||
Input.receive(writer, record);
|
||||
};
|
||||
Writer.prototype[receive] = Writer.receive;
|
||||
|
||||
// Signal constructor takes `target` element where changes will be
|
||||
// rendered and an `input` signal containing those changes. Keys in
|
||||
// the change are assumed to be child element id's of the target.
|
||||
// If element for the change is found new state is going to be rendered
|
||||
// in it.
|
||||
function Renderer(source, target) {
|
||||
this.target = target;
|
||||
Input.call(this, source);
|
||||
}
|
||||
Renderer.prototype = new Input();
|
||||
Renderer.prototype.constructor = Renderer;
|
||||
Renderer.receive = function(renderer, delta) {
|
||||
Object.keys(delta).forEach(function(id) {
|
||||
var target = renderer.target.ownerDocument.getElementById(id);
|
||||
if (target) {
|
||||
if (target.tagName.toLowerCase() === "input") {
|
||||
target.value = delta[id];
|
||||
}
|
||||
else {
|
||||
target.textContent = delta[id];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Renderer.prototype[receive] = Renderer.receive;
|
||||
|
||||
|
||||
// Reflex constructs a signal out of initializer which is expected
|
||||
// to return all the ports who's changes should be reflected in the
|
||||
// document. Signal on it's own is not very useful as signal although
|
||||
// Reflex instance has a `render` method, which can be invoked with
|
||||
// a `target` element. That initiates a render loop with in that
|
||||
// element. Changes on input cells will be reflected on output cells
|
||||
// by renderig updates with in them.
|
||||
var Reflex = function(initializer) {
|
||||
if (!(this instanceof Reflex))
|
||||
return new Reflex(initializer);
|
||||
|
||||
var cells = [];
|
||||
while (cells.length < initializer.length) {
|
||||
cells.push(new Cell());
|
||||
}
|
||||
|
||||
|
||||
var ports = Object.create(initializer.prototype);
|
||||
ports = initializer.apply(ports, cells) || ports;
|
||||
var names = Object.keys(ports);
|
||||
var inputs = names.reduce(function(inputs, id) {
|
||||
var port = ports[id];
|
||||
if (port instanceof Cell) {
|
||||
id = port.id || id;
|
||||
inputs[port.type + "/" + id] = port;
|
||||
port.id = id;
|
||||
}
|
||||
return inputs;
|
||||
}, Object.create(null));
|
||||
var outputs = names.map(function(id) { return new Writer(id, ports[id]); });
|
||||
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
|
||||
Input.call(this, merges(outputs));
|
||||
};
|
||||
Reflex.prototype = new Input();
|
||||
Reflex.render = function(reflex, target) {
|
||||
var eventBus = new EventBus(reflex.inputs, target);
|
||||
var renderer = new Renderer(reflex, target);
|
||||
start(eventBus);
|
||||
start(renderer);
|
||||
};
|
||||
Reflex.prototype.constructor = Reflex;
|
||||
Reflex.prototype.render = function(target) {
|
||||
Reflex.render(this, target);
|
||||
};
|
||||
Reflex.lift = signal.lift;
|
||||
Reflex.map = signal.map;
|
||||
Reflex.constant = signal.constant;
|
||||
Reflex.merge = signal.merge;
|
||||
Reflex.merges = signal.merges;
|
||||
Reflex.combine = signal.combine;
|
||||
Reflex.count = signal.count;
|
||||
Reflex.countIf = signal.countIf;
|
||||
Reflex.keepIf = signal.keepIf;
|
||||
Reflex.dropIf = signal.dropIf;
|
||||
Reflex.keepWhen = signal.keepWhen;
|
||||
Reflex.dropWhen = signal.dropWhen;
|
||||
Reflex.dropRepeats = signal.dropRepeats;
|
||||
Reflex.sampleOn = signal.sampleOn;
|
||||
|
||||
|
||||
module.exports = Reflex;
|
||||
|
||||
},{"./signal":3}],3:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
|
||||
// The library for general signal manipulation. Includes `lift` function
|
||||
// (that supports up to 8 inputs), combinations, filters, and past-dependence.
|
||||
//
|
||||
// Signals are time-varying values. Lifted functions are reevaluated whenver
|
||||
// any of their input signals has an event. Signal events may be of the same
|
||||
// value as the previous value of the signal. Such signals are useful for
|
||||
// timing and past-dependence.
|
||||
//
|
||||
// Some useful functions for working with time (e.g. setting FPS) and combining
|
||||
// signals and time (e.g. delaying updates, getting timestamps) can be found in
|
||||
// the Time library.
|
||||
//
|
||||
// Module implements elm API: http://docs.elm-lang.org/library/Signal.elm
|
||||
|
||||
|
||||
var $source = "source@signal"
|
||||
var $sources = "sources@signal"
|
||||
var $outputs = "outputs@signal"
|
||||
var $connect = "connect@signal"
|
||||
var $disconnect = "disconnect@signal"
|
||||
var $receive = "receive@signal"
|
||||
var $error = "error@signal"
|
||||
var $end = "end@signal"
|
||||
var $start = "start@signal"
|
||||
var $stop = "stop@signal"
|
||||
var $state = "state@signal"
|
||||
var $pending = "pending@signal"
|
||||
|
||||
function outputs(input) { return input[$outputs] }
|
||||
outputs.toString = function() { return $outputs }
|
||||
exports.outputs = outputs
|
||||
|
||||
function start(input) { input[$start](input) }
|
||||
start.toString = function() { return $start }
|
||||
exports.start = start
|
||||
|
||||
function stop(input) { input[$stop](input) }
|
||||
stop.toString = function() { return $stop }
|
||||
exports.stop = stop
|
||||
|
||||
function connect(source, target) { source[$connect](source, target) }
|
||||
connect.toString = function() { return $connect }
|
||||
exports.connect = connect
|
||||
|
||||
function disconnect(source, target) { source[$disconnect](source, target) }
|
||||
disconnect.toString = function() { return $disconnect }
|
||||
exports.disconnect = disconnect
|
||||
|
||||
function receive(input, message) { input[$receive](input, message) }
|
||||
receive.toString = function() { return $receive }
|
||||
exports.receive = receive
|
||||
|
||||
function error(input, message) { input[$error](input, message) }
|
||||
error.toString = function() { return $error }
|
||||
exports.error = error
|
||||
|
||||
function end(input) { input[$end](input) }
|
||||
end.toString = function() { return $end }
|
||||
exports.end = end
|
||||
|
||||
function stringify(input) {
|
||||
return input.name + "[" + (input[$outputs] || []).map(function(x) { return x.name }) + "]"
|
||||
}
|
||||
|
||||
var stringifier = Object.prototype.toString
|
||||
function isError(message) {
|
||||
return stringifier.call(message) === "[object Error]"
|
||||
}
|
||||
|
||||
function Return(value) {
|
||||
if (!(this instanceof Return))
|
||||
return new Return(value)
|
||||
|
||||
this.value = value
|
||||
}
|
||||
exports.Return = Return
|
||||
|
||||
function send(input, message) {
|
||||
if (message instanceof Return) {
|
||||
input[$receive](input, message.value)
|
||||
input[$end](input)
|
||||
}
|
||||
else if (isError(message)) {
|
||||
input[$error](input, message)
|
||||
}
|
||||
else {
|
||||
input[$receive](input, message)
|
||||
}
|
||||
}
|
||||
exports.send = send
|
||||
|
||||
function Break() {}
|
||||
exports.Break = Break
|
||||
|
||||
|
||||
function Input(source) {
|
||||
this[$source] = source;
|
||||
this[$outputs] = [];
|
||||
}
|
||||
exports.Input = Input
|
||||
|
||||
|
||||
// `Input.start` is invoked with an `input` whenever system is
|
||||
// ready to start receiving values. After this point `input` can
|
||||
// start sending messages. Generic behavior is to `connect` to
|
||||
// the `input[$source]` to start receiving messages.
|
||||
Input.start = function(input) {
|
||||
var source = input[$source]
|
||||
source[$connect](source, input)
|
||||
}
|
||||
|
||||
// `Input.stop` is invoked with an `input` whenever it needs to
|
||||
// stop. After this point `input` should stop sending messages.
|
||||
// Generic `Input` behavior is to `disconnect` from the
|
||||
// `input[$source]` so no more `messages` will be received.
|
||||
Input.stop = function(input) {
|
||||
var source = input[$source]
|
||||
source[$disconnect](source, input)
|
||||
}
|
||||
|
||||
// `Input.connect` is invoked with `input` and `output`. This
|
||||
// implementation put's `output` to it's `$output` ports to
|
||||
// delegate received `messages` to it.
|
||||
Input.connect = function(input, output) {
|
||||
var outputs = input[$outputs]
|
||||
if (outputs.indexOf(output) < 0) {
|
||||
outputs.push(output)
|
||||
if (outputs.length === 1)
|
||||
input[$start](input)
|
||||
}
|
||||
}
|
||||
|
||||
// `Input.disconnect` is invoked with `input` and an `output`
|
||||
// connected to it. After this point `output` should not longer
|
||||
// receive messages from the `input`. If it's a last `output`
|
||||
// `input` will be stopped.
|
||||
Input.disconnect = function(input, output) {
|
||||
var outputs = input[$outputs]
|
||||
var index = outputs.indexOf(output)
|
||||
if (index >= 0) {
|
||||
outputs.splice(index, 1)
|
||||
if (outputs.length === 0)
|
||||
input[$stop](input)
|
||||
}
|
||||
}
|
||||
|
||||
// `Input.Port` creates a message receiver port. `Input` instances support
|
||||
// `message`, `error`, `end` ports.
|
||||
Input.Port = function(port) {
|
||||
var isError = port === $error
|
||||
var isEnd = port === $end
|
||||
var isMessage = port === $receive
|
||||
|
||||
// Function will write `message` to a given `input`. This means
|
||||
// it will delegeate messages to it's `input[$outputs]` ports.
|
||||
return function write(input, message) {
|
||||
var outputs = input[$outputs]
|
||||
var result = void(0)
|
||||
var count = outputs.length
|
||||
var index = 0
|
||||
|
||||
// Note: dispatch loop decreases count or increases index as needed.
|
||||
// This makes sure that new connections will not receive messages
|
||||
// until next dispatch loop & intentionally so.
|
||||
while (index < outputs.length) {
|
||||
// Attempt to send a value to a connected `output`. If this is
|
||||
// `$end` `port` return `Break` to cause `output` to be
|
||||
// disconnected. If any other `port` just deliver a `message`.
|
||||
var output = outputs[index]
|
||||
try {
|
||||
result = isEnd ? output[port](output, input) :
|
||||
output[port](output, message, input)
|
||||
}
|
||||
catch (reason) {
|
||||
throw reason
|
||||
// If exception was thrown and `message` was send to `$error`
|
||||
// `port` give up and log error.
|
||||
if (isError) {
|
||||
console.error("Failed to receive an error message",
|
||||
message,
|
||||
reason)
|
||||
}
|
||||
// If exception was thrown when writing to a different `port`
|
||||
// attempt to write to an `$error` `port` of the `output`.
|
||||
else {
|
||||
try {
|
||||
result = output[$error](output, reason, input)
|
||||
}
|
||||
// If exception is still thrown when writing to an `$error`
|
||||
// `port` give up and log `error`.
|
||||
catch (error) {
|
||||
console.error("Failed to receive message & an error",
|
||||
message,
|
||||
reason,
|
||||
error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If result of sending `message` to an `output` was instance
|
||||
// of `Break`, disconnect that `output` so it no longer get's
|
||||
// messages. Note `index` is decremented as disconnect will
|
||||
// remove it from `outputs`.
|
||||
if (result instanceof Break || isEnd) {
|
||||
input[$disconnect](input, output)
|
||||
}
|
||||
// On any other `result` just move to a next output.
|
||||
else {
|
||||
index = index + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Once message was written to all outputs update `value` of
|
||||
// the input.
|
||||
if (isMessage)
|
||||
input.value = message
|
||||
|
||||
if (count === 0 && isEnd)
|
||||
input[$stop](input)
|
||||
}
|
||||
}
|
||||
|
||||
// Inputs have `message`, `error` and `end` ports
|
||||
Input.receive = Input.Port($receive)
|
||||
Input.error = Input.Port($error)
|
||||
Input.end = Input.Port($end)
|
||||
|
||||
// Same API functions are saved in the prototype in order to enable
|
||||
// polymorphic dispatch.
|
||||
Input.prototype[$start] = Input.start
|
||||
Input.prototype[$stop] = Input.stop
|
||||
Input.prototype[$connect] = Input.connect
|
||||
Input.prototype[$disconnect] = Input.disconnect
|
||||
Input.prototype[$receive] = Input.receive
|
||||
Input.prototype[$error] = Input.error
|
||||
Input.prototype[$end] = Input.end
|
||||
Input.prototype.toJSON = function() {
|
||||
return { value: this.value }
|
||||
}
|
||||
|
||||
function Constant(value) {
|
||||
this.value = value
|
||||
}
|
||||
Constant.ignore = function() {}
|
||||
|
||||
Constant.prototype = new Input()
|
||||
Constant.prototype.constructor = Constant
|
||||
Constant.prototype[$start] = Constant.ignore
|
||||
Constant.prototype[$stop] = Constant.ignore
|
||||
Constant.prototype[$connect] = Constant.ignore
|
||||
Constant.prototype[$disconnect] = Constant.ignore
|
||||
Constant.prototype[$receive] = Constant.ignore
|
||||
Constant.prototype[$error] = Constant.ignore
|
||||
Constant.prototype[$end] = Constant.ignore
|
||||
|
||||
|
||||
// Create a constant signal that never changes.
|
||||
|
||||
// a -> Signal a
|
||||
|
||||
function constant(value) {
|
||||
return new Constant(value)
|
||||
}
|
||||
exports.constant = constant
|
||||
|
||||
|
||||
function Merge(inputs) {
|
||||
this[$outputs] = []
|
||||
this[$sources] = inputs
|
||||
this[$pending] = inputs.length
|
||||
this.value = inputs[0].value
|
||||
}
|
||||
Merge.start = function(input) {
|
||||
var sources = input[$sources]
|
||||
var count = sources.length
|
||||
var id = 0
|
||||
|
||||
while (id < count) {
|
||||
var source = sources[id]
|
||||
source[$connect](source, input)
|
||||
id = id + 1
|
||||
}
|
||||
}
|
||||
Merge.stop = function(input) {
|
||||
var inputs = input[$sources]
|
||||
var count = inputs.length
|
||||
var id = 0
|
||||
while (id < count) {
|
||||
var source = inputs[id]
|
||||
source[$disconnect](source, input)
|
||||
id = id + 1
|
||||
}
|
||||
}
|
||||
Merge.end = function(input, source) {
|
||||
var sources = input[$sources]
|
||||
var id = sources.indexOf(source)
|
||||
if (id >= 0) {
|
||||
var pending = input[$pending] - 1
|
||||
input[$pending] = pending
|
||||
source[$disconnect](source, input)
|
||||
|
||||
if (pending === 0)
|
||||
Input.end(input)
|
||||
}
|
||||
}
|
||||
|
||||
Merge.prototype = new Input()
|
||||
Merge.prototype.constructor = Merge
|
||||
Merge.prototype[$start] = Merge.start
|
||||
Merge.prototype[$stop] = Merge.stop
|
||||
Merge.prototype[$end] = Merge.end
|
||||
|
||||
// Merge two signals into one, biased towards the
|
||||
// first signal if both signals update at the same time.
|
||||
|
||||
// Signal x -> Signal y -> ... -> Signal z
|
||||
function merge() {
|
||||
return new Merge(slicer.call(arguments, 0))
|
||||
}
|
||||
exports.merge = merge
|
||||
|
||||
|
||||
// Merge many signals into one, biased towards the
|
||||
// left-most signal if multiple signals update simultaneously.
|
||||
function merges(inputs) {
|
||||
return new Merge(inputs)
|
||||
}
|
||||
exports.merges = merges
|
||||
|
||||
|
||||
// # Past-Dependence
|
||||
|
||||
// Create a past-dependent signal. Each value given on the input signal
|
||||
// will be accumulated, producing a new output value.
|
||||
|
||||
function FoldP(step, value, input) {
|
||||
this[$outputs] = []
|
||||
this[$source] = input
|
||||
this.value = value
|
||||
this.step = step
|
||||
}
|
||||
FoldP.receive = function(input, message, source) {
|
||||
Input.receive(input, input.step(input.value, message))
|
||||
}
|
||||
|
||||
FoldP.prototype = new Input()
|
||||
FoldP.prototype.constructor = FoldP
|
||||
FoldP.prototype[$receive] = FoldP.receive
|
||||
|
||||
|
||||
function foldp(step, x, xs) {
|
||||
return new FoldP(step, x, xs)
|
||||
}
|
||||
exports.foldp = foldp
|
||||
|
||||
|
||||
// Optimized version that tracks single input.
|
||||
function Lift(step, input) {
|
||||
this.step = step
|
||||
this[$source] = input
|
||||
this[$outputs] = []
|
||||
this.value = step(input.value)
|
||||
}
|
||||
Lift.receive = function(input, message) {
|
||||
Input.receive(input, input.step(message))
|
||||
}
|
||||
|
||||
Lift.prototype = new Input()
|
||||
Lift.prototype.constructor = Lift
|
||||
Lift.prototype[$receive] = Lift.receive
|
||||
|
||||
function LiftN(step, inputs) {
|
||||
var count = inputs.length
|
||||
var id = 0
|
||||
var params = Array(count)
|
||||
while (id < count) {
|
||||
var input = inputs[id]
|
||||
params[id] = input.value
|
||||
id = id + 1
|
||||
}
|
||||
var value = step.apply(step, params)
|
||||
|
||||
this.step = step
|
||||
this[$outputs] = []
|
||||
this[$sources] = inputs
|
||||
this[$pending] = inputs.length
|
||||
this[$state] = params
|
||||
this.value = value
|
||||
}
|
||||
LiftN.start = Merge.start
|
||||
LiftN.stop = Merge.stop
|
||||
LiftN.end = Merge.end
|
||||
|
||||
|
||||
LiftN.receive = function(input, message, source) {
|
||||
var params = input[$state]
|
||||
var index = input[$sources].indexOf(source)
|
||||
var step = input.step
|
||||
params[index] = message
|
||||
return Input.receive(input, step.apply(step, params))
|
||||
}
|
||||
|
||||
LiftN.prototype = new Input()
|
||||
LiftN.prototype.constructor = LiftN
|
||||
LiftN.prototype[$start] = LiftN.start
|
||||
LiftN.prototype[$stop] = LiftN.stop
|
||||
LiftN.prototype[$end] = LiftN.end
|
||||
LiftN.prototype[$receive] = LiftN.receive
|
||||
|
||||
var slicer = [].slice
|
||||
|
||||
// Transform given signal(s) with a given `step` function.
|
||||
|
||||
// (x -> y -> ...) -> Signal x -> Signal y -> ... -> Signal z
|
||||
//
|
||||
// xs :--x-----x-----x---
|
||||
// lift(f, xs) :--f(x)--f(x)--f(x)
|
||||
//
|
||||
// xs :--x--------------------------x-------
|
||||
// ys :-----------y---------y---------------
|
||||
// lift(f, xs, ys) :--f(x, y)--f(x, y)--f(x, y)--f(x, y)-
|
||||
function lift(step, xs, ys) {
|
||||
return ys ? new LiftN(step, slicer.call(arguments, 1)) :
|
||||
new Lift(step, xs)
|
||||
}
|
||||
exports.lift = lift
|
||||
exports.lift2 = lift
|
||||
exports.lift3 = lift
|
||||
exports.lift4 = lift
|
||||
exports.lift5 = lift
|
||||
exports.lift6 = lift
|
||||
exports.lift7 = lift
|
||||
exports.lift8 = lift
|
||||
exports.liftN = lift
|
||||
|
||||
|
||||
// Combine a array of signals into a signal of arrays.
|
||||
function combine(inputs) {
|
||||
return new LiftN(Array, inputs)
|
||||
}
|
||||
exports.combine = combine
|
||||
|
||||
|
||||
|
||||
// Count the number of events that have occured.
|
||||
|
||||
// Signal x -> Signal Int
|
||||
//
|
||||
// xs : --x--x----x--x------x
|
||||
// count(xs): --1--2----3--4------5
|
||||
function count(xs) {
|
||||
return foldp(function(x, y) {
|
||||
return x + 1
|
||||
}, 0, xs)
|
||||
}
|
||||
exports.count = count
|
||||
|
||||
// Count the number of events that have occured that
|
||||
// satisfy a given predicate.
|
||||
|
||||
// (x -> Bool) -> Signal x -> Signal Int
|
||||
function countIf(p, xs) {
|
||||
return count(keepIf(p, xs.value, xs))
|
||||
}
|
||||
exports.countIf = countIf
|
||||
|
||||
// # Filters
|
||||
|
||||
function KeepIf(p, value, input) {
|
||||
this.p = p
|
||||
this.value = p(input.value) ? input.value : value
|
||||
this[$outputs] = []
|
||||
this[$source] = input
|
||||
}
|
||||
KeepIf.receive = function(input, message) {
|
||||
if (input.p(message))
|
||||
Input.receive(input, message)
|
||||
}
|
||||
KeepIf.prototype.constructor = KeepIf
|
||||
KeepIf.prototype = new Input()
|
||||
KeepIf.prototype[$receive] = KeepIf.receive
|
||||
|
||||
// Keep only events that satisfy the given predicate.
|
||||
// Elm does not allow undefined signals, so a base case
|
||||
// must be provided in case the predicate is never satisfied.
|
||||
|
||||
// (x -> Bool) -> x -> Signal x -> Signal x
|
||||
function keepIf(p, x, xs) {
|
||||
return new KeepIf(p, x, xs)
|
||||
}
|
||||
exports.keepIf = keepIf
|
||||
|
||||
|
||||
function DropIf(p, value, input) {
|
||||
this.p = p
|
||||
this.value = p(input.value) ? value : input.value
|
||||
this[$source] = input
|
||||
this[$outputs] = []
|
||||
}
|
||||
DropIf.receive = function(input, message) {
|
||||
if (!input.p(message))
|
||||
Input.receive(input, message)
|
||||
}
|
||||
DropIf.prototype = new Input()
|
||||
DropIf.prototype.constructor = DropIf
|
||||
DropIf.prototype[$receive] = DropIf.receive
|
||||
|
||||
// Drop events that satisfy the given predicate. Elm does not allow
|
||||
// undefined signals, so a base case must be provided in case the
|
||||
// predicate is never satisfied.
|
||||
|
||||
// (x -> Bool) -> x -> Signal x -> Signal x
|
||||
function dropIf(p, x, xs) {
|
||||
return new DropIf(p, x, xs)
|
||||
}
|
||||
exports.dropIf = dropIf
|
||||
|
||||
|
||||
// Keep events only when the first signal is true. When the first signal
|
||||
// becomes true, the most recent value of the second signal will be propagated.
|
||||
// Until the first signal becomes false again, all events will be propagated.
|
||||
// Elm does not allow undefined signals, so a base case must be provided in case
|
||||
// the first signal is never true.
|
||||
|
||||
// Signal Bool -> x -> Signal x -> Signal x
|
||||
function Skip() { return Skip }
|
||||
function isSkip(x) { return x === Skip }
|
||||
function skipIfTrue(isTrue, x) { return isTrue ? Skip : x }
|
||||
function skipIfFalse(isTrue, x) { return isTrue ? x : Skip }
|
||||
|
||||
function keepWhen(state, x, xs) {
|
||||
var input = lift(skipIfFalse, dropRepeats(state), xs)
|
||||
return dropIf(isSkip, x, input)
|
||||
}
|
||||
exports.keepWhen = keepWhen
|
||||
|
||||
// Drop events when the first signal is true. When the first signal
|
||||
// becomes false, the most recent value of the second signal will be
|
||||
// propagated. Until the first signal becomes true again, all events
|
||||
// will be propagated. Elm does not allow undefined signals, so a base
|
||||
// case must be provided in case the first signal is always true.
|
||||
|
||||
// Signal Bool -> x -> Signal x -> Signal x
|
||||
function dropWhen(state, x, xs) {
|
||||
var input = lift(skipIfTrue, dropRepeats(state), xs)
|
||||
return dropIf(isSkip, x, input)
|
||||
}
|
||||
exports.dropWhen = dropWhen
|
||||
|
||||
// Drop sequential repeated values. For example, if a signal produces
|
||||
// the sequence [1,1,2,2,1], it becomes [1,2,1] by dropping the values
|
||||
// that are the same as the previous value.
|
||||
|
||||
// Signal x -> Signal x
|
||||
function dropRepeats(xs) {
|
||||
return dropIf(function(x) {
|
||||
return xs.value === x
|
||||
}, xs.value, xs)
|
||||
}
|
||||
exports.dropRepeats = dropRepeats
|
||||
|
||||
// Sample from the second input every time an event occurs on the first
|
||||
// input. For example, (sampleOn clicks (every second)) will give the
|
||||
// approximate time of the latest click.
|
||||
|
||||
// Signal a -> Signal b -> Signal b
|
||||
function sampleOn(ticks, input) {
|
||||
return merge(dropIf(True, input.value, input),
|
||||
lift(function(_) { return input.value }, ticks))
|
||||
}
|
||||
exports.sampleOn = sampleOn
|
||||
|
||||
function True() { return true }
|
||||
|
||||
},{}]},{},[1])
|
||||
;
|
|
@ -1,62 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var reflex = require("../../reflex");
|
||||
|
||||
// Arguments reperesent cells (like in spreadsheet) that user may change. We can
|
||||
// define derived cells that react to changes on cells they derived from and change
|
||||
// as well.
|
||||
var main = reflex(function(loan, down, price, interest, tax, hazard, other) {
|
||||
var due = reflex.lift(function(loan) {
|
||||
return loan * 12;
|
||||
}, loan);
|
||||
|
||||
var downAmount = reflex.lift(function(price, down) {
|
||||
return price * down / 100;
|
||||
}, price, down);
|
||||
|
||||
var loanAmount = reflex.lift(function(price, downAmount) {
|
||||
return price - downAmount;
|
||||
}, price, downAmount);
|
||||
|
||||
var monthlyMortgage = reflex.lift(function(loan, interest, due) {
|
||||
return Math.round(loan * interest / (1 - (Math.pow(1 / (1 + interest), due))));
|
||||
}, loanAmount, interest, due);
|
||||
|
||||
var estateTax = reflex.lift(function(tax) {
|
||||
return Math.round(tax / 12);
|
||||
}, tax);
|
||||
|
||||
var sum = function() {
|
||||
var total = 0;
|
||||
var index = 0;
|
||||
while (index < arguments.length) {
|
||||
total = total + arguments[index];
|
||||
index = index + 1;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
var totalMonthly = reflex.lift(sum, hazard, other, estateTax, monthlyMortgage);
|
||||
|
||||
// Finally we return record of named cells. Changes on either one of them going to be reflected
|
||||
// on the rendering target. Name of the cell is assumed to be mapped to an id of the element it
|
||||
// is bound to.
|
||||
this.loan = loan;
|
||||
this.down = down;
|
||||
this.price = price;
|
||||
this.interest = interest;
|
||||
this.tax = tax;
|
||||
this.hazardInsurance = hazard;
|
||||
this.otherFinancing = other;
|
||||
this.due = due;
|
||||
this.downAmount = downAmount;
|
||||
this.loanAmount = loanAmount;
|
||||
this.monthlyMortgage = monthlyMortgage;
|
||||
this.estateTax = estateTax;
|
||||
this.totalMonthly = totalMonthly;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
main.render(document.documentElement);
|
||||
}
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="index.css" type="text/css">
|
||||
<title>Loan calculator</title>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<style>
|
||||
input {
|
||||
border: none;
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Loan program: <input id=loan type=number min=10 max=50 step=5 value=0 />yr Fixed</p>
|
||||
<p>Term/Due in: <output id=due /></p>
|
||||
<p>Purchase price: $<input id=price type=number min=100000 max=10000000 step=1000 value=0 /></p>
|
||||
<p>Percent down: <input id=down type=number min=0 max=100 value=0 />% ($<output id=downAmount></output>)</p>
|
||||
<p>Base Loan Amount/Total Loan Amount: $<output id=loanAmount></output></p>
|
||||
<p>Estimated Interest Rate: <input id=interest type=number min=0 max=100 step=0.01 value=0 />%</p>
|
||||
<p>Property taxes: $<input id=tax min=1000 max=4000 step=10 value=0 /></p>
|
||||
<hr/>
|
||||
|
||||
<p>Monthly Mortgage: $<output id=monthlyMortgage></output></p>
|
||||
<p>Hazard Insurance: $<input id=hazardInsurance type=number min=0 value=0 /></p>
|
||||
<p>Other Financing: $<input id=otherFinancing type=number min=0 value=0 /></p>
|
||||
<p>Real Estate Taxes: $<output id=estateTax></output></p>
|
||||
|
||||
<hr/>
|
||||
<p>Estimated Total Monthly Payment: $<output id=totalMonthly type=number></output></p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.5
|
||||
- 0.6
|
|
@ -1,5 +0,0 @@
|
|||
# Changes
|
||||
|
||||
## 0.0.1 / 2012-11-08
|
||||
|
||||
- Initial release
|
|
@ -1,18 +0,0 @@
|
|||
Copyright 2012 Irakli Gozalishvili. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
|
@ -1,12 +0,0 @@
|
|||
# widgets
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/Gozala/widgets.png)](http://travis-ci.org/Gozala/widgets)
|
||||
|
||||
Example of widges
|
||||
|
||||
## Try / Hack
|
||||
|
||||
npm install
|
||||
npm start
|
||||
|
||||
And open `./index.html` in your browser.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,234 +0,0 @@
|
|||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
height: 300px;
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
/* Set scrolling behaviour here */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror pre.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.cm-keymap-fat-cursor pre.CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
background: rgba(0, 200, 0, .4);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
|
||||
}
|
||||
/* Kludge to turn off filter in ie9+, which also accepts rgba */
|
||||
.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable {color: black;}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-property {color: black;}
|
||||
.cm-s-default .cm-operator {color: black;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-emstrong {font-style: italic; font-weight: bold;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px; padding-right: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actuall scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
height: 100%;
|
||||
float: left;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%; height: 0px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
.CodeMirror-focused pre.CodeMirror-cursor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
|
||||
.CodeMirror-searching {
|
||||
background: #ffa;
|
||||
background: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,411 +0,0 @@
|
|||
// TODO actually recognize syntax of TypeScript constructs
|
||||
|
||||
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit;
|
||||
var jsonMode = parserConfig.json;
|
||||
var isTS = parserConfig.typescript;
|
||||
|
||||
// Tokenizer
|
||||
|
||||
var keywords = function(){
|
||||
function kw(type) {return {type: type, style: "keyword"};}
|
||||
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
||||
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||
|
||||
var jsKeywords = {
|
||||
"if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
|
||||
"var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||
"function": kw("function"), "catch": kw("catch"),
|
||||
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||
"in": operator, "typeof": operator, "instanceof": operator,
|
||||
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
|
||||
};
|
||||
|
||||
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||
if (isTS) {
|
||||
var type = {type: "variable", style: "variable-3"};
|
||||
var tsKeywords = {
|
||||
// object-like things
|
||||
"interface": kw("interface"),
|
||||
"class": kw("class"),
|
||||
"extends": kw("extends"),
|
||||
"constructor": kw("constructor"),
|
||||
|
||||
// scope modifiers
|
||||
"public": kw("public"),
|
||||
"private": kw("private"),
|
||||
"protected": kw("protected"),
|
||||
"static": kw("static"),
|
||||
|
||||
"super": kw("super"),
|
||||
|
||||
// types
|
||||
"string": type, "number": type, "bool": type, "any": type
|
||||
};
|
||||
|
||||
for (var attr in tsKeywords) {
|
||||
jsKeywords[attr] = tsKeywords[attr];
|
||||
}
|
||||
}
|
||||
|
||||
return jsKeywords;
|
||||
}();
|
||||
|
||||
var isOperatorChar = /[+\-*&%=<>!?|]/;
|
||||
|
||||
function chain(stream, state, f) {
|
||||
state.tokenize = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
function nextUntilUnescaped(stream, end) {
|
||||
var escaped = false, next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == end && !escaped)
|
||||
return false;
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// Used as scratch variables to communicate multiple values without
|
||||
// consing up tons of objects.
|
||||
var type, content;
|
||||
function ret(tp, style, cont) {
|
||||
type = tp; content = cont;
|
||||
return style;
|
||||
}
|
||||
|
||||
function jsTokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'")
|
||||
return chain(stream, state, jsTokenString(ch));
|
||||
else if (/[\[\]{}\(\),;\:\.]/.test(ch))
|
||||
return ret(ch);
|
||||
else if (ch == "0" && stream.eat(/x/i)) {
|
||||
stream.eatWhile(/[\da-f]/i);
|
||||
return ret("number", "number");
|
||||
}
|
||||
else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
|
||||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||
return ret("number", "number");
|
||||
}
|
||||
else if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
return chain(stream, state, jsTokenComment);
|
||||
}
|
||||
else if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||
/^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||
nextUntilUnescaped(stream, "/");
|
||||
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
||||
return ret("regexp", "string-2");
|
||||
}
|
||||
else {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", null, stream.current());
|
||||
}
|
||||
}
|
||||
else if (ch == "#") {
|
||||
stream.skipToEnd();
|
||||
return ret("error", "error");
|
||||
}
|
||||
else if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", null, stream.current());
|
||||
}
|
||||
else {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
||||
ret("variable", "variable", word);
|
||||
}
|
||||
}
|
||||
|
||||
function jsTokenString(quote) {
|
||||
return function(stream, state) {
|
||||
if (!nextUntilUnescaped(stream, quote))
|
||||
state.tokenize = jsTokenBase;
|
||||
return ret("string", "string");
|
||||
};
|
||||
}
|
||||
|
||||
function jsTokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = jsTokenBase;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
||||
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
|
||||
|
||||
function JSLexical(indented, column, type, align, prev, info) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.prev = prev;
|
||||
this.info = info;
|
||||
if (align != null) this.align = align;
|
||||
}
|
||||
|
||||
function inScope(state, varname) {
|
||||
for (var v = state.localVars; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
}
|
||||
|
||||
function parseJS(state, style, type, content, stream) {
|
||||
var cc = state.cc;
|
||||
// Communicate our context to the combinators.
|
||||
// (Less wasteful than consing up a hundred closures on every call.)
|
||||
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
|
||||
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = true;
|
||||
|
||||
while(true) {
|
||||
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||
if (combinator(type, content)) {
|
||||
while(cc.length && cc[cc.length - 1].lex)
|
||||
cc.pop()();
|
||||
if (cx.marked) return cx.marked;
|
||||
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||
return style;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combinator utils
|
||||
|
||||
var cx = {state: null, column: null, marked: null, cc: null};
|
||||
function pass() {
|
||||
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||
}
|
||||
function cont() {
|
||||
pass.apply(null, arguments);
|
||||
return true;
|
||||
}
|
||||
function register(varname) {
|
||||
var state = cx.state;
|
||||
if (state.context) {
|
||||
cx.marked = "def";
|
||||
for (var v = state.localVars; v; v = v.next)
|
||||
if (v.name == varname) return;
|
||||
state.localVars = {name: varname, next: state.localVars};
|
||||
}
|
||||
}
|
||||
|
||||
// Combinators
|
||||
|
||||
var defaultVars = {name: "this", next: {name: "arguments"}};
|
||||
function pushcontext() {
|
||||
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
|
||||
cx.state.localVars = defaultVars;
|
||||
}
|
||||
function popcontext() {
|
||||
cx.state.localVars = cx.state.context.vars;
|
||||
cx.state.context = cx.state.context.prev;
|
||||
}
|
||||
function pushlex(type, info) {
|
||||
var result = function() {
|
||||
var state = cx.state;
|
||||
state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
|
||||
};
|
||||
result.lex = true;
|
||||
return result;
|
||||
}
|
||||
function poplex() {
|
||||
var state = cx.state;
|
||||
if (state.lexical.prev) {
|
||||
if (state.lexical.type == ")")
|
||||
state.indented = state.lexical.indented;
|
||||
state.lexical = state.lexical.prev;
|
||||
}
|
||||
}
|
||||
poplex.lex = true;
|
||||
|
||||
function expect(wanted) {
|
||||
return function expecting(type) {
|
||||
if (type == wanted) return cont();
|
||||
else if (wanted == ";") return pass();
|
||||
else return cont(arguments.callee);
|
||||
};
|
||||
}
|
||||
|
||||
function statement(type) {
|
||||
if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
|
||||
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
||||
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||
if (type == "{") return cont(pushlex("}"), block, poplex);
|
||||
if (type == ";") return cont();
|
||||
if (type == "function") return cont(functiondef);
|
||||
if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
|
||||
poplex, statement, poplex);
|
||||
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
||||
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
||||
block, poplex, poplex);
|
||||
if (type == "case") return cont(expression, expect(":"));
|
||||
if (type == "default") return cont(expect(":"));
|
||||
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
||||
statement, poplex, popcontext);
|
||||
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||
}
|
||||
function expression(type) {
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
|
||||
if (type == "function") return cont(functiondef);
|
||||
if (type == "keyword c") return cont(maybeexpression);
|
||||
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
|
||||
if (type == "operator") return cont(expression);
|
||||
if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
|
||||
if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
|
||||
return cont();
|
||||
}
|
||||
function maybeexpression(type) {
|
||||
if (type.match(/[;\}\)\],]/)) return pass();
|
||||
return pass(expression);
|
||||
}
|
||||
|
||||
function maybeoperator(type, value) {
|
||||
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
|
||||
if (type == "operator" && value == "?") return cont(expression, expect(":"), expression);
|
||||
if (type == ";") return;
|
||||
if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
|
||||
if (type == ".") return cont(property, maybeoperator);
|
||||
if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
|
||||
}
|
||||
function maybelabel(type) {
|
||||
if (type == ":") return cont(poplex, statement);
|
||||
return pass(maybeoperator, expect(";"), poplex);
|
||||
}
|
||||
function property(type) {
|
||||
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||
}
|
||||
function objprop(type) {
|
||||
if (type == "variable") cx.marked = "property";
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
|
||||
}
|
||||
function commasep(what, end) {
|
||||
function proceed(type) {
|
||||
if (type == ",") return cont(what, proceed);
|
||||
if (type == end) return cont();
|
||||
return cont(expect(end));
|
||||
}
|
||||
return function commaSeparated(type) {
|
||||
if (type == end) return cont();
|
||||
else return pass(what, proceed);
|
||||
};
|
||||
}
|
||||
function block(type) {
|
||||
if (type == "}") return cont();
|
||||
return pass(statement, block);
|
||||
}
|
||||
function maybetype(type) {
|
||||
if (type == ":") return cont(typedef);
|
||||
return pass();
|
||||
}
|
||||
function typedef(type) {
|
||||
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
||||
return pass();
|
||||
}
|
||||
function vardef1(type, value) {
|
||||
if (type == "variable") {
|
||||
register(value);
|
||||
return isTS ? cont(maybetype, vardef2) : cont(vardef2);
|
||||
}
|
||||
return pass();
|
||||
}
|
||||
function vardef2(type, value) {
|
||||
if (value == "=") return cont(expression, vardef2);
|
||||
if (type == ",") return cont(vardef1);
|
||||
}
|
||||
function forspec1(type) {
|
||||
if (type == "var") return cont(vardef1, expect(";"), forspec2);
|
||||
if (type == ";") return cont(forspec2);
|
||||
if (type == "variable") return cont(formaybein);
|
||||
return cont(forspec2);
|
||||
}
|
||||
function formaybein(_type, value) {
|
||||
if (value == "in") return cont(expression);
|
||||
return cont(maybeoperator, forspec2);
|
||||
}
|
||||
function forspec2(type, value) {
|
||||
if (type == ";") return cont(forspec3);
|
||||
if (value == "in") return cont(expression);
|
||||
return cont(expression, expect(";"), forspec3);
|
||||
}
|
||||
function forspec3(type) {
|
||||
if (type != ")") cont(expression);
|
||||
}
|
||||
function functiondef(type, value) {
|
||||
if (type == "variable") {register(value); return cont(functiondef);}
|
||||
if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
|
||||
}
|
||||
function funarg(type, value) {
|
||||
if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: jsTokenBase,
|
||||
lastType: null,
|
||||
cc: [],
|
||||
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||
localVars: parserConfig.localVars,
|
||||
context: parserConfig.localVars && {vars: parserConfig.localVars},
|
||||
indented: 0
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.sol()) {
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = false;
|
||||
state.indented = stream.indentation();
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if (type == "comment") return style;
|
||||
state.lastType = type;
|
||||
return parseJS(state, style, type, content, stream);
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
|
||||
if (state.tokenize != jsTokenBase) return 0;
|
||||
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
|
||||
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
|
||||
var type = lexical.type, closing = firstChar == type;
|
||||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
|
||||
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||
else if (type == "form") return lexical.indented + indentUnit;
|
||||
else if (type == "stat")
|
||||
return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0);
|
||||
else if (lexical.info == "switch" && !closing)
|
||||
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||
},
|
||||
|
||||
electricChars: ":{}",
|
||||
|
||||
jsonMode: jsonMode
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
|
||||
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
|
||||
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>widgets</title>
|
||||
<link rel=stylesheet href=build/codemirror.css />
|
||||
<link rel=stylesheet href=build/solarized.css />
|
||||
<script src=build/codemirror.js></script>
|
||||
<script src=build/javascript.js></script>
|
||||
<style>
|
||||
body { width: 100%; height: 100%; position: fixed; top: 0; left: 0; margin: 0; }
|
||||
.CodeMirror { height: 100%; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script src="build/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,169 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var CodeMirror = require("./code-mirror")
|
||||
var diff = require("diffpatcher/diff")
|
||||
var patch = require("diffpatcher/patch")
|
||||
var render = require("./render")
|
||||
|
||||
|
||||
CodeMirror.defaults.interactiveEnabled = true
|
||||
CodeMirror.defaults.interactiveKey = "Cmd-Enter"
|
||||
CodeMirror.defaults.interactiveSpeed = 300
|
||||
CodeMirror.defaults.interactiveSeparator = /^\/\/ \=\>[^\n]*$/m
|
||||
|
||||
var makeView = (function() {
|
||||
var uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAMCAYAAABBV8wuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGpJREFUeNpi/P//PwM2wMSAA7CACEYggLKZgfgvEP8BCYAwKxALAjEPEH8B4g9MUI5IWlqayevXr9eCaCBfGGSSVnJysu/Xr1+fAx3y/9u3by9BfIb29vZCmCAMgCQZ/+NwL07nUlECIMAAMr41sxvv6oEAAAAASUVORK5CYII="
|
||||
var template = document.createElement("div")
|
||||
|
||||
template.style.marginLeft = "-10px"
|
||||
template.style.padding = "0"
|
||||
template.style.position = "relative"
|
||||
template.style.marginRight = "-10px"
|
||||
template.style.whiteSpace = "normal"
|
||||
|
||||
template.innerHTML = [
|
||||
" <div class='cm-live-output-border-top'> </div>",
|
||||
" <div class='cm-live-output-box'>",
|
||||
" <h1 class='cm-live-output-head'>Out[0]</h1>",
|
||||
" <pre class='cm-live-output-body'>Hello output</pre>",
|
||||
" </div>",
|
||||
" <div class='cm-live-output-border-bottom'></div>",
|
||||
].join("\n")
|
||||
|
||||
template.querySelector(".cm-live-output-border-top").setAttribute("style", [
|
||||
"position: relative",
|
||||
"z-index: 2",
|
||||
"height: 12px",
|
||||
"background-clip: padding-box",
|
||||
"background: url('" + uri + "') top right repeat-x"
|
||||
].join(";"))
|
||||
|
||||
template.querySelector(".cm-live-output-border-bottom").setAttribute("style", [
|
||||
"position: relative",
|
||||
"z-index: 2",
|
||||
"height: 12px",
|
||||
"background-clip: padding-box",
|
||||
"background: url('" + uri + "') top left repeat-x",
|
||||
"-webkit-transform: rotate(180deg)",
|
||||
"transform: rotate(180deg)"
|
||||
].join(";"))
|
||||
|
||||
template.querySelector(".cm-live-output-box").setAttribute("style", [
|
||||
"-moz-box-shadow: 0 0 30px -2px #000",
|
||||
"-webkit-box-shadow: 0 0 30px -2px #000",
|
||||
"box-shadow: 0 0 30px -2px #000",
|
||||
"color: black",
|
||||
"background: white",
|
||||
"position: relative",
|
||||
"padding: 10px",
|
||||
"margin: 0px",
|
||||
"display: -webkit-box",
|
||||
"display: -moz-box",
|
||||
"display: -moz-flex;",
|
||||
"-webkit-box-flex: 2",
|
||||
"-moz-box-flex: 2",
|
||||
"box-flex: 2",
|
||||
"width: 100%"
|
||||
].join(";"))
|
||||
|
||||
template.querySelector(".cm-live-output-head").setAttribute("style", [
|
||||
"-webkit-box-flex: 0",
|
||||
"-moz-box-flex: 0",
|
||||
"box-flex: 0",
|
||||
"margin: 0 10px 0 0",
|
||||
"whitespace: pre",
|
||||
"color: white",
|
||||
"text-shadow: 0px 1px 5px #000"
|
||||
].join(";"))
|
||||
template.querySelector(".cm-live-output-body").setAttribute("style", [
|
||||
"-webkit-box-flex: 1",
|
||||
"-moz-box-flex: 1",
|
||||
"box-flex: 1",
|
||||
"padding-right: 30px"
|
||||
].join(";"))
|
||||
|
||||
return function makeView(editor, line) {
|
||||
var view = template.cloneNode(true)
|
||||
|
||||
editor.markText({ line: line, ch: 0 },
|
||||
{ line: line + 1, ch: 0 },
|
||||
{ atomic: true, replacedWith: view })
|
||||
|
||||
return view
|
||||
}
|
||||
})()
|
||||
|
||||
module.exports = function interactive(editor) {
|
||||
var state = {}
|
||||
var View = {}
|
||||
var Out = {}
|
||||
var id = -1
|
||||
|
||||
window.Out = Out
|
||||
|
||||
function apply(delta) {
|
||||
Object.keys(delta).forEach(function(id) {
|
||||
var In = delta[id]
|
||||
editor.operation(function() {
|
||||
if (In === null) {
|
||||
delete Out[id]
|
||||
delete View[id]
|
||||
} else {
|
||||
var view = View[id] || (View[id] = makeView(editor, In.line))
|
||||
try {
|
||||
Out[id] = window.eval(In.source)
|
||||
} catch (error) {
|
||||
Out[id] = error
|
||||
}
|
||||
var label = view.querySelector(".cm-live-output-head")
|
||||
var code = view.querySelector(".cm-live-output-body")
|
||||
label.textContent = "Out[" + id + "] = "
|
||||
code.innerHTML = "<span></span>"
|
||||
var out = render(Out[id])
|
||||
if (out instanceof Element)
|
||||
code.replaceChild(out, code.children[0])
|
||||
else
|
||||
code.textContent = out
|
||||
}
|
||||
})
|
||||
})
|
||||
state = patch(state, delta)
|
||||
}
|
||||
|
||||
function calculate() {
|
||||
var source = editor.getValue()
|
||||
var separator = editor.getOption("interactiveSeparator")
|
||||
var sections = source.split(separator)
|
||||
sections.pop()
|
||||
var update = Object.keys(sections).reduce(function(result, index) {
|
||||
var source = sections[index]
|
||||
var out = result.out + source.split("\n").length - 1
|
||||
result.out = out
|
||||
result.state[index] = {
|
||||
source: source,
|
||||
line: out
|
||||
}
|
||||
|
||||
return result
|
||||
}, { out: 0, state: {} })
|
||||
|
||||
var delta = diff(state, update.state)
|
||||
apply(delta)
|
||||
}
|
||||
|
||||
editor.on("change", function(editor, change) {
|
||||
clearTimeout(id)
|
||||
id = setTimeout(calculate, editor.getOption("interactiveSpeed"), change)
|
||||
})
|
||||
|
||||
function print(editor) {
|
||||
if (!editor.getOption("interactiveEnabled")) throw CodeMirror.Pass
|
||||
editor.operation(function() {
|
||||
var cursor = editor.getCursor()
|
||||
editor.replaceSelection("\n// =>\n")
|
||||
editor.setCursor({ line: cursor.line + 2, ch: 0 })
|
||||
})
|
||||
}
|
||||
|
||||
CodeMirror.keyMap.default[editor.getOption("interactiveKey")] = print
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var reducers = require("reducers")
|
||||
var dom = require("dom-reduce")
|
||||
var widget = require("./widget")
|
||||
|
||||
var interactive = require("interactivate/main")
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"name": "widgets",
|
||||
"id": "widgets",
|
||||
"version": "0.0.1",
|
||||
"description": "Example of widges",
|
||||
"keywords": [
|
||||
"widgets"
|
||||
],
|
||||
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||
"homepage": "https://github.com/Gozala/widgets",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gozala/widgets.git",
|
||||
"web": "https://github.com/Gozala/widgets"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Gozala/widgets/issues/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"test": "~0.x.0",
|
||||
"repl-utils": "~1.0.0",
|
||||
"phantomify": "~0.x.0",
|
||||
"browserify": "~1.x.0",
|
||||
"interactivate": "0.0.1"
|
||||
},
|
||||
"main": "./main.js",
|
||||
"scripts": {
|
||||
"test": "npm run test-node && npm run test-browser",
|
||||
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/index.js",
|
||||
"test-node": "node ./test/index.js",
|
||||
"repl": "node node_modules/repl-utils",
|
||||
"start": "node ./node_modules/browserify/bin/cmd.js --exports require --watch --debug --entry ./main.js --outfile ./build/main.js",
|
||||
"postinstall": "npm dedup"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/Gozala/widgets/License.md"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"diffpatcher": "~1.0.0",
|
||||
"dom-reduce": "~1.0.0",
|
||||
"reducers": "~2.0.0",
|
||||
"method": "~1.0.0",
|
||||
"interactivate": "0.0.3",
|
||||
"event": "~1.0.0"
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var method = require("method")
|
||||
var util = require("util")
|
||||
|
||||
|
||||
// Render function takes arbitrary data structure and returns something
|
||||
// that can visually represent it.
|
||||
var render = method("render")
|
||||
|
||||
render.define(function(value) {
|
||||
return util.inspect(value)
|
||||
})
|
||||
|
||||
render.define(Error, function(error) {
|
||||
return String(error)
|
||||
})
|
||||
|
||||
render.define(Element, function(element) {
|
||||
return element
|
||||
})
|
||||
|
||||
module.exports = render
|
|
@ -1,52 +0,0 @@
|
|||
var widget = require("./widget")
|
||||
|
||||
var chart = widget(function open(data) {
|
||||
var sheet = document.createElement('style')
|
||||
sheet.innerHTML = ".bar { -webkit-transition: width ease-in 1s;" +
|
||||
"transition: width ease-in 1s; }"
|
||||
document.body.appendChild(sheet);
|
||||
|
||||
var view = document.createElement("div")
|
||||
Object.keys(data).forEach(function(id) {
|
||||
var item = document.createElement("div")
|
||||
item.id = id
|
||||
item.className = "bar"
|
||||
item.style.height = "5px"
|
||||
item.style.margin = "2px"
|
||||
item.style.background = "orange"
|
||||
item.style.width = data[id] + "%"
|
||||
view.appendChild(item)
|
||||
})
|
||||
return view
|
||||
}, function swap(state, view) {
|
||||
Object.keys(state).forEach(function(id) {
|
||||
var item = view.querySelector("#" + id)
|
||||
item.style.width = state[id] + "%"
|
||||
})
|
||||
})
|
||||
|
||||
c1 = chart({ apples: 30, oranges: 36, grapes: 45 })
|
||||
|
||||
// =>
|
||||
|
||||
|
||||
|
||||
var event = require("event")
|
||||
var send = require("event/send")
|
||||
|
||||
var input = event()
|
||||
|
||||
c2 = chart({ apples: 30, oranges: 36, grapes: 40 }, input)
|
||||
|
||||
|
||||
// =>
|
||||
|
||||
|
||||
|
||||
|
||||
send(input, { apples: 30, grapes: 40 })
|
||||
|
||||
|
||||
// =>
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
"use strict";
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var event = require("event")
|
||||
var send = require("event/send")
|
||||
var fold = require("reducers/fold")
|
||||
var render = require("interactivate/render")
|
||||
|
||||
|
||||
function Widget(model, input, open, swap) {
|
||||
this.model = model
|
||||
this.input = input
|
||||
this.open = open
|
||||
this.swap = swap
|
||||
}
|
||||
render.define(Widget, function(widget) {
|
||||
var view = widget.open(widget.model)
|
||||
fold(widget.input, function(state) {
|
||||
widget.swap(state, view)
|
||||
})
|
||||
return view
|
||||
})
|
||||
|
||||
function widget(open, swap) {
|
||||
return function (model, input) {
|
||||
return new Widget(model, input, open, swap)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = widget
|
Загрузка…
Ссылка в новой задаче