Fixes issues in the PR "Button widget data attributes" (#7852)

* fix: fixed ordered attributes handling and improved tests to catch event attributes

* fix: clean up code from testing

* fix: more tests and refactoring

* fix: use lowercase when checking for event attribute prefix

* fix: use lowercase when checking for event attribute prefix

* fix: changed comment wording

* fix: minor refactoring

* refactor: for brevity
This commit is contained in:
Saq Imtiaz 2023-11-22 20:57:08 +01:00 committed by GitHub
parent fb57eab2f4
commit 5ce2601c10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 23 deletions

View File

@ -104,7 +104,11 @@ TW_Element.prototype.setAttribute = function(name,value) {
if(this.isRaw) {
throw "Cannot setAttribute on a raw TW_Element";
}
this.attributes[name] = value + "";
if(name === "style") {
this.style = value;
} else {
this.attributes[name] = value + "";
}
};
TW_Element.prototype.setAttributeNS = function(namespace,name,value) {

View File

@ -415,19 +415,30 @@ Widget.prototype.getAttribute = function(name,defaultText) {
/*
Assign the common attributes of the widget to a domNode
options include:
sourcePrefix: prefix of attributes that are to be directly assigned (defaults to the emtpy string meaning all attributes)
sourcePrefix: prefix of attributes that are to be directly assigned (defaults to the empty string meaning all attributes)
destPrefix: prefix to be applied to attribute names that are to be directly assigned (defaults to the emtpy string which means no prefix is added)
changedAttributes: hashmap by attribute name of attributes to process (if missing, process all attributes)
excludeEventAttributes: ignores attributes whose name would begin with "on"
*/
Widget.prototype.assignAttributes = function(domNode,options) {
var self = this;
options = options || {};
var changedAttributes = options.changedAttributes || this.attributes;
var sourcePrefix = options.sourcePrefix || "";
var destPrefix = options.destPrefix || "";
var EVENT_ATTRIBUTE_PREFIX = "on";
var self = this,
changedAttributes = options.changedAttributes || this.attributes,
sourcePrefix = options.sourcePrefix || "",
destPrefix = options.destPrefix || "",
EVENT_ATTRIBUTE_PREFIX = "on";
var assignAttribute = function(name,value) {
// Process any style attributes before considering sourcePrefix and destPrefix
if(name.substr(0,6) === "style." && name.length > 6) {
domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value;
return;
}
// Check if the sourcePrefix is a match
if(name.substr(0,sourcePrefix.length) === sourcePrefix) {
name = destPrefix + name.substr(sourcePrefix.length);
} else {
value = undefined;
}
// Check for excluded attribute names
if(options.excludeEventAttributes && name.substr(0,2).toLowerCase() === EVENT_ATTRIBUTE_PREFIX) {
value = undefined;
@ -445,17 +456,20 @@ Widget.prototype.assignAttributes = function(domNode,options) {
} catch(e) {
}
}
};
// If the parse tree node has the orderedAttributes property then use that order
if(this.parseTreeNode.orderedAttributes) {
$tw.utils.each(this.parseTreeNode.orderedAttributes,function(attribute,index) {
if(attribute.name in changedAttributes) {
assignAttribute(attribute.name,self.getAttribute(attribute.name));
}
});
// Otherwise update each changed attribute irrespective of order
} else {
$tw.utils.each(changedAttributes,function(value,name) {
assignAttribute(name,self.getAttribute(name));
});
}
$tw.utils.each(changedAttributes,function(value,name) {
value = self.getAttribute(name);
// Check for a prefixed attribute
if(name.substr(0,sourcePrefix.length) === sourcePrefix) {
domNode.setAttribute(destPrefix + name.substr(sourcePrefix.length),value);
// Check for a style attribute
} else if(name.substr(0,6) === "style." && name.length > 6) {
domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value;
}
});
};
/*

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$button tag="div" class="myclass" data-title="mytiddler" style.color="red">
<$button tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked">
my tiddler
</$button>
<$button tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}>

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$checkbox tag="done" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> Is it done?</$checkbox>
<$checkbox tag="done" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked"> Is it done?</$checkbox>
+
title: Actions

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$draggable tag="div" class="myclass" data-title="mytiddler" style.color="red">
<$draggable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked">
my tiddler
</$draggable>
<$draggable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}>

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$droppable tag="div" class="myclass" data-title="mytiddler" style.color="red">
<$droppable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked">
my tiddler
</$droppable>
<$droppable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}>

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$link data-id="mytiddler" style.color="red" to="Temp">
<$link data-id="mytiddler" style.color="red" to="Temp" onclick="clicked">
link to Temp
</$link>
<$link tag="button" data-id={{Temp}} style.color={{{ [[Temp]get[color]] }}} to="SomeTiddler">

View File

@ -0,0 +1,15 @@
title: Widgets/DataAttributes/OrderedStyleAttributes
description: Ordered style attributes
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<div style="background:red;color:blue;" style.background="green">
hello
</div>
+
title: ExpectedResult
<p><div style="background:green;color:blue;">hello</div></p>

View File

@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$select tiddler='New Tiddler' field='text' default='Choose a new text' data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}>
<$select tiddler='New Tiddler' field='text' default='Choose a new text' data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked">
<option disabled>Choose a new text</option>
<option>A Tale of Two Cities</option>
<option>A New Kind of Science</option>

View File

@ -0,0 +1,15 @@
title: Widgets/ElementWidgetEventAttributes
description: Element widget should not support event attributes starting with "on"
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<div class="hello" onclick="clicked">
TiddlyWiki
</div>
+
title: ExpectedResult
<p><div class="hello">TiddlyWiki</div></p>

View File

@ -0,0 +1,15 @@
title: Widgets/ElementWidgetStyleAttributes
description: Element widget should support style.* attributes
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<div class="hello" onclick="clicked" style.color="blue" style.color="red" style.background="yellow">
TiddlyWiki
</div>
+
title: ExpectedResult
<p><div class="hello" style="color:red;background:yellow;">TiddlyWiki</div></p>