62 votes

Comment accéder au contenu généré par CSS avec JavaScript

Je génère la numérotation de mes en-têtes et de mes figures à l'aide de CSS. counter y content propriétés :

img.figure:after {
  counter-increment: figure;
  content: "Fig. " counter(section) "." counter(figure);
}

Ceci (en supposant un navigateur approprié) donne un étiquetage agréable "Fig. 1.1", "Fig. 1.2" et ainsi de suite à la suite de toute image.

Question : Comment puis-je y accéder à partir de Javascript ? La question est double : j'aimerais accéder à soit la valeur actuelle d'un certain compteur (à un certain nœud du DOM) o la valeur du contenu généré par le CSS (à un certain nœud du DOM) o évidemment, les deux informations.

Le contexte : J'aimerais ajouter aux liens qui renvoient aux chiffres le numéro approprié, comme ceci :

<a href="#fig1">see here</h>
------------------------^ " (Fig 1.1)" inserted via JS

D'après ce que je vois, cela se résume à ce problème : I pourrait accès content o counter-increment via getComputedStyle :

var fig_content = window.getComputedStyle(
                    document.getElementById('fig-a'),
                    ':after').content;

Cependant, ce n'est pas le en direct mais celle qui est déclarée dans la feuille de style. Je ne trouve pas d'interface permettant d'accéder à la réel valeur vivante. Dans le cas du compteur, il n'y a même pas de propriété CSS réelle à interroger.

Editar: En creusant de plus en plus profondément dans les spécifications DOM, j'ai trouvé l'interface DOM Level 2 Style Counter . Cela semble a) permettre l'accès à la valeur actuelle du compteur et b) être implémenté dans Firefox, au moins. Cependant, je n'ai aucune idée de la manière de l'utiliser. Mon approche actuelle est morte tragiquement après cette sortie de Firebug :

// should return a DOM 2 Counter interface implementation...
window.getComputedStyle(fig_a_element, ':after')
      .getPropertyCSSValue("counter-increment")[0]
      .getCounterValue();

[Exception... "Modifications are not allowed for this document" code: "7"
 nsresult: "0x80530007 (NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR)"
 location: "http://localhost/countertest.html Line: 71"]

Toute idée sur la manière de donner vie à ce projet serait très appréciée.

Edit 2 : Apparemment, j'ai mal interprété l'objet Counter du DOM Level 2 Style. Lui non plus n'a pas de propriété pour retourner la valeur actuelle du compteur. Cela rend l'approche ci-dessus invalide.

Nouvelle approche : Existe-t-il une possibilité de lire le contenu d'un pseudo-élément via le DOM ? C'est-à-dire, puis-je sélectionner le pseudo-élément ( treeWalker me vient à l'esprit) et ensuite obtenir son nodeValue ? (Si vous commencez à taper jQuery maintenant, s'il vous plaît reconsidérez de changer ce terme en "Sizzle ...)

24voto

bobince Points 270740

Je ne trouve aucune interface pour accéder à la valeur réelle en direct. [du compteur]

Ouais. Je ne pense pas qu'il y en ait une. Désolé.

La seule chose à laquelle je pense serait de passer par chaque élément (y compris son :before / :after pseudo-éléments) avant l'élément dans le document, en recherchant des compteurs et en additionnant leur nombre.

Évidemment, c'est hideux. Si vous essayez de reproduire le propre navigateur counter mécanisme, il serait probablement plus facile (et beaucoup plus compatible, étant donné le manque de support des compteurs/contenus d'IE<=7) de simplement le remplacer par vos propres compteurs basés sur le script. par exemple, quelque chose du genre :

<a href="#prettypicture">this</a>

<div class="counter level=0">...</div>
<img id="prettypicture" class="counter level=1" alt="ooo, pretty"/>

window.onload= function() {
    var counters= Node_getElementsByClassName(document.body, 'counter');
    var indices= [];
    for (var counteri= 0; counteri<counters.length; counteri++) {
        var counter= counters[counteri];

        var level= Element_getClassArgument(counter, 'level');
        while (indices.length<=level)
            indices.push(0);
        indices[level]++;
        indices= indices.slice(level+1);
        var text= document.createTextNode('Figure '+indices.join('.'));
        counter.parentNode.insertBefore(text, counter.nextSibling);

        if (counter.id!=='') {
            for (var linki= document.links.length; linki-->0;) {
                var link= document.links[i];
                if (
                    link.hostname===location.hostname && link.pathname===location.pathname &&
                    link.search===location.search && link.hash==='#'+counter.id
                ) {
                    var text= document.createTextNode('('+indices.join('.')+')');
                    link.parentNode.insertBefore(text, link.nextSibling);
                }
            }
        }
    }
};

15voto

aSeptik Points 19103

Lisez ça :

Le contenu généré ne modifie pas le l'arbre du document. En particulier, il n'est en particulier, il n'est pas renvoyé au processeur de (par exemple, pour le reparsage).


Le contenu spécifié dans une feuille de style ne fait pas partie du DOM.

C'est pour cette raison que le getComputedStyle ne fonctionnera pas dans ce cas Je pense que le seul moyen, c'est de faire un classique. boucle à travers comme quelqu'un l'a décrit ci-dessous !

2voto

svinto Points 8601

Je porterais votre css en Javascript, cela vous permet d'obtenir la légende de la figure et aussi d'avoir une plus grande couverture du navigateur. En utilisant jQuery, vous feriez quelque chose comme ceci :

$(function() {
  var section = 0;
  $(".section").each(function() {
    section++;
    var figure = 0;
    $(this).find("img.figure").each(function() {
      figure++;
      var s = "Fig. " + section + "." + figure;
      $(this).attr({alt:s}).after(s);
    });
  });
});

Alors vous pourriez le faire :

<div class="section">blabla <img id="foo" src="http://www.example.com/foo.jpg"></div>
<p>Lorem ipsum dolor sit amet <a href="#foo" class="figurereference">see here</a></p>

<script type="text/javascript">
  $(function() {
    $("a.figurereference").each(function() {
      var selector = $(this).attr("href");
      var $img = $(selector);
      var s = $(this).text() + " (" + $img.attr("alt") + ")";
      $(this).text(s);
    });
  });
</script>

Bien que je sois d'accord pour dire que faire cela en utilisant CSS serait très bien.

0voto

Doug Points 2296

Je ne sais pas comment il est implémenté, mais le sélecteur jquery .css() semble fonctionner pour cela sur la dernière version de safari, chrome et firefox.

.foo { content: 'hello'; }

...

var value = $('.foo').css('content').toString();

Voici un stylo de celui-ci en action pour injecter des icônes SVG directement à partir du css ; http://codepen.io/shadowmint/pen/unvLB

(remarquez que la valeur du contenu doit être échappée, c'est-à-dire '1' ; utiliser content : 1 ne fonctionnera pas)

-1voto

Justin Johnson Points 16243

Je ne trouve aucune interface pour accéder à la valeur réelle en direct.

Si vous ne pouvez pas obtenir la valeur de window.getComputedStyle il semble que ce soit impossible.

Plus important encore, bien qu'il soit capable de le faire, je pense qu'il pourrait s'agir d'un abus de CSS puisque vous brisez la barrière entre le contenu et la présentation à ce stade.

Consultez cette question connexe Quelles sont les bonnes utilisations de la propriété css "Content" ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X