2017-09-25 1 views
0

Je souhaite ajouter par programmation des attributs aux éléments DOM (par exemple des éléments HTML ou SVG) de manière dynamique au moment de l'exécution, c'est-à-dire en fonction de l'entrée utilisateur. Si l'attribut est un attribut standard, j'utiliserai le nom tel quel, mais s'il ne l'est pas, c'est-à-dire s'il nécessite la transformation en un attribut personnalisé, alors je veux ajouter le préfixe "data-". Donc, y a-t-il un moyen de déterminer si une chaîne représente ou non un attribut DOM "standard/normal"?Détermination de la validité d'un attribut en HTML standard (ou SVG)

Par exemple, dire que j'ai un rectangle SVG comme suit:

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

Notez que la couleur de remplissage est pas (encore) spécifié.

Les demandes des utilisateurs en ajoutant deux attributs:

  • un attribut nommé « remplir » avec la valeur « rouge », ce qui devrait donner fill="red" (note l'absence d'un préfixe)
  • un attribut nommé « prix "avec la valeur « chère », ce qui devrait donner data-price="expensive" (note le préfixe data-)

Comment puis-je distinguer dynamiquement entre ces deux? L'attribut fill n'est pas présent dans mon élément DOM actuel, donc je ne peux pas vérifier s'il existe une valeur préexistante pour un attribut de ce nom. Je ne pense pas non plus pouvoir vérifier si une erreur est générée si je crée l'attribut sans le préfixe car, pour autant que je sache, au moins mon navigateur actuel (Chrome v61.0) me permettra d'ajouter un attribut de price="expensive" (sans le préfixe data-) même si ce n'est pas la meilleure pratique.

Je veux quelque chose comme ce qui suit:

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

Y at-il préexistante testAttributeNameValidity fonctionnalité de type là-bas?

Je l'ai tagué avec javascript comme je suis à la recherche d'une solution Javascript.

** MISE À JOUR: Solution d'autres SO répondre à des œuvres en HTML mais pas SVG **

Basé sur the suggested link in the comments, j'ai essayé d'utiliser attributeName in document.createElement(elementNodeName) qui est censé revenir true un nom d'attribut valide et false pour un non un valide. Lorsque j'utilise le nom d'attribut valide "id" pour un élément HTML (<p>), cette approche fonctionne.

En revanche, je n'ai toujours pas cette approche pour travailler en SVG. J'ai essayé de convertir createElement en createElementNS, et cela ne semble toujours pas résoudre le problème. Voir mon code de test ci-dessous. Les fonctions critiques dans le code de test sont testHtmlAttributeNameValidity et testSvgAttributeNameValidity. Si vous exécutez le code et vérifiez la sortie dans la console, il montre qu'il fonctionne correctement pour HTML, c'est-à-dire qu'il produit id="someId" data-price="expensive". Cependant, pour SVG, il produit uniquement la sortie non souhaitée: data-fill="yellow" data-price="expensive".

Si cela fait une différence, je travaille dans Chrome v61.

Code d'essai:

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>

code de travail doit changer correctement le rectangle de remplissage du noir au jaune, qui ne se produit pas.

+1

semble lié à [Comment vérifier si l'élément DOM et/ou un attribut est valide?] (Https://stackoverflow.com/questions/33584700/how-to-check-if -dom-element-and-or-attribute-is-valid) –

+0

C'est pourquoi XHTML a été créé. Pourtant, tout le monde crache sur sa tombe en faveur du HTML. – BoltClock

+0

@ShreyanshGandhi, j'ai regardé ce lien, et il semblait résoudre mon problème. Cependant, je ne semble pas être en mesure de l'implémenter, comme le montre la mise à jour de ma question qui inclut un code de test qui ne produit pas les résultats souhaités. De plus, j'ai essayé d'utiliser à la fois le standard 'createElement' pour HTML mais aussi le' createElementNS' plus spécifique pour svg ... ni travaillé. –

Répondre

0

Le commentaire de @ccprog m'a aidé à résoudre ce problème. En résumé, pour les éléments DOM SVG, j'avais besoin de la vérification d'origine plus une vérification booléenne-OR'd qui est identique mais avec l'ajout de la propriété .style.

Comme le montre la question, la validité d'un élément DOM HTML nom d'attribut peut être déterminé en vérifiant comme suit:

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

Cependant, cette approche ne fonctionnera pas pour les éléments SVG DOM. Plus précisément, ce qui suit va déterminer la validité des vrais noms d'attributs comme « id », mais pas déterminer la validité des noms d'attributs comme le style comme « remplir »:

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

Cependant, la duplication simplement que essai et en ajoutant la propriété .style à l'un des deux contrôles permettra à deux catégories de noms d'attributs à vérifier, comme suit:

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

Ceci est démontré dans le code suivant qui est essentiellement identique au code dans le Qué sauf pour le changement mentionné ci-dessus. La possibilité de déterminer la validité des deux catégories de nom d'attribut est reflétée dans l'apparition de la largeur jaune et de la largeur du trait épais dans le rectangle visible, tout en ajoutant l'attribut personnalisé "data-price" à l'élément. Notez en particulier comment les éléments DOM HTML et les éléments DOM SVG doivent être vérifiés différemment.

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>