shannonmoeller-archive / mdom

Supporting vanilla DOM apis since 2014. **Unmaintained**
0 stars 0 forks source link

Chaining #1

Open shannonmoeller opened 10 years ago

shannonmoeller commented 10 years ago

mdom is basically wrappers that mimic jquery's apis around any Node or NodeList really. So:

var $ = require('jquery');
$(element).closest('.thing');

Becomes:

var closest = require('mdom/closest');
closest(element, '.thing');

The big downside to this pattern is loss of chaining. We end up back in lisp land with a bunch of close-paren soup. I don't think there's a good way to get around that if each method is supposed to return a Node or NodeList.

I wonder if we can come up with a mixin pattern.

function View(el) { this.el = el; }
View.prototype.closest = require('mdom/closest/method');

Would be a shortcut for something like:

View.prototype.closest = function(selector) {
    return new (this.constructor)(closest(this.el, selector));
};

Kind of a byo$.

shannonmoeller commented 10 years ago

This might be less error prone:

    function View(el) { this.el = el; }
    require('mdom/closest/mixin')(View);

Would be something like:

var closest = require('mdom/closest');
module.exports = function (View) {
    View.prototype.closest = function (selector) {
        return new View(closest(this.el, selector));
    };
    return View;
};
vecdeque commented 10 years ago

This is a random idea but throwing it out there.

var sequence = require('mdom/sequence')
.....

var myHardToFindElement = sequence(document.querySelector('.baseQueryClass'), [
    parents('tr'),
    siblings(':not(even)'),
    children('td')
]);

As long as each call in sequence returns a node or nodeList - it should be passed as an implied first argument to the next call.

shannonmoeller commented 10 years ago

I really like this idea. It's more consistent with the direction mtil seems to be taking where helpers are factories. Would even allow for crazy async patterns:

var q = require('q');
var get = require('mjax/get');

q(document.querySelector('[data-model]'))
    .then(first('[data-controller]'))
    .then(function(el) {
        return get(el.dataset.url);
    })
    .then(function(data) {
        return document.querySelector(data.target);
    })
    .then(container('.js-obscure-element'))
    .then(function(el) { ... });
shannonmoeller commented 10 years ago

Perhaps a bit more useful example:

Array.prototype.forEach
    .call(document.querySelectorAll('.thumbnail'), addClass('foo'));