New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attributes event API #637

Closed
justinbmeyer opened this Issue Jan 2, 2014 · 1 comment

Comments

Projects
None yet
2 participants
@justinbmeyer
Contributor

justinbmeyer commented Jan 2, 2014

For 2.1, I want to add the ability to listen to attributes changing. This will be useful for a variety of purposes. The most important of which will be allowing attribute changes to be reflected in a can.Component. Consider something like:

can.Component.extend({
  tag: "my-message",
  scope: {
    title: "@"
  }
})

That controls an element like:

<my-message title="Welcome">{{title}}</my-message>

If I change title like:

$("my-message").attr("title","Goodbye")

I'd expect the html content of my-message to change.

Furthermore, a template like:

<my-message title="{{message}}">{{title}}</my-message>

Rendered like:

template({
  message: can.compute("Hi there")
})

... should work.

To accomplish this, changes in can.Component are needed, but some low-level event attribute event binding is needed. For this API, I propose an attributes event that one can listen to like:

$(el).bind("attributes", function(ev){
  ev.type // attributes
  ev.attributeName // changed attribute
  ev.oldValue // previous value of the attribute
  ev.target // element who's element changed
})

This reflects the mutation observer API a bit:

  • you configure attributes: true
  • a mutation record has the same properties (and values).

However, it works with event binding instead of calling observe on some Constructor. This will make it possible to write:

events: {
  "attributes": function(el, ev){

  }
}

Some important considerations:

  • these events do not bubble
  • these events are dispatched asynchronously

The asynchronous dispatching is likely the most important change. This was done so we can use MutationObserver in browsers that support it to dispatch events on the element. This will make changing attributes much faster in those browsers.

To get this working in browsers that do not support it, I'm overwriting their set and remove attribute's method (Ex: $.attr and $.removeAttr) and if there is a change, dispatching an "attributes" event with setImmediate.

You can see this work here:

https://github.com/bitovi/canjs/blob/observe-attributes/util/attr/attr.js
https://github.com/bitovi/canjs/blob/observe-attributes/util/jquery/jquery.js#L165

@matthewp

This comment has been minimized.

Show comment
Hide comment
@matthewp

matthewp Apr 1, 2014

Contributor

This has already been fixed, close @daffl ?

Contributor

matthewp commented Apr 1, 2014

This has already been fixed, close @daffl ?

@matthewp matthewp closed this Apr 2, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment