JSFiddle - React, Tailwind, and code Playground

by mistakster

HTML

<script src="http://pozadi.github.io/kefir/dist/kefir.js"></script>
	<table id="table">
		<tr>
			<td><input class="val"></td>
			<td><input class="pct">%</td>
		</tr>
		<tr>
			<td><input class="val"></td>
			<td><input class="pct">%</td>
		</tr>
		<tr>
			<td><input class="val"></td>
			<td><input class="pct">%</td>
		</tr>
		<tr>
			<td><input class="val"></td>
			<td><input class="pct">%</td>
		</tr>
		<tr>
			<td><input class="sum"></td>
			<td><input readonly value="100">%</td>
		</tr>
	</table>

JavaScript

$(function () {

	var $table = $('#table');

	var streamVal = Kefir.fromBinder(function (emitter) {
		function handler() {
			var values = $.map($table.find('.val'), function (ele) {
				return $(ele).val();
			});
			emitter.emit(values);
		}
		$table.on('change', '.val', handler);
		return function () {
			$table.off('change', '.val', handler);
		};
	});

	var streamPct = Kefir.fromBinder(function (emitter) {
		function handler() {
			var $input = $(this);
			var $row = $input.closest('tr');
			var i = $table.find('tr').index($row);
			emitter.emit({
				pct: $input.val(),
				index: i
			});
		}
		$table.on('change', '.pct', handler);
		return function () {
			$table.off('change', '.pct', handler);
		};
	});

	var streamSum = Kefir.fromBinder(function (emitter) {
		function handler() {
			emitter.emit($table.find('.sum').val());
		}
		$table.on('change', '.sum', handler);
		return function () {
			$table.off('change', '.sum', handler);
		};
	});


	streamSum.onValue(function (sum) {
		sum = parseFloat(sum);

		if (isNaN(sum)) {
			return;
		}

		// compute values
		$table.find('.pct').each(function (i) {
			var pct = parseFloat($(this).val());
			$table.find('.val').eq(i)
                .val(isNaN(pct) ? '' : (sum * pct / 100));
		});
	});


	streamVal.onValue(function (values) {
		// compute sum
		var sum = values.reduce(function (memo, v) {
			v = parseFloat(v);
			return memo + (isNaN(v) ? 0 : v)
		}, 0);
		$table.find('.sum').val(sum);

		// compute percentage
		values.forEach(function (v, i) {
			v = parseFloat(v);
			$table.find('.pct').eq(i)
                .val(isNaN(v) ? '' : (100 * v / sum));
		});

	});


	streamPct.onValue(function (data) {
		var $pct = $table.find('.pct');
		var $val = $table.find('.val');

		var other = $
			.map($pct, function (ele, i) {
				return {
					pct: $(ele).val(),
					index: i
				}
			})
			.filter(function (d) {
				return d.index != data.index
			});

		var otherSum = other.reduce(function (memo, v) {
		    v =...