2

Messing around with a bacon.js. I'd like to keep a running total of values in a group of text inputs. The example on the github site uses .scan and an adder function, which works fine for the example because it's using -1 and +1 in the stream. But I'd like values to be removed from the stream if they are edited, so the .scan solution won't really work for me or I'm not doing it right.

Markup:

<ul style="repeat-direction: vertical; list-style-type: none;">
  <li><input data-group="0"></li>
  <li><input data-group="0"></li>
  <li><input data-group="0"></li>
</ul>
<ul style="repeat-direction: vertical; list-style-type: none;">
  <li><input data-group="1"></li>
  <li><input data-group="1"></li>
  <li><input data-group="1"></li>
</ul>

So the solution that I have is to run through the inputs whenever there's a throttled keyup event and then update a span when it changes.

groupZeroEvents = events.filter (val) ->
   Math.floor(val[0]) == 0 # the stream contains the group the input belongs to 

groupZeroEvents.onValue (val) ->
    sum = 0
    $("input[data-group='0']").each (i,el) ->
      sum += Math.floor($(el).val())
    $('span#sum-g0').html(sum)

It works fine, but seems lame -- feels like I'm missing a way to use Bacon.js correctly.

jcollum
  • 43,623
  • 55
  • 191
  • 321

1 Answers1

3

The sum depends on the current value of multiple inputs. If you model these inputs as Properties, you'll come to a nicer solution:

function sum(xs) { return _.reduce(xs, (function(x,y) {return x + y}), 0); }

// array of Properties representing the value of each group-zero-element
var groupZeroValues = $("input[data-group=0]").map(function(index, elem) {
     return $(elem).asEventStream("keyup")
            .map(function(e) { return parseInt($(e.target).val()); })
            .toProperty(0)
     }).toArray();

// sum Property
var groupZeroSum = Bacon.combineAsArray(groupZeroValues).map(sum)

// assign Property value to the "text" method of the sum element
groupZeroSum.assign($("#sum-g0"), "text")

I didn't have time to actually try this, but the idea will definitely work.

Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
raimohanska
  • 3,265
  • 17
  • 28
  • Bugs noticed: jquery's map's signature is (index, elem), so you're assigning the EventStream to the wrong thing. You should parseInt() the return value, or your sum will just concatenate the numbers as strings. You must put toArray() at the end of the groupZeroValues expression or you'll get jquery-related metadata combineAsArray() won't understand. Your reduce function doesn't introduce the array to be reduced, and doesn't have an initialization value. I did, however, get this to work.... – Elf Sternberg Mar 15 '13 at 18:06