确定标准HTML(或SVG)中的属性是否有效 [英] Determining whether an attribute is valid in standard HTML (or SVG)

查看:80
本文介绍了确定标准HTML(或SVG)中的属性是否有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望以编程方式在运行时动态地(即基于用户输入)向DOM元素(例如HTML或SVG元素)添加属性。如果属性是标准属性,我将按原样使用该名称,但如果属性不是,即需要转换为自定义属性,那么我想为其添加数据前缀。



那么,有没有一种方法可以确定一个字符串是否代表一个标准/普通DOM属性?

例如,假设我有一个SVG矩形,如下所示:

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

请注意,填充颜色尚未指定。



用户请求添加两个属性:


  • 名为fill的属性值为red,应该(注意缺少一个前缀)
  • 一个名为price的属性,其值为expensive ,应该产生 data-price =expensive(注意 data - 前缀)



我如何动态区分这两个? fill 属性在我当前的DOM元素中不存在,因此我无法检查该名称的属性是否存在预先存在的值。我也不相信如果我创建没有前缀的属性,我甚至不会检查是否引发错误,因为据我所知,至少我目前的浏览器(Chrome v61.0)将允许我添加属性 price =expensive(没有 data - 前缀),尽管这不是最佳做法。



我想要类似下面的内容:

  const elementNodeName =rect; 
const attributeName =height; //或例如price
const nameIsValid = testAttributeNameValidity(elementNodeName,attributeName);
if(!nameIsValid)attributeName ='data-'+ attributeName;

是否有预先存在的 testAttributeNameValidity - 是否有类型的功能?



当我正在寻找Javascript解决方案时,我用 javascript 标记了这个功能。

更新:解决方案来自其他SO解决方案,但不支持SVG ** b 基于< a href =https://stackoverflow.com/questions/33584700/how-to-check-if-dom-element-and-or-attribute-is-valid>建议的评论链接,我尝试在document.createElement(elementNodeName)中使用 attributeName,它应该返回 true 作为有效的属性名称, false 为无效的。当我为HTML元素(< p> )使用有效的属性名称id时,这种方法就可行。



相反,我仍然没有在SVG中使用这种方法。我尝试将 createElement 转换为 createElementNS ,但仍然无法解决问题。看到我的测试代码如下。测试代码中的关键功能是 testHtmlAttributeNameValidity testSvgAttributeNameValidity 。如果您运行代码并检查控制台中的输出,它将显示它适用于HTML,即它会生成 id =someIddata-price =expensive 。但是,对于SVG,它只会产生不需要的输出: data-fill =yellowdata-price =expensive



测试代码:



如果它有所不同,我正在使用Chrome v61。

  const testHtmlAttributeNameValidity =(elementNodeName,attributeName)=> {return(document.createElement(elementNodeName)中的attributeName);}; const testHtmlAttributeName =(attributeName,attributeValue)=> {const elementNodeName =p; const nameIsValid = testHtmlAttributeNameValidity(elementNodeName,attributeName); if(!nameIsValid)attributeName ='data-'+ attributeName; const element = document.querySelector(elementNodeName); ()); const();(); const(const char *); svgNS =http://www.w3.org/2000/svg\";const testSvgAttributeNameValidity =(elementNodeName,attributeName)=> {return(document.createElementNS(svgNS,elementNodeName)中的attributeName);}; const testSvgAttributeName =(attributeName,attributeValue)=> {const elementNodeName =rect; const nameIsValid = testSvgAttributeNameValidity(elementNodeName,attributeName); if(!nameIsValid)attributeName ='data-'+ attributeName; const element = document.querySelector(elementNodeName); (););}();};};};}; / code> 

#someId {color:green;} < svg height =55>

 < rect x =10y =10width =80height =40stroke =red/>< / svg>< div>< p> Hello world< / p> < / div>  



正确工作的代码应该改变矩形填充从黑色到黄色,这并没有发生。

解决方案

@ccprog的评论帮助我解决了这个问题。总之,对于SVG DOM元素,我需要原始检查和一个相同的布尔OR'd检查,但要添加 .style 属性。



如问题所示,HTML DOM元素属性名称的有效性可以通过检查如下来确定:

  //正确的HTML:
return(
attributeName in document.createElement(elementNodeName)
);

但是,这种方法不适用于SVG DOM元素。具体来说,下面的确定真实属性名称的有效性,比如id,但不会确定像fill这样的样式属性名称的有效性: p>

  //对SVG不够用,即只有部分正确:
return(document.createElementNS中的
attributeName(svgNS ,elementNodeName)
);

