Determining if an attribute is valid in standard HTML (or SVG)

I want to programmatically add attributes to DOM elements (e.g. HTML or SVG elements) dynamically at runtime, i.e. based on user input. If the attribute is standard, I will use the name as is, but if it is not, that is, if it requires conversion to a user attribute, then I want to add the prefix "data-" to it.

So, is there a way to determine if a string represents a "standard / normal" DOM ​​attribute?

For example, let's say I have an SVG rectangle as follows:

<rect x="10" y="10" width="80" height="40" stroke="black"/>

Please note that the fill color is not specified (yet).

The user requests the addition of two attributes:

  • attribute with the name "fill" with the value "red", which should give fill="red"(note the absence of a prefix)
  • attribute with the name "price" with the value "expensive", which should give data-price="expensive"(note the prefix data-)

How can I dynamically distinguish between the two? The attribute is fillmissing from my current DOM element, so I cannot check if a pre-existing value exists for the attribute of this name. I also do not believe that I can even check if an error occurs if I create an attribute without a prefix, because, as far as I can tell, at least my current browser (Chrome v61.0) will allow me to add an attribute price="expensive"(without a prefix data-), although this is not the best practice.

I need something like the following:

const elementNodeName = "rect";
const attributeName = "height"; // or, e.g. "price"
const nameIsValid = testAttributeNameValidity(elementNodeName, attributeName);
if (!nameIsValid) attributeName = 'data-' + attributeName;

- testAttributeNameValidity -type?

javascript, Javascript.

** : SO HTML, SVG **

attributeName in document.createElement(elementNodeName), true false . "id" HTML- (<p>), .

, SVG. createElement createElementNS, , , . . . : testHtmlAttributeNameValidity testSvgAttributeNameValidity. , , HTML, .. id="someId" data-price="expensive". SVG : data-fill="yellow" data-price="expensive".

, Chrome v61.

:

const testHtmlAttributeNameValidity = (elementNodeName, attributeName) => {
  return (attributeName in document.createElement(elementNodeName));
};

const testHtmlAttributeName = (attributeName, attributeValue) => {
  const elementNodeName = "p";
  const nameIsValid = testHtmlAttributeNameValidity(elementNodeName, attributeName);
  if (!nameIsValid) attributeName = 'data-' + attributeName;
  const element = document.querySelector(elementNodeName);
  element.setAttribute(attributeName, attributeValue);
};

testHtmlAttributeName("id", "someId");
testHtmlAttributeName("price", "expensive");

console.log(document.querySelector('div').innerHTML);


const svgNS = "http://www.w3.org/2000/svg";

const testSvgAttributeNameValidity = (elementNodeName, attributeName) => {
  return (attributeName in document.createElementNS(svgNS, elementNodeName));
};

const testSvgAttributeName = (attributeName, attributeValue) => {
  const elementNodeName = "rect";
  const nameIsValid = testSvgAttributeNameValidity(elementNodeName, attributeName);
  if (!nameIsValid) attributeName = 'data-' + attributeName;
  const element = document.querySelector(elementNodeName);
  element.setAttribute(attributeName, attributeValue);
};

testSvgAttributeName("fill", "yellow");
testSvgAttributeName("price", "expensive");

console.log(document.querySelector('svg').innerHTML);
#someId {
  color: green;
}
<svg height="55">
  <rect x="10" y="10" width="80" height="40" stroke="red"/>
</svg>

<div>
<p>Hello world</p>
</div>
Hide result

, .

0
1

@ccprog . , SVG DOM OR'd, , .style.

, HTML DOM :

// correct for HTML:
return (
  attributeName in document.createElement(elementNodeName)
);

SVG DOM. , , "id", , "fill":

// insufficient for SVG, i.e. only partially correct:
return (
  attributeName in document.createElementNS(svgNS, elementNodeName)
);

.style :

// correct for SVG:
return (
  attributeName in document.createElementNS(svgNS, elementNodeName).style ||
  attributeName in document.createElementNS(svgNS, elementNodeName)
);

, , . , , "-". , , HTML DOM SVG DOM -.

const testHtmlAttributeNameValidity = (elementNodeName, attributeName) => {
  return (attributeName in document.createElement(elementNodeName));
  return (
    attributeName in document.createElement(elementNodeName)
  );
};

const testHtmlAttributeName = (attributeName, attributeValue) => {
  const elementNodeName = "p";
  const nameIsValid = testHtmlAttributeNameValidity(elementNodeName, attributeName);
  if (!nameIsValid) attributeName = 'data-' + attributeName;
  const element = document.querySelector(elementNodeName);
  element.setAttribute(attributeName, attributeValue);
};

testHtmlAttributeName("id", "someHtmlId");
  // This should result in "id" attribute being changed, changing the
  // font color to green.

testHtmlAttributeName("color", "orange");
  // While "color" IS a CSS property name, it is NOT an HTML DOM element
  // attribute name. Therefore, this test should result in "color" NOT being
  // recognized as a valid attribute name, resulting in the
  // custom attribute name "data-color", with no effect on the
  // actual styling of the element, i.e. this test should NOT
  // turn the text orange. This test is included here
  // to provide a contrast to what should happen with SVG DOM
  // element style-like attributes like "fill", as shown below
  // in the section testing SVG DOM element attribute names.

testHtmlAttributeName("price", "expensive");
  // This should result in a new attribute with the name "data-price"
  // and the value "expensive".

console.log(document.querySelector('div').innerHTML);


const svgNS = "http://www.w3.org/2000/svg";

const testSvgAttributeNameValidity = (elementNodeName, attributeName) => {
  return ( // ********** THIS IS THE IMPORTANT CHANGE **********
    attributeName in document.createElementNS(svgNS, elementNodeName).style ||
    attributeName in document.createElementNS(svgNS, elementNodeName)
  );
};

const testSvgAttributeName = (attributeName, attributeValue) => {
  const elementNodeName = "rect";
  const nameIsValid = testSvgAttributeNameValidity(elementNodeName, attributeName);
  if (!nameIsValid) attributeName = 'data-' + attributeName;
  const element = document.querySelector(elementNodeName);
  element.setAttribute(attributeName, attributeValue);
};

testSvgAttributeName("id", "someSvgId");
testSvgAttributeName("fill", "yellow"); // *** Now correctly identified as valid
testSvgAttributeName("price", "expensive");

console.log(document.querySelector('svg').innerHTML);
#someHtmlId {
  color: green;
}
#someSvgId {
  stroke-width: 5px;
}
<svg height="55">
  <rect x="10" y="10" width="80" height="40" stroke="red"/>
</svg>

<div>
<p>Hello world</p>
</div>
Hide result
0

Source: https://habr.com/ru/post/1614863/


All Articles