I know timerE returns an event stream that fires an event at specific
intervals. But I am a bit lost in how to make my desired function to
work. for example, I want to build a sample that reduces from 100 to
0:
// i have a timer now that triggers event every second
var timer = timerE(1000);
// what i want to here is reduce the value of element 'fall' by 1
every sec (timer triggers)
var content = timer.mapE(function(x){
return $B('fall') - 1;
});
// given an init value 100 and fill it in element 'fall'
insertDomB(content.startsWith("100"), 'fall');
I cannot get it working. Maybe this sounds very simple for some you
guys but I tried many ways. What I want to do is just {get a value
from form input element id 'fall', minus 1 then return, replace page
element with a behavior}. According to flapjax api doc, timerE event
value is current system time which is not what I need. I just need my
own function triggers every 1 second. Perhaps I dont understand event
streams in flapjax very well, any advice would be appreciated.
Is there a particular reason you want it to use the form element,
rather than the event stream itself, to store your "fall" value? The
following flapjax-compiler-ready code does a slightly simpler version
of what you're asking:
<html>
<head>
<title>Flapjax Demo: Where is the Mouse?</title>
<link rel="stylesheet" href="/demo.css"/>
<script type="text/flapjax">
// Count the number of times we catch up.
var fallB =
timerE(1000). //once per second
collectE(100, //collecting starting at 100
function (_,p) { return p - 1;}). //every time the event occurs,
subtract 1 from the event value p
startsWith(100); //before any events have been fired, the
behavior is 100
> I know timerE returns an event stream that fires an event at specific
> intervals. But I am a bit lost in how to make my desired function to
> work. for example, I want to build a sample that reduces from 100 to
> 0:
> // i have a timer now that triggers event every second
> var timer = timerE(1000);
> // what i want to here is reduce the value of element 'fall' by 1
> every sec (timer triggers)
> var content = timer.mapE(function(x){
> return $B('fall') - 1;
> });
> // given an init value 100 and fill it in element 'fall'
> insertDomB(content.startsWith("100"), 'fall');
> I cannot get it working. Maybe this sounds very simple for some you
> guys but I tried many ways. What I want to do is just {get a value
> from form input element id 'fall', minus 1 then return, replace page
> element with a behavior}. According to flapjax api doc, timerE event
> value is current system time which is not what I need. I just need my
> own function triggers every 1 second. Perhaps I dont understand event
> streams in flapjax very well, any advice would be appreciated.
Thanks a lot for help. It greatly helps me rethinking and resolve my
problem.
Now i'm thinking about some other issues. According to flapjax,
traditional callbacks are avoided at most effort. Say, i have a small
div block on page and i want to move its position by keyboard strokes,
arrow directions. Now that I'm not encouraged to use callbacks, i have
to find a way to identify what key user pressed. I have been reading
tutorial and api doc but cannot find an effective way yet.
all the best,
/p
On May 18, 9:14 pm, Dan Bjorge <brosm...@gmail.com> wrote:
> Is there a particular reason you want it to use the form element,
> rather than the event stream itself, to store your "fall" value? The
> following flapjax-compiler-ready code does a slightly simpler version
> of what you're asking:
> <html>
> <head>
> <title>Flapjax Demo: Where is the Mouse?</title>
> <link rel="stylesheet" href="/demo.css"/>
> <script type="text/flapjax">
> // Count the number of times we catch up.
> var fallB =
> timerE(1000). //once per second
> collectE(100, //collecting starting at 100
> function (_,p) { return p - 1;}). //every time the event occurs,
> subtract 1 from the event value p
> startsWith(100); //before any events have been fired, the
> behavior is 100
> On May 18, 12:29 pm, pointer <chen...@gmail.com> wrote:
> > Hi there,
> > I know timerE returns an event stream that fires an event at specific
> > intervals. But I am a bit lost in how to make my desired function to
> > work. for example, I want to build a sample that reduces from 100 to
> > 0:
> > // i have a timer now that triggers event every second
> > var timer = timerE(1000);
> > // what i want to here is reduce the value of element 'fall' by 1
> > every sec (timer triggers)
> > var content = timer.mapE(function(x){
> > return $B('fall') - 1;
> > });
> > // given an init value 100 and fill it in element 'fall'
> > insertDomB(content.startsWith("100"), 'fall');
> > I cannot get it working. Maybe this sounds very simple for some you
> > guys but I tried many ways. What I want to do is just {get a value
> > from form input element id 'fall', minus 1 then return, replace page
> > element with a behavior}. According to flapjax api doc, timerE event
> > value is current system time which is not what I need. I just need my
> > own function triggers every 1 second. Perhaps I dont understand event
> > streams in flapjax very well, any advice would be appreciated.
> Now i'm thinking about some other issues. According to flapjax, > traditional callbacks are avoided at most effort. Say, i have a small > div block on page and i want to move its position by keyboard strokes, > arrow directions. Now that I'm not encouraged to use callbacks, i have > to find a way to identify what key user pressed. I have been reading > tutorial and api doc but cannot find an effective way yet.
The key here is to think in terms of data dependencies, I think. What events/behaviors does a position depend on?
Let's take a small counter example (pun intended). Say you have an output field that displays current counter value, and a button to increase that value. That button, when pressed, "creates" an event, and thus generates a stream of events; every event is an object that holds a function to increase it's argument by one:
b = function(x) { return x + 1; }, function(x) { return x + 1; }, ... (I use this representation when I think of event streams [1])
How do we define a counter then? Quite easily: a counter is a *left fold* over stream of button events (streams are somewhat analogous to singly linked lists):
a = startsWith(collectE(b, 0, function(x,y) { return x(y); }), 0);
We turned 'a' into a behavior, so it always has a value. Initially, the value is zero (it's called a 'seed'), but when an event arrives, we apply it to the seed value, which gives us next seed. The process continues on.
There's more here. We can add another button, and it's event stream would be defined as follows:
c = function(x) { return x - 1; }, ...
Since no user can press two buttons simultaneously, I think it's safe to combine two event streams using mergeE:
x = mergeE(b,c)
We can supply this value to the collectE function, creating a counter with two buttons. :) We can go further, by defining another button:
d = function(_) { return 0; }, ...
Guess what it does. :)
Hope this helps, Artyom Shalkhakov.
[1] in Flapjax, that would be clicksE('my-button').constantE(function(x) { return x + 1; })
Thanks a lot for your informative reply! It helps a lot. I think the core of
what you are trying to say is exactly "By thinking harder about the
relationships between your data you write more declarative specifications,
leaving more of the work of maintaining consistency to the language" in
flapjax tutorial.
However, lets back to my concrete problem. Heres some my thoughts:
* div block position fully depends on its topleft (x,y)
* (x,y) must be a behavior result
* i have to detect what arrow keys people pressed to decide what (x,y) value
should behave
and actually after a few attempts, I make it working.
First make an event stream which is to capture all keydown events on window
itself:
var keysE = extractEventE(self, 'keydown');
then transform this event stream:
var move = keysE.mapE(function(p){
switch (p.keyCode) {
case 37: // user press '<---'
x = x - 24;
return x;
break;
case 39: // user press '--->'
x = x + 24;
return x;
break;
default:
break;
}
});
lastly I render it:
insertDomB(DIV({
className: 'block',
style: {
position: 'absolute',
left: move.startsWith(x), // currently i'm only making it
can be moved left or right
top: y,
width: this.width, // my class Block attribute
height: this.height,
background: this.color
}
}, ""), 'area', 'beginning');
It works fine. BUT, I still feel a bit guilty :-s - because of my 'var
move'. No matter how I inspect it, it looks quite like traditional
callbacks: detect key code then make a decision what to do next. However, I
think it's the key business logic for this problem isnt it. What makes me
relieved is my block's topleft corner is exactly a flapjax behavior result.
I'd like to hear any tips to do it in a more decent way.
> 2009/5/20 pointer <chen...@gmail.com>:
> > Now i'm thinking about some other issues. According to flapjax,
> > traditional callbacks are avoided at most effort. Say, i have a small
> > div block on page and i want to move its position by keyboard strokes,
> > arrow directions. Now that I'm not encouraged to use callbacks, i have
> > to find a way to identify what key user pressed. I have been reading
> > tutorial and api doc but cannot find an effective way yet.
> The key here is to think in terms of data dependencies, I think. What
> events/behaviors does a position depend on?
> Let's take a small counter example (pun intended). Say you have an
> output field that displays current counter value, and a button to increase
> that value. That button, when pressed, "creates" an event, and thus
> generates a stream of events; every event is an object that holds
> a function to increase it's argument by one:
> b = function(x) { return x + 1; }, function(x) { return x + 1; }, ...
> (I use this representation when I think of event streams [1])
> How do we define a counter then? Quite easily: a counter is a *left fold*
> over stream of button events (streams are somewhat analogous to singly
> linked lists):
> We turned 'a' into a behavior, so it always has a value. Initially, the
> value is
> zero (it's called a 'seed'), but when an event arrives, we apply it to the
> seed
> value, which gives us next seed. The process continues on.
> There's more here. We can add another button, and it's event stream would
> be defined as follows:
> c = function(x) { return x - 1; }, ...
> Since no user can press two buttons simultaneously, I think it's safe to
> combine
> two event streams using mergeE:
> x = mergeE(b,c)
> We can supply this value to the collectE function, creating a counter with
> two
> buttons. :) We can go further, by defining another button:
> d = function(_) { return 0; }, ...
> Guess what it does. :)
> Hope this helps,
> Artyom Shalkhakov.
> [1] in Flapjax, that would be
> clicksE('my-button').constantE(function(x) { return x + 1; })
I assume x is a global variable that is initialized to the the initial position of the block. I recommend you look at the collectE function. Turn that mapE into a collectE and it will no longer use global state.
This will let you create multiple moveE's (if you move that logic into a function) that are initialized with different starting positions. That will give turn this into a reusable abstraction: perhaps that's what you're looking for?
> It works fine. BUT, I still feel a bit guilty :-s - because of my 'var > move'. No matter how I inspect it, it looks quite like traditional > callbacks: