Added object list to layers panel (#466)

Co-authored-by: Timo Dittmann <timo.dittmann@kaufland.com>
master
Timo Dittmann 2021-01-16 13:34:25 +01:00 committed by GitHub
parent ded5e11e80
commit c0f55416a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 186 additions and 23 deletions

View File

@ -146,6 +146,14 @@ class Layer {
}
}
/**
* Returns all children of this layer.
* @returns {NodeListOf<ChildNode>} The children of this layer.
*/
getChildren () {
return this.group_.childNodes;
}
/**
* @returns {SVGTitleElement|null}
*/

View File

@ -961,6 +961,12 @@
</svg>
</g>
<g id="object_select">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<ellipse cx="12" cy="11.9875" fill="#000000" fill-opacity="0" id="svg_2" rx="9.33333" ry="9.33333" stroke="#000000" stroke-width="3"/>
</svg>
</g>
<g id="no_color">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<line fill="none" stroke="#d40000" id="svg_90" y2="24" x2="24" y1="0" x1="0"/>

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -65,6 +65,16 @@
<td class="layername">Layer 1</td>
</tr>
</table>
<h3>Objects</h3>
<table id="objectlist">
<tr class="object">
<td class="objectvis"></td>
<td class="objectname">Object 1</td>
<td class="objectselect"></td>
</tr>
</table>
<span id="selLayerLabel">Move elements to:</span>
<select id="selLayerNames" title="Move selected elements to a different layer" disabled="disabled">
<option selected="selected" value="layer1">Layer 1</option>

View File

@ -273,7 +273,8 @@ select {
cursor: pointer;
}
#layerlist {
#layerlist,
#objectlist {
margin: 1px;
padding: 0;
width: 127px;
@ -282,45 +283,63 @@ select {
background-color: #FFFFFF;
}
#layerlist tr.layer {
#layerlist tr.layer,
#objectlist tr.object {
background-color: #FFFFFF;
margin: 0;
padding: 0;
}
#layerlist tr.layersel {
#layerlist tr.layersel,
#objectlist tr.objectsel {
border: 1px solid #808080;
background-color: #CCCCCC;
}
#layerlist td.layervis {
#layerlist td.layervis,
#objectlist td.objectvis,
#objectlist td.objectselect {
width: 22px;
cursor: pointer;
}
#layerlist td.layerinvis {
#objectlist td.objectselect {
text-align: center;
}
#layerlist td.layerinvis,
#objectlist td.objectinvis {
background-image: none;
cursor: pointer;
}
#layerlist td.layervis * {
#layerlist td.layervis *,
#objectlist td.objectvis * {
display: block;
}
#layerlist td.layerinvis * {
#layerlist td.layerinvis *,
#objectlist td.objectinvis * {
display: none;
}
#layerlist td.layername {
#layerlist td.layername,
#objectlist td.objectname {
cursor: pointer;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 1px;
}
#layerlist td.layername:hover {
#layerlist td.layername:hover,
#objectlist td.objectname:hover {
color: blue;
font-style: italic;
}
#layerlist tr.layersel td.layername {
#layerlist tr.layersel td.layername,
#objectlist tr.objectsel td.objectname {
font-weight: bold;
}

View File