但是,只需复制该测试并添加 .style property到两个检查中的一个将允许检查两个类别的属性名称,如下所示:

  //正确的SVG:
返回(document.createElementNS(svgNS,elementNodeName)中的
attributeName .style ||
document.createElementNS(svgNS,elementNodeName)中的attributeName
);

下面的代码演示了这一点,它除了上面的代码外基本上与代码相同 - 注明的变化。确定两个类别属性名称的有效性的能力反映在可见矩形中黄色填充和粗划线宽度的外观上,同时将自定义的数据价格属性添加到元素。请特别注意HTML DOM元素和SVG DOM元素需要以不同的方式进行检查。



const testHtmlAttributeNameValidity =(elementNodeName,attributeName)=> {return(document.createElement(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,someHtmlId); //这会导致id属性发生变化,将//字体颜色更改为green.testHtmlAttributeName(color,orange); //color是一个CSS属性名称,它不是一个HTML DOM元素//属性名称。因此,这个测试应该导致color不被识别为有效的属性名称,导致//自定义属性名称为data-color,而不会影响元素的实际样式,也就是说测试不应该//将文本变为橙色。这个测试包含在这里//用于比较SVG DOM //元素样式属性(如fill)应该发生的情况,如下所示//测试SVG DOM元素属性names.testHtmlAttributeName(price ,昂贵); //这应该导致一个名为data-price的新属性//并且值expensive.console.log(document.querySelector('div')。innerHTML); const svgNS =http:// www.w3.org/2000/svg\";const testSvgAttributeNameValidity =(elementNodeName,attributeName)=> {return(// **********这是document.createElementNS(svgNS,elementNodeName)中的重要更改********** attributeName。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); (); testSvgAttributeName(id,someSvgId); testSvgAttributeName(fill,yellow); // ***现在正确识别为validtestSvgAttributeName(price,expensive); console.log(document.querySelector('svg')。innerHTML);

#someHtmlId {color:green;}#someSvgId {stroke-width:5px;}

< svg height =55> < rect x =10y =10width =80height =40stroke =red/>< / svg>< div>< p> Hello world< / p> < / div>


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

So, is there a way of determining whether or not a string represents a "standard/normal" DOM attribute?

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

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

Note that the fill color is not (yet) specified.

The user requests adding two attributes:

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

How do I dynamically distinguish between these two? The fill attribute isn't present in my current DOM element so I can't check if there is a pre-existing value for an attribute of that name. I also don't believe I can even check whether an error is thrown if I create the attribute without the prefix because, as far as I can tell, at least my current browser (Chrome v61.0) will allow me to add an attribute of price="expensive" (without the data- prefix) even though that is not best practice.

I want something like the following:

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

Is there any pre-existing testAttributeNameValidity-type functionality out there?

I've tagged this with javascript as I'm looking for a Javascript solution.

** UPDATE: Solution from other SO answer works in HTML but not SVG **

Based on the suggested link in the comments, I tried using attributeName in document.createElement(elementNodeName) which is supposed to return true for a valid attribute name and false for a non-valid one. When I use the valid attribute name "id" for an HTML element (<p>), this approach works.

In contrast, I still haven't gotten this approach to work in SVG. I tried converting createElement to createElementNS, and that still does not seem to fix the problem. See my test code below. The critical functions in the test code are testHtmlAttributeNameValidity and testSvgAttributeNameValidity. If you run the code and check the output in the console, it shows that it works properly for HTML, i.e. it produces id="someId" data-price="expensive". However, for SVG, it only produces the undesired output: data-fill="yellow" data-price="expensive".

If it makes a difference, I'm working in Chrome v61.

Test code:

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>

Correctly working code should change the rectangle fill from black to yellow, which does not happen.

解决方案

The comment from @ccprog helped me solve this problem. In summary, for SVG DOM elements, I needed the original check plus a boolean-OR'd check that is identical but with the addition of the .style property.

As shown in the question, the validity of an HTML DOM element attribute name can be determined by checking as follows:

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

However, this approach will not work for SVG DOM elements. Specifically, the following will determine the validity of true attribute names like "id", but will not determine the validity of style-like attribute names like "fill":

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

However, simply duplicating that test and adding the .style property to one of the two checks will allow both categories of attribute names to be checked, as follows:

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

This is demonstrated in the following code which is essentially identical to the code in the question except for the above-noted change. The ability to determine the validity of both categories of attribute name is reflected in the appearance of both yellow fill and thick stroke width in the visible rectangle while at the same time adding the custom "data-price" attribute to the element. Note in particular how HTML DOM elements and SVG DOM elements need to be checked differently.

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>

这篇关于确定标准HTML(或SVG)中的属性是否有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