2017-09-25 51 views
0

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

那么,有没有一种方法来确定一个字符串是否代表“标准/正常”的DOM属性?

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

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

注意,填充颜色是(还)没有指定。

用户请求添加两个属性:

  • 名为“补”具有值“红色”的属性,它应产生fill="red"(注意没有前缀)
  • 命名的属性“价格“值”昂贵“,应该产生data-price="expensive"(注意前缀data-

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

我想要的东西,像下面这样:

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

是否有任何预先存在的testAttributeNameValidity型的功能了吗?

我标记为javascript,因为我在寻找Javascript解决方案。

**更新:从基于the suggested link in the comments,我尝试使用attributeName in document.createElement(elementNodeName)这应该返回true一个有效的属性名称和false用于非在HTML而不是SVG **

其他SO回答工程解决方案有效的。当我使用HTML元素的有效属性名称“id”(<p>)时,此方法有效。

相比之下,我仍然没有在SVG中使用这种方法。我试图将createElement转换为createElementNS,但似乎仍无法解决问题。看到我的测试代码如下。测试代码中的关键功能是testHtmlAttributeNameValiditytestSvgAttributeNameValidity。如果您运行代码并检查控制台中的输出,它将显示它适用于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>

正常工作的代码应该改变矩形从黑填写黄色,这不会发生。

+1

似乎与[如何检查是否DOM元素和/或属性是否有效?(https://stackoverflow.com/questions/33584700/how-to-check-if -dom-element-and-or-attribute-is-valid) –

+0

这就是为什么制作XHTML的原因。然而,每个人都在为了HTML而唾弃自己的坟墓。 – BoltClock

+0

@ShreyanshGandhi,我看着那个链接,它似乎解决了我的问题。但是,我似乎无法实现它,如我的问题的更新中所示,其中包含的测试代码不能产生所需的结果。此外,我尝试使用HTML的标准'createElement',但也更具体的'createElementNS'svg ...既不工作。 –

回答

0

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

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

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

然而,这种方法不会对SVG DOM元素工作。具体来说,有以下决定像“身份证”真正的属性名称的有效性,但确定风格类似属性的名称,如“补”的有效性:

// 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>

相关问题