@ -1184,6 +1184,8 @@ editor.init = () => {
'#layer_down': 'go_down',
'#layer_moreopts': 'context_menu',
'#layerlist td.layervis': 'eye',
'#objectlist td.objectvis': 'eye',
'#objectlist td.objectselect': 'object_select',
'#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok',
'#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel',
@ -1207,7 +1209,7 @@ editor.init = () => {
resize: {
'#logo .svg_icon': 28,
'.flyout_arrow_horiz .svg_icon': 5,
'.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14,
'.layer_button .svg_icon, #layerlist td.layervis .svg_icon, #objectlist .svg_icon': 14,
'.dropdown button .svg_icon': 7,
'#main_button .dropdown .svg_icon': 9,
'.palette_item:first .svg_icon': 15,
@ -1405,6 +1407,7 @@ editor.init = () => {
$('#layerlist tr.layer').removeClass('layersel');
$(this.parentNode).addClass('layersel');
svgCanvas.setCurrentLayer(this.textContent);
populateObjects();
evt.preventDefault();
})
.mouseover(function () {
@ -1429,6 +1432,66 @@ editor.init = () => {
}
};
const populateObjects = function () {
const objectlist = $('#objectlist tbody').empty();
const eyeIcon = $.getSvgIcon('eye');
const selectIcon = $.getSvgIcon('object_select');
const selectedElementId = selectedElement ? selectedElement.id : null;
const drawing = svgCanvas.getCurrentDrawing();
const currentElements = drawing.getCurrentLayerChildren();
for (const currentElement of currentElements) {
const elementId = currentElement.id;
const objectTr = $('<tr class="object">').toggleClass('objectsel', elementId === selectedElementId);
const objectVis = $('<td class="objectvis">').toggleClass('objectinvis', !drawing.isLayerChildrenVisible(elementId));
const objectName = $('<td class="objectname" title="' + elementId + '">' + elementId + '</td>');
const objectSelect = $('<td class="objectselect">');
objectlist.append(objectTr.append(objectVis, objectName, objectSelect));
}
if (eyeIcon !== undefined) {
const copy = eyeIcon.clone();
$('td.objectvis', objectlist).append(copy);
$.resizeSvgIcons({'td.objectvis .svg_icon': 14});
}
if (selectIcon !== undefined) {
const copy = selectIcon.clone();
$('td.objectselect', objectlist).append(copy);
$.resizeSvgIcons({'td.objectselect .svg_icon': 8});
}
// Change visibility of object
$('#objectlist td.objectvis').click(function () {
const row = $(this.parentNode).prevAll().length;
const id = $('#objectlist tr.object:eq(' + row + ') td.objectname').text();
const vis = $(this).hasClass('objectinvis');
drawing.setLayerChildrenVisible(id, vis);
$(this).toggleClass('objectinvis');
if (!vis) svgCanvas.clearSelection();
});
// Handle selection of object
$('#objectlist td.objectselect').click(function () {
$('#objectlist tr.object').removeClass('objectsel');
const row = $(this.parentNode).prevAll().length;
const vis = $('#objectlist tr.object:eq(' + row + ') td.objectvis').hasClass('objectinvis');
if (!vis) {
const id = $('#objectlist tr.object:eq(' + row + ') td.objectname').text();
svgCanvas.clearSelection();
svgCanvas.addToSelection([$('[id="' + id + '"]')[0]], true);
$(this).parent().toggleClass('objectsel');
}
});
// if there were too few rows, let's add a few to make it not so lonely
let num = 5 - $('#objectlist tr.object').size();
while (num-- > 0) {
objectlist.append('<tr><td style="color:white">_</td><td/><td/></tr>');
}
};
let editingsource = false;
let origSource = '';
@ -2386,6 +2449,7 @@ editor.init = () => {
// Deal with pathedit mode
togglePathEditMode(isNode, elems);
updateContextPanel();
populateObjects();
svgCanvas.runExtensions('selectedChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_selectedChanged} */ {
elems,
selectedElement,
@ -5281,6 +5345,7 @@ editor.init = () => {
});
populateLayers();
populateObjects();
// function changeResolution (x,y) {
// const {zoom} = svgCanvas.getResolution();

View File

@ -340,6 +340,29 @@ export class Drawing {
return finalName;
}
/**
* Returns all objects of the currently selected layer. If an error occurs, an empty array is returned.
* @returns {SVGGElement[] | any[]} The objects of the currently active layer (or an empty array if no objects found).
*/
getCurrentLayerChildren () {
return this.current_layer
? [...this.current_layer.getChildren()].filter((object) => { return object.tagName !== 'title'; })
: [];
}
/**
* Returns the object at the current layer with the given 'objectId'. If none is found 'null' is returned.
* @param {string} objectId The id of the object
* @returns {?SVGGElement} The found object or 'null' if none is found.
*/
getCurrentLayerChild (objectId) {
const foundElements = this.getCurrentLayerChildren()
.filter((obj) => { return obj.id === objectId; });
if (!foundElements) { return null; }
return foundElements[0];
}
/**
* Set the current layer's position.
* @param {Integer} newpos - The zero-based index of the new position of the layer. Range should be 0 to layers-1
@ -630,6 +653,38 @@ export class Drawing {
return layer.getGroup();
}
/**
* Sets the visibility of the object. If the object id is not valid, this
* function returns `null`, otherwise it returns the `SVGElement` representing
* the object. This is an undo-able action.
* @param {string} objectId - The id of the object to change the visibility
* @param {boolean} bVisible - Whether the object should be visible
* @returns {?SVGGElement} The SVGGElement representing the object if the
* `objectId` was valid, otherwise `null`.
*/
setLayerChildrenVisible (objectId, bVisible) {
if (typeof bVisible !== 'boolean') {
return null;
}
const element = this.getCurrentLayerChild(objectId);
const expected = bVisible ? 'inline' : 'none';
const oldDisplay = element.getAttribute('display');
if (oldDisplay !== expected) {
element.setAttribute('display', expected);
}
return element;
}
/**
* Returns whether the object with the given id is visible or not.
* @param {string} objectId - id of the object on which to get the visibility.
* @returns {false|boolean} The visibility of the object, or `false` if the objects id was invalid.
*/
isLayerChildrenVisible (objectId) {
const element = this.getCurrentLayerChild(objectId);
return element.getAttribute('display') !== 'none';
}
/**
* Returns the opacity of the given layer. If the input name is not a layer, `null` is returned.
* @param {string} layerName - name of the layer on which to get the opacity

View File

@ -21,38 +21,38 @@ const REVERSE_NS = getReverseNS();
/* eslint-disable max-len */
const svgWhiteList_ = {
// SVG Elements
a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],
circle: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title', 'display'],
circle: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'display'],
clipPath: ['class', 'clipPathUnits', 'id'],
defs: [],
style: ['type'],
desc: [],
ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'display'],
feGaussianBlur: ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
feMorphology: ['class', 'in', 'operator', 'radius'],
filter: ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
foreignObject: ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],
g: ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
image: ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],
line: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],
image: ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y', 'display'],
line: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2', 'display'],
linearGradient: ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],
marker: ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
mask: ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
metadata: ['class', 'id'],
path: ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
path: ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'display'],
pattern: ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],
polygon: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
polyline: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
polygon: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'display'],
polyline: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'display'],
radialGradient: ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],
rect: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],
rect: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y', 'display'],
stop: ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],
svg: ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],
switch: ['class', 'id', 'requiredFeatures', 'systemLanguage'],
symbol: ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],
text: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],
textPath: ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
text: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y', 'display'],
textPath: ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href', 'display'],
title: [],
tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],
tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y', 'display'],
use: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],
// MathML Elements