I'm attempting to make a heat map binding for a chunk of numbers. So far, numbers that should be part of the associated map should be designated by context
It works up to a point.. I still have to work out the rgb algorithm a bit, but the part that is problematic at is the for loop in it within the setHeat computed function.
What I want is that whenever 'max' or 'min' is changed, i want all elements currently in the 'elements' array to update their color.
But when an element is added to the 'elements' array I just want to set the color of that element, but that requires max and min and so i dont know how to separate the calls properly so that min and max updates will call one and an element update will call the other.
Also i'm open to critiques on how to improve my binding.
<!-- ko foreach:items -->
<tr>
<td class="postCell">
<div class="ui-post-icon" data-bind="class: $parents[2].setPostIcon(post)"></div>
<span data-bind="text:post"></span>
</td>
<!-- ko foreach:combinations -->
<td data-bind="heat:{value:amount,context:'exotics'}"></td>
<!-- /ko -->
</tr>
<!-- /ko -->
ko.bindingHandlers.heat = {
init: function (element, value, allBindings, viewModel, bindingConext) {
var item = value();
var model = bindingConext.$root;
if (!model["koHeat"])
model["koHeat"] = {};
if (!model["koHeat"][item.context])
model["koHeat"][item.context] = ko.observable(new HeatContext());
var ctx = model["koHeat"][item.context];
if (!isNaN(item.value)) {
if (+item.value > ctx().max()) ctx().max(+item.value);
if (+item.value < ctx().min()) ctx().min(+item.value);
ctx().elements.push(element);
}
$(element).html(item.value).data('koHeat', item.value);
//set value
function HeatContext() {
var self = this;
this.max = ko.observable(0);
this.min = ko.observable(Number.MAX_VALUE);
this.elements = ko.observableArray([]);
this.setHeat = ko.computed(function () {
var max = self.max(),
min = self.min(),
elems = self.elements(),
mid = (max + min) / 2,
range = max - min,
r, g, b, x;
for (var i = 0; i < elems.length; i++) {
var val = $(elems[i]).data('koHeat');
x = (val - mid) / range;
if (x > 0) {
g = Math.abs(Math.round(x* 100));
b = 0.0;
r = Math.abs(Math.round((1.0 - x) * 100));
} else {
g = Math.abs(Math.round(x * 100));
b = Math.abs(Math.round((1.0 - x) * 100));
r = 0.0;
}
log(r,g,b);
$(elems[i]).css('color', "rgb(" + r + "," + g + "," + b + ")");
}
});
}
}
};
Edit I made up a quick fiddle for the situation