Tuesday, May 1, 2012

Spreadsheet-like formulas on the DOM


I am looking for a way to dynamically bind formulas throughout my DOM.



We have a data intensive app, and currently I write many handlers to try and recalculate and update the appropriate cells. However, this is error-prone.



I saw something that might be capable, hashigo . However it hasn't been updated in about a year and a half.



Does anyone know of something similar that is under active development? I have been searching, but this is all I have managed to find.



Ideally I only need to setup the formula, and it will handle monitoring if fields in the formula have changed, and update the value accordingly.



EDIT: I also jQuerySheet however it is way more than I can use, I just need the formula parsing aspects of it. And it's calculation engine appears to revolve too much around cells with a column/row identifier.



EDIT2: This jQuery Calculation plugin is getting closer to what I need.



EDIT3: Ultimately, I'd love to be able to write out something as simple as




$('#output').formula(" ( SUM($('.x')) + $('#y') ) / ( funcThatReturnsValue() + 4 )");



Which would result in the value of #output being recalculated whenever a value in .x or #y changed.



However, I may would setting for something as basic as this




$('#output').formula({
formula: "(SUM(x)+y)/(j+k)",
variables: {
x: $('.x'),
y: $('#y'),
j: function() {
return 3;
},
k: 4
}
onblur: $('.x, #y')
});


Source: Tips4all

5 comments:

  1. You can use knockout.js to get the functionality you're looking for.

    Knockout.js implements an mvvm pattern in your javascript. Here is how they define MVVM:


    MVVM and View Models Model-View-View Model (MVVM) is a design pattern
    for building user interfaces. It describes how you can keep a
    potentially sophisticated UI simple by splitting it into three parts:

    A model: your application’s stored data. This data represents objects
    and operations in your business domain (e.g., bank accounts that can
    perform money transfers) and is independent of any UI. When using KO,
    you will usually make Ajax calls to some server-side code to read and
    write this stored model data.

    A view model: a pure-code representation of the data and operations on
    a UI. For example, if you’re implementing a list editor, your view
    model would be an object holding a list of items, and exposing methods
    to add and remove items.

    Note that this is not the UI itself: it doesn’t have any concept of
    buttons or display styles. It’s not the persisted data model either -
    it holds the unsaved data the user is working with. When using KO,
    your view models are pure JavaScript objects that hold no knowledge of
    HTML. Keeping the view model abstract in this way lets it stay simple,
    so you can manage more sophisticated behaviors without getting lost.

    A view: a visible, interactive UI representing the state of the view
    model. It displays information from the view model, sends commands to
    the view model (e.g., when the user clicks buttons), and updates
    whenever the state of the view model changes.

    When using KO, your view is simply your HTML document with declarative
    bindings to link it to the view model. Alternatively, you can use
    templates that generate HTML using data from your view model.


    So you'll create your "model" which includes the data in the spreadsheet, along with any functions you need to recalculate data. Then you'll have your view, which automatically updates (aka recalculates) the data as the user changes things on the page.

    http://knockoutjs.com

    ReplyDelete
  2. What you are describing sounds a lot like "Bindings" and "Computed Properties" from Sproutcore or Ember.js.

    ReplyDelete
  3. Have a look at jQuery Calculation Plug-in. But I'm not sure whether you can define any formula

    ReplyDelete
  4. You're going to want a framework like Backbone.js or Knockout



    Backbone.js

    http://documentcloud.github.com/backbone/

    Cited from Backbone:
    With Backbone, you represent your data as Models, which can be created, validated, destroyed, and saved to the server. Whenever a UI action causes an attribute of a model to change, the model triggers a "change" event; all the Views that display the model's state can be notified of the change, so that they are able to respond accordingly, re-rendering themselves with the new information. In a finished Backbone app, you don't have to write the glue code that looks into the DOM to find an element with a specific id, and update the HTML manually — when the model changes, the views simply update themselves.



    Knockout.js

    http://www.knockoutjs.com/

    Cited from Knockout JS: By encapsulating data and behavior into a view model, you get a clean, extensible foundation on which to build sophisticated UIs without getting lost in a tangle of event handlers and manual DOM updates.

    ReplyDelete
  5. You can approach the problem like this:


    by storing the vars on the DOM node you want to keep update via $('myDomElement').data('varX',data);
    by overloading the setData-method for that DOM node via
    $("myDomElement").bind("setData", function(key,value){
    setTimeout(function() { $("myDomElement").trigger("formula"); },10);
    return value;
    });
    and by finally creating your update formula like
    $('myDomElement').bind("formula",function() { this.html(foo()); });


    Woehoe, I reread your post and found you don't really specify you have vars in which you store the data ... instead you got cells ...


    in this case you could just add a changeHandler to the cells that update the formula ..


    hmmm, actually, I think I forgot what the problem was, it seems a bit too obvious what I'm supposing here ... sorry if of no help

    anyway ... I did a quick google on data binding jquery, that's where I found you can bind the setData/getData-events on $.data:
    What you might not know about jquery

    I also found this, which might or not be of interest to your spreadsheety-approach:
    using jquery.data to detect form changes

    What's more, I agree with previous answers, you could always use a framework -- personally I prefer jsmvc

    ReplyDelete