2010-06-05 23 views
0

Dans une application Lift, j'aimerais ajouter une balise spéciale qui prend la partie <tbody> du tableau suivant et ajoute les classes odd et even (par exemple) à chaque étiquette <tr>. Alternant, bien sûr. Bien que j'ai trouvé un moyen d'ajouter un autre attribut à tous les tags <tr>, il reste quelques problèmes (voir le code ci-dessous).scala: Ajout d'attributs (lignes impaires et paires) à la table xml

Tout d'abord, cela ne fonctionne pas. cycle.next est appelé trop souvent, donc à la fin, tout est une ligne odd. D'autres problèmes sont que le code n'exclut pas les tables internes (donc un <tr> imbriqué serait également transformé) et qu'il affecte également la partie <thead> de la table.

Des idées pour que ce code fonctionne? (Bien sûr, s'il y a déjà un ascenseur basée sur la solution - sans jQuery - pour cela, je vais remercier le prendre.)

// Helper class for looping 
class Loop(val strs: String*) { 
    val stream_iter = Stream.continually(strs.toStream).flatten.iterator 
    def next = stream_iter.next 
} 

val cycle = new Loop("even", "odd") 

val rr = new RewriteRule { 
    override def transform(n: Node): Seq[Node] = n match { 
    // match any Elem 
    case elem : Elem => elem match { 
     // If it’s a <tr> do some further processing 
     case Elem(_, "tr", att @ _, _, _*) => 
      elem % Attribute(None, "class", Text(
       // add the attribute and concatenate with others 
       List(att.get("class").getOrElse("").toString, cycle.next).reduceLeft(_+" "+_).trim 
       ), Null) toSeq 
     case other => other 
    } 
    case other => other 
    } 
} 

val rt = new RuleTransformer(rr) 

val code = <table> 
    <thead><tr><td>Don’t</td><td>transform this</td></tr></thead> 
    <tbody> 
    <tr class="otherclass"> 
     <td>r1c1</td><td>r1c2</td> 
    </tr> 
    <tr> 
     <td>r2c1</td><td>r2c2</td> 
    </tr> 
    <tr> 
     <td>r3c1</td><td>r3c2</td> 
    </tr> 
    </tbody> 
</table> 

println(rt(code)) 

Répondre

1

le problème avec RewriteRule s semble être qu'ils nichent trop profondément. C'est-à-dire qu'une fois qu'une règle d'ajout d'attributs à <tr> est démarrée, il n'est pas possible de l'arrêter. (Au moins, cela n'a pas fonctionné pour moi.) Cependant, j'ai trouvé une solution récursive qui fonctionne pour moi. En outre, tant qu'il est un <tbody> à l'intérieur, la récursivité s'arrêtera tôt. S'il n'y a pas, nous pourrions avoir un problème ...

abstract class Loop { 
    val stream_iter = Stream.continually(elems.toStream).flatten.iterator 
    def next = stream_iter.next 
    def elems: Seq[String] 
} 
class Cycle extends Loop { override def elems = List("odd", "even") } 

// Call this when in <tbody> 
def transformChildren(sn: Seq[Node]): Seq[Node] = { 
    // Start a new cycle 
    val cycle = new Cycle 
    sn.map{ node => node match { 
     case Elem(prefix, "tr", att, scope, ch @ _*) => 
      Elem(prefix, "tr", att, scope, ch:_*) % Attribute(None, "class", Text(
       List(att.get("class").getOrElse("").toString, cycle.next).reduceLeft(_+" "+_).trim 
       ), Null) 
     case other => other 
     } 
    } 
} 

// Look for first <tbody>, transform child tr elements and stop recursion 
// If no <tbody> found, recurse 
def recurse(sn: NodeSeq): NodeSeq = sn.map{ node => 
    node match { 
     case Elem(prefix, "tbody", att, scope, ch @ _*) 
      => Elem(prefix, "tbody", att, scope, transformChildren(ch):_*) 
     case Elem(prefix, label, att, scope, ch @ _*) 
      => Elem(prefix, label, att, scope, recurse(ch):_*) 
     case other => other 
    } 
} 

val code = <table> 
    <thead><tr><td>Don’t</td><td>transform this</td></tr></thead> 
    <tbody> 
    <tr class="otherclass"> 
     <td>r1c1</td><td>r1c2</td> 
    </tr> 
    <tr> 
     <td><table><tbody><tr><td>Neither this.</td></tr></tbody></table></td><td>r2c2</td> 
    </tr> 
    <tr> 
     <td>r3c1</td><td>r3c2</td> 
    </tr> 
    </tbody> 
</table> 

println(recurse(code)) 

donne:

<table> 
    <thead><tr><td>Don’t</td><td>transform this</td></tr></thead> 
    <tbody> 
    <tr class="otherclass odd"> 
     <td>r1c1</td><td>r1c2</td> 
    </tr> 
    <tr class="even"> 
     <td><table><tbody><tr><td>Neither this</td></tr></tbody></table></td><td>r2c2</td> 
    </tr> 
    <tr class="odd"> 
     <td>r3c1</td><td>r3c2</td> 
    </tr> 
    </tbody> 
</table> 
3

Il y a 2 façons différentes que j'Accomplir les classes de ligne de table de rechange:

1 - Utilisez le jQuery colorize plugin

2 - utilisation zipWithIndex lors du bouclage de vos données pour créer la table:

doQuery.zipWithIndex.map{ case (log, i) => { 
    <tr class={if (i % 2 == 0) "even" else "odd"}> 
     <td>Data</td> 
    </tr> 
} 
+0

Comme je l'ai dit, je ne veux pas utiliser jQuery pour cela. De plus, je ne veux pas créer d'index côté serveur car je pense que les lignes paires/impaires sont quelque chose dont le concepteur de modèle doit se soucier et pas le programmeur. (Le programmeur pourrait créer la balise de modèle pour le faire, cependant.) – Debilski