2010-03-25 5 views
2

(je l'ai attributs enlevé, mais il est un peu de HTML généré automatiquement.)jquery éléments de sélection entre les deux éléments qui ne sont pas frères et soeurs

<img class="p"/> 
<div> hello world 
    <p> 
     <font><font size="2">text.<img class="p"/> 
     some text 
     </font></font> 
    </p> 
    <img class="p"/> 
    <p> <font><font size="2">more text<img class="p"/> 
     another piece of text 
     </font></font> 
    </p><img class="p"/> some text on the end 
</div> 

je besoin d'appliquer une mise en évidence avec des fonds à tous les textes que est entre deux éléments les plus proches (dans le code HTML) img.p en survolant le premier d'entre eux. Je n'ai aucune idée de comment faire ça. Disons que je plane le premier img.p - il devrait mettre en évidence hello world et text. et rien d'autre.

Et maintenant la pire partie - j'ai besoin que les arrière-plans disparaissent sur mouseleave. J'en ai besoin pour travailler avec n'importe quel désordre de HTML possible.

Ce qui précède n'est qu'un exemple et la structure des documents sera différente. Astuce: Le traitement de l'ensemble du code html avant la liaison hover et la mise en place de certaines travées, etc. est OK tant qu'il ne modifie pas l'apparence du document de sortie.

Répondre

5

Traitement toute html avant de se lier vol stationnaire et mettre quelques travées etc. est ok

Vous auriez certainement pour ce faire, car vous ne pouvez pas styler des nœuds de texte, seulement des éléments.

Voici une fonction que vous pourriez utiliser pour le faire depuis un script. (Malheureusement, jQuery n'est pas très ici car il n'aime pas les nœuds de texte de manipulation.)

// Wrap Text nodes in a new element of given tagname, when their 
// parents contain a mixture of text and element content. Ignore 
// whitespace nodes. 
// 
function wrapMixedContentText(el, tag) { 
    var elementcontent= false; 
    for (var i= el.childNodes.length; i-->0;) { 
     var child= el.childNodes[i]; 
     if (child.nodeType===1) { 
      elementcontent= true; 
      wrapMixedContentText(child, tag); 
     } 
    } 
    if (elementcontent) { 
     for (var i= el.childNodes.length; i-->0;) { 
      var child= el.childNodes[i]; 
      if (child.nodeType===3 && !child.data.match('^\\s*$')) { 
       var wrap= document.createElement(tag); 
       el.replaceChild(wrap, child); 
       wrap.appendChild(child); 
      } 
     } 
    } 
} 

Et voici quelques fonctions que vous pouvez utiliser pour sélectionner des noeuds entre autres noeuds. (Encore une fois, jQuery n'a pas une fonction pour cela.)

// Get array of outermost elements that are, in document order, 
// between the two argument nodes (exclusively). 
// 
function getElementsBetweenTree(start, end) { 
    var ancestor= getCommonAncestor(start, end); 

    var before= []; 
    while (start.parentNode!==ancestor) { 
     var el= start; 
     while (el.nextSibling) 
      before.push(el= el.nextSibling); 
     start= start.parentNode; 
    } 

    var after= []; 
    while (end.parentNode!==ancestor) { 
     var el= end; 
     while (el.previousSibling) 
      after.push(el= el.previousSibling); 
     end= end.parentNode; 
    } 
    after.reverse(); 

    while ((start= start.nextSibling)!==end) 
     before.push(start); 
    return before.concat(after); 
} 

// Get the innermost element that is an ancestor of two nodes. 
// 
function getCommonAncestor(a, b) { 
    var parents= $(a).parents().andSelf(); 
    while (b) { 
     var ix= parents.index(b); 
     if (ix!==-1) 
      return b; 
     b= b.parentNode; 
    } 
    return null; 
} 

utilisation possible:

var outer= document.getElementById('myhighlightingimagesdiv'); 
wrapMixedContentText(outer, 'span'); 

var ps= $('#myhighlightingimagesdiv .p'); 
ps.each(function(pi) { 
    // Go up to the next image in the list, or for the last image, up 
    // to the end of the outer wrapper div. (There must be a node 
    // after the div for this to work.) 
    // 
    var end= pi===ps.length-1? outer.nextSibling : ps[pi+1]; 

    var tweens= $(getElementsBetweenTree(this, end)); 
    $(this).hover(function() { 
     tweens.addClass('highlight'); 
    }, function() { 
     tweens.removeClass('highlight'); 
    }); 
}); 
+0

C'est beaucoup de code intéressant. Je l'ai travaillé de façon à ce qu'il fonctionne assez vite pour réagir aux survols en ajoutant beaucoup de portées tout en générant la sortie html, mais je vais regarder tout votre code, parce que je veux toujours savoir comment puis-je obtenir ces éléments. Merci pour ce travail. Je vous donnerais plus de +1, mais il ne me laissera pas;) Je pense que je ferai un plugin si vous n'envisagez pas de le faire. – naugtur

1

C'est un morceau de HTML totalement non structuré, ce que vous devriez toujours éviter. Cependant, vous ajoutez des données à l'img que vous souhaitez suivre pour le vol stationnaire, comme ceci:

[...] 
<img src="#" class="master" data-friends-group="group1"/> 
[...] 
<span class="group1">text1</span> 
[...] 
<span class="group1">text2</span> 
[...] 

Vous pouvez maintenant prendre de l'"data-friends-group" l'attribut de la classe en commun à tous les éléments dont vous avez besoin pour mettre en évidence. Maintenant, le reste est facile.

$(document).ready(function() { 
    $("img.master").each(function() { 
     $friends = $("." + $(this).attr("data-friends-group")); 
     $(this).hover(
      function(){ 
       $friends.addClass("highlighted"); 
      }, 
      function(){ 
       $friends.removeClass("highlighted"); 
      } 
     ); 
    }); 
}); 

De toute évidence, la classe .hightlighted sera celle avec le background-color: yellow;

+0

Le html provient d'une application qui le traite comme du texte et des scissions. Je ne peux que mettre mon propre code entre les parties et je dois mettre en évidence ces parties. J'ai trouvé une solution de contournement basée sur la mise en place de certaines travées dans le texte, mais c'est très différent. +1 de toute façon et merci pour votre temps. – naugtur

Questions connexes