Skip to content
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

Add support for new elements in event-valuechange #1184

Merged
merged 6 commits into from
Sep 16, 2013
Merged

Add support for new elements in event-valuechange #1184

merged 6 commits into from
Sep 16, 2013

Conversation

clarle
Copy link
Collaborator

@clarle clarle commented Sep 11, 2013

As discussed in #1157:

This PR adds support for two groups of new elements for event-valuechange, <select> elements with <option> choices, and any element with the [contenteditable="true"] attribute.

The <select> elements work nearly the same way as <input> and <textarea>, which basically checks their value attribute for any change. There are some performance cheats involved in the polling loop to improve performance on IE6 without having to resort to using node.get('value'), and have been fully tested.

The [contenteditable="true"] (or [contenteditable=""]) elements act differently, and fires a change when their innerHTML property changes. For now, there isn't support for elements that inherit contenteditable from a parent element. It's something I could add, but I'm worried about the performance hit on having to search up the DOM tree to check whether or not the element has a parent node that has [contenteditable="true"]. If that's something that might be useful, though, let me know, and I'll see if I can find an efficient way to do that.

This was tested on all A-grade browsers (including IE6) and passes all unit tests and manual tests for each one. There were no performance hits even after adding the new functionality in.

The goal for this enhancement is mainly so that we can use the valuechange event to efficiently detect form element changes when implementing two-way data-binding later on.

Clarence Leung added 3 commits September 10, 2013 17:12
* Tests for subscriber and delegation on <select> elements
* Tests for subscriber and delegation on [contenteditable="true"]
  elements.
* Supports <select> elements with different <option> choices
* Supports all elements with [contenteditable="true"]

Maintains performance by accessing raw DOM properties (that
are supported in all browsers).
* Added tests for <select> elements with <option> choices
* Added tests for [contenteditable="true"] elements
@@ -96,6 +97,16 @@ VC = {

prevVal = vcData.prevVal;

if (VC._isEditable(node)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be necessary to check _isEditable() each time you poll. If you just cache the check in _startPolling(), that should be sufficient.

* Caches `tagName` and `isEditable` inside of the node
* Uses `tagName` to determine how to extract the `newVal`
* Replaces all `getHTML` instances with `innerHTML`
@clarle
Copy link
Collaborator Author

clarle commented Sep 12, 2013

@rgrove I made the caching improvements that you suggested by adding tagName and isEditable into vcData, and replaced all instance of node.getHTML() with just innerHTML.

I'm still thinking about what the best way is to handle the last case that you suggested.

// Back-compatibility with IE6 <select> element values.
// Huge performance cheat to get past node.get('value').
selectedOption = domNode.options[domNode.selectedIndex];
newVal = selectedOption.value || selectedOption.text;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here if selectedOption.value is an empty string? Does selectedOption.text return a string on all browsers? If not, this could end up setting newVal to undefined, which wouldn't be good.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if you have no value, and no text inside of an option, like this:

<select>
  <option></option>
</select>

selectedOption.text will return an empty string ('') on all A-grade browsers. I'm looking for the spec to prove it, but this was manually tested too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, sounds good then!

@rgrove
Copy link
Contributor

rgrove commented Sep 12, 2013

Don't forget to update the user guide (and you might want to add a caveat about elements that are added/removed/changed after a delegated listener is attached), but after that: 👍

Thanks @clarle!

var domNode = node._node, // performance cheat; getValue() is a big hit when polling
event = options.e,
vcData = node._data && node._data[DATA_KEY], // another perf cheat
tagName = vcData.tagName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that it really matters, but I'd probably use nodeName here instead. Why? nodeName is actually part of the DOM Level 3 standard (http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-F68D095), where as tagName isn't.

Clarence Leung added 2 commits September 16, 2013 15:30
* Used standards-based `nodeName` instead of `tagName`
* Used better boolean statement in `_poll`
@ericf
Copy link
Member

ericf commented Sep 25, 2013

Sweet! I'm glad this landed. @apipkin can you take advantage of the contenteditable support now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants