-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Added HTML support for Button labels #1163
Conversation
… label ATTR to non-HTML.
…of its host node.
@@ -68,7 +72,7 @@ Y.extend(Button, Y.Widget, { | |||
*/ | |||
bindUI: function() { | |||
var button = this; | |||
button.after('labelChange', button._afterLabelChange); | |||
button.after('labelHTMLChange', button._afterLabelHTMLChange); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean this change will break backwards compatibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bindUI
is actually being removed from Y.Button
as I believe it is no longer necessary now with the proper setters in place.
FWIW, an intent of this pull request is to not break backwards compat in Button. I'm only introducing new features, as well as fixes to meet expected behavior.
What happens when the |
* IMPORTANT: Sanitize all input passed into this attribute | ||
* | ||
* @attribute labelHTML | ||
* @type {HTML|String} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If labelHTML
is always treated as HTML, then its type should be just HTML
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next push
@ericf The provided text string is applied to the So, with your provided HTML, executing this:
I just reviewed some of this behavior with @msweeney. He suggested some additional documentation to clarify that if you are dealing with an |
* @method _uiSetLabel | ||
* @method _getLabel | ||
* @description Getter for a button's 'label' ATTR | ||
* @return {String} The label for a given node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since _getLabelFromNode()
might return unsanitized HTML, this method must also be considered unsafe until _getLabelFromNode()
is updated to always return something safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See: #1163 (comment)
…y removing most of the now unneccesary prototype properties. * `Y.Button.ATTRS` now points to `Y.ButtonCore.ATTRS` * Improved code documentation
As a result of an investigation into one of @rgrove's questions, I was able to fix the issue where P.S. All hidden diff comments have either been addressed, or are still a WIP. |
* user provided content, appropriate sanitization steps should first be | ||
* conducted to ensure the content is safe for insertion into the DOM. | ||
* This process typically involves removing any <script> or | ||
* <iframe> tags, or other HTML that can be considered malicious. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't actually good advice, since it implies that blacklist-based tag filtering is a good approach, and also assumes that sanitization (rather than escaping) is the way to go, which is very rarely true in client-side JS.
This comment should just advocate escaping (using Y.Escape.html()
) and leave it at that. Actual HTML sanitization is way out of scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid clobbering the diff discussion with another commit, how about this instead?
/**
* The HTML of the button's label
*
* **IMPORTANT**
* This attribute accepts HTML and inserts it into the DOM **without**
* sanitization. This attribute should only be used with HTML that has
* either been escaped (using `Y.Escape.html`), or sanitized according to
* the requirements of your application.
*
* If all you need is support for text labels, please use the `label`
* attribute instead.
*
* @attribute labelHTML
* @type HTML
*/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Feel free to omit the "IMPORTANT" though. That might be taking it too far. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed update.
tagName = labelNode.get('tagName').toLowerCase(), | ||
label = labelNode.get(tagName === 'input' ? 'value' : 'text'); | ||
|
||
label = Y.Escape.html(label); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rgrove This escape was added to address this comment, though due to this getter now only returning a String and not mixed HTML|String, I believe the escapement is no longer necessary. Can you confirm and I'll remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed, but happy to add it back if neccesary.
I reviewed all the outdated diffs and believe all questions/issues have been addressed. Let me know if there's anything I missed. |
Looks good to me. Thanks @derek. 👍 |
* @public | ||
*/ | ||
getNode: function() { | ||
if (!this._host && this instanceof Y.Widget) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instanceof
will fail across YUI instances. Duck-typing would be more robust in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rethinking that line, checking if this
is an instance of Y.Widget is a little over-cautious. ButtonCore inherits from AttributeCore, so it will always have a get
method, so falling into the condition can't result in a script error. If the instance is a Widget, get('boundingBox')
will return the node, if not, it will return undefined
, which was already the value of this._host
going into the branch. Update coming.
@derek This should have tests for What is the coverage for the button modules? And what browsers was this tested in? |
Button has 100% coverage (S, B, F, & L) and tested browsers are noted in the PR description. But another round of testing will be done, assuming additional tests are added and code changes occur. |
@derek I added line comments earlier today as well… |
… the `disabled` ATTR instead of the node's attribute property.
After the additional commit
|
There are existing tests for The reason there are no unit tests addressing |
Currently
Y.Button
widgets do not support HTML labels. This is an issue because is isn't uncommon to use nested HTML structures inside of a<button>
element. For example...To fix this issue, this pull request introduces a
labelHTML
ATTR, and relegates thelabel
ATTR as secure sugar aroundlabelHTML
.A separate attribute is required for the following reasons:
label
ATTRAdditional notes
@config
instead of@attribute
in ButtonCore documentation because@attribute
will include theChange
events to the API documentation, which ButtonCore (derived from AttributeCore) does not fire.Test Results