nathan-alden-sr / dom-view-js

Represents the DOM as hierarchical jQuery objects
Other
15 stars 1 forks source link

Functions In A View Get Executed On Init #5

Open earaya opened 10 years ago

earaya commented 10 years ago

On the following sample:

var view = DomView({
    selector: ".container",
    button: {
        selector: "input[type='button']",
        disable: function (view) {
            this.prop("disabled", true);
            this.attr("value", view.message()); // Calls the wrapper function, not the real function defined below
        }
    },
    message: function () { // Only called once with its return value cached for subsequent wrapper function evaluations
        return "Disabled!";
    }
});

I'm seeing disable and message get executed when the button is "inited". Is this intended behavior?

This is problematic on cases where you're trying to attache a "disable" function to your button while a form is being submitted.

nathan-alden-sr commented 10 years ago

Yes, that is expected behavior. Assigning a function for a property value means the function will be evaluated just before the DomView function returns, and its value cached for subsequent accesses.

Please see https://github.com/NathanAlden/DOMViewJS#using-custom-functions-for-property-values.

If you want to add custom functions to the resultant object, wrap them in a property with an object value, like this:

var view = DomView({
    fn: {
        theseFunctions: function() {
        },
        wontBeEvaluated: function() {
        },
        byTheDomViewFunction: function() {
        }
    }
})

view.fn.theseFunctions();
view.fn.wontBeEvaluated();
view.fn.byTheDomViewFunction();
earaya commented 10 years ago

I saw that, but I think that's rather unfortunate. It'd be nice to be able to disable a button within the context of the button. Having to wrap them in another object, makes it really akward to get a hold of the button you're trying to disable.

Does that make sense?

nathan-alden-sr commented 10 years ago

Yeah, it does. It was one of the design tradeoffs I dealt with when creating this library. Unfortunately, I couldn't find a good way to support both scenarios. I am open to suggestions, however.

I really do need to find a way to improve this. The problem with the current design is that executing custom functions usually requires starting at the top of the view rather than the current "context." In fact, there really isn't a concept of context at all. There should be.

nathan-alden-sr commented 10 years ago

At one point I experimented with passing in a context parameter to the custom function. context would be the parent object of the property whose value is the custom function. Another idea was choosing a special prefix that would prevent init-time evaluation. I didn't pursue the latter because I already use a custom _ prefix to denote jQuery event handler functions. There needs to be some way for the library to know how to treat the function.

earaya commented 10 years ago

What if you did events as an object? Something like:

events: {
  "click": "clickHandlerFunctionInView",
  "submit": "submitHandlerFunctionInView"
}

It still stinks that you'd have to functionName your functions. Maybe switch the selector functions to use the prefix?

nathan-alden-sr commented 10 years ago

I just discovered this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get. I'm not too familiar with ES5/ES6, but it seems like these getters could replace the use of explicit function properties.