Nifty Piano Demo

3 views
Skip to first unread message

Dan Bjorge

unread,
May 18, 2009, 3:30:48 PM5/18/09
to Flapjax
I just threw together a small flapjax demo on a whim - it
demonstrates, among some basic event/behavior examplings, that flapjax
works fine with other libraries (in this case, SoundManager2). It is
hosted at http://users.wpi.edu/~dbjorge/flapjax/piano.html

While I was making it, I came across a problem that I was hoping
someone here could help with. I tried making the text box at the
bottom clear the input as you typed so that it could read the entire
box instead of just the last character in the box (which would let
people play chords if you pressed several keys at once), and it worked
pretty well except for one issue - extractValueB('thetextbox') doesn't
seem to pick up changes in the value if the value is set by javascript
instead of a user. I tried clearing it by putting a clear function
inside a mapE on extractValueB('thetextbox').changes() (the same place
the "playNoteSound()" bit fires), but whether I tried it - whether the
clear function worked via insertValueB('', 'thetextbox', 'value') or
document.getElementById('thetextbox').value='' - extractValueB
('thetextbox') doesn't seem to notice the value changing
programatically. This caused a bug in that extractValueB
('thetextbox').changes() wouldn't fire if the user played the same
note twice in a row, since as far as flapjax seemed to know the box
hadn't changed.

Is this behavior intended? I can see how it could potentially cause
infinite loop issues if it worked like I'd like here and programmers
weren't careful about it. If it's not intended, am I doing something
wrong, is it a bug in flapjax, or a quirk of javascript...?

Thanks!
-Dan Bjorge

Leo Meyerovich

unread,
May 18, 2009, 3:45:58 PM5/18/09
to fla...@googlegroups.com
Right, it was the feedback loop thing -- I just merge the insert stream
with the extracted stream, and maybe filterRepeats. Merging still allows
feedback loops, so this isn't a real solution. My hope was that you'd
notice the potential for the loop this way, and it leaves room for
figuring out and incorporating a more principled solution.

The $B function has a simple case statement on form element type. I
think there is a DOM value change event you can simply add to the event
listeners -- there might have been a browser compatibility issue with
this as well.

- Leo

Arjun Guha

unread,
May 18, 2009, 6:22:34 PM5/18/09
to fla...@googlegroups.com
Yeah, extractValueE/B doesn't play nicely with programmatic updates of
the textbox. What you could do--this is an awful hack--is set the
value and then call .sendBehavior(value) to update the behavior that
you're reading. (Let me know if this is unclear, I can give an
example).

This is a quirk/bug in Flapjax. extractValueB is a thin function that
monitors that uses event handlers like "keypress" to monitor changes
to the input. No event fires when you programmatically update a text
box, so extractValueB misses it.


Have you considered using the extractEventE(textbox, "keypress")? The
event values of a keypress event (and anything from extractEventE) are
DOM events:

http://www.w3schools.com/jsref/jsref_onkeypress.asp

So, you could use the .keyCode field.

Arjun

Dan Bjorge

unread,
May 19, 2009, 12:06:03 PM5/19/09
to Flapjax
I changed it to use the keyup event (not keypress - the idea is to
support chords) like you suggested and that works fantastically,
except that I have to do something mildly gross and hacky since I
think keyup events happen before extractValue updates itself or
something. Here's the code that initializes the text box event stream
(this works):


keysE = extractEventE('keyinput', 'keyup'); //use events from here so
programitic updates don't fail
keysE.mapE(function() {
document.getElementById('keyinput').value. //This SHOULD be a
behavior, but the behaviors don't update themselves in time. This
works since it's wrapped in a function()
split('').forEach(function(ch) {
if(ch in noteKeys) {
notes[noteKeys[ch]].play();
}}
);
document.getElementById('keyinput').value='';
});


I feel intuitively like it "should" look something more like this, but
this doesn't work:


keysE = extractEventE('keyinput', 'keyup') //use events from here so
programitic updates don't fail
.snapshotE(extractValueB('keyinput')); //use this instead of
event.keycode so we can read >1 key at once
keysE.mapE(function(keys) {
keys.split('').forEach(function(ch) {
if(ch in noteKeys) {
notes[noteKeys[ch]].play();
}}
);
document.getElementById('keyinput').value='';
});
Reply all
Reply to author
Forward
0 new messages