2010-02-11 5 views
20

Estoy trabajando en un sitio de Jekyll y estoy tratando de generar tres divisiones de columna anidadas en una fila div. Liquid hace que este muy fácil con su filtro de cycle:Módulo (o falta del mismo) en el motor de plantillas líquidas de Ruby

{% for p in site.categories.post %} 
    {% cycle 'add rows': '<div class="row">', nil, nil %} 
     <div class="column"> 
      <a href="{{ p.url }}">{{ p.title }}</a> 
     </div> 
    {% cycle 'close rows': nil, nil, '</div>' %} 
{% endfor %} 

Sin embargo, esto sólo funciona cuando hay 3, 6, 9, etc. puestos. Cuando el número total de publicaciones no es un múltiplo de tres, el <div class="row"> nunca se cierra: el bucle for finaliza antes de que la etiqueta de cierre pueda salir como parte del ciclo close rows.

En Ruby, PHP, o cualquier otro lenguaje que fácilmente podría solucionar este problema con un operador de módulo, lo que además de close rows ciclo de producción que lo haría cuando </div>if site.categories.size % 3 == 0. Sin embargo, Liquid, porque es un lenguaje de plantillas seguro, no es compatible con el módulo.

¿Qué más puedo hacer para cerrar correctamente <div class="row"> cuando el número total de publicaciones no es un múltiplo de tres?

Respuesta

13

Para su ejemplo específico, puede usar {% cycle 'close rows': nil, '</div>', '</div>' %} después del {% endfor %}.

+0

¡Eso funciona perfectamente! ¡Gracias! – Andrew

1

IIRC Liquid no bloquea el funcionamiento del módulo, solo el carácter %. Puede realizar un módulo sin usar el operador %. Por ejemplo, 14.modulo(3) => 2 en lugar de 14 % 3.

+0

Eso tiene sentido, ya que todas las demás funciones aritméticas se abstraen así, pero desafortunadamente ni 'modulo' ni' modulus' funcionan ... – Andrew

+0

Sí. Acabo de comprobar el código fuente. Lamentablemente, no 'modulo'. Tendré que tal vez bifurcarlo y agregarlo o algo así. Mi solución actual es un desastre: 'a menos que sea total == 3 o total == 6 o total == 9 o total == 12 o total == 15 ...' – Andrew

+1

'x.modulo (y)' es solo un alias para ' x.divmod (y) [1] '. Si se permite 'divmod', podrías usar esa forma. O bien, siempre puede desplegar su propia función de módulo: 'x - (x/y)' (utilizando las versiones abstractas de los operadores aritméticos que necesite). – bta

8

La única manera por ahora es escribir un filtro de líquido para lograr esto. Registre el filtro en algún lugar de su código donde sea apropiado (está en diferentes lugares si se usa con rieles y sin ellos).

líquido :: Template.register_filter (LiquidFilters)

En ustedes proyectos/lib añadir liquid_filters.rb:

module LiquidFilters 
    # makes modulus operation available to templates 
    def mod(data, param) 
    data % param 
    end 
end 

Después de que se pueden utilizar como si fuera siguiente en sus plantillas : {{variable | mod: 5}}

Y si necesita usarlo para cierta lógica, puede capturar el valor.

{% capture modulus %}{{ variable | mod:5 }}{% endcapture %} 

Sólo me he dado cuenta de que el valor capturado es una cadena para el fin de compararlo utiliza

{% if modulus == "0" %} 
.. 
{% endif %} 
+0

Esta es de lejos la mejor respuesta. – ptrin

+1

¡Es una verdadera mierda, pero una solución funcional! Gracias :) –

3

utilicé otro truco en un bucle for: inútil en su caso, útil si Solo quiero un módulo para saber si tu línea ha finalizado y necesitas una nueva fila, como hice yo.

En este ejemplo voy a ir con una línea de 4 elementos:

{% assign currentRow = 1 %} 
# enter the for loop ... then, with 4 as the divisor: 
{% if forloop.index == 4 * currentRow %} 
    # do whatever you want 
    {% assign currentRow = currentRow + 1 %} 
{% endif %} 
# exit the for loop 

No es muy agradable, pero fácil.

12

¡He encontrado esta manera de funcionar genial!

{% assign mod = forloop.index0 | modulo:4 %} 
{% if mod == 0 %} 
    <!-- Do stuff --> 
{% endif %} 
+0

Modulo debe haber sido agregado en las versiones posteriores de Jekyll. Esto definitivamente funciona en mi proyecto. – ThisClark

1

Aprendí mucho de esta publicación, y estos son tres patrones que utilicé a lo largo de mi proyecto. Funcionó muy bien con Bootstrap también. Simplemente cambie la clase de columna en el siguiente código. En lugar de columnas, los mismos patrones se pueden aplicar a otros escenarios donde el módulo es útil, como filas impares. Espero que ayuda a alguien -

cuatro columnas:

<div class="container"> 
    {% for post in site.posts %} 
     {% cycle 'add row' : '<div class="row">', nil, nil, nil %} 
      <div class="column"> 
       <!-- liquid tags here --> 
      </div> 
     {% cycle 'end row' : nil, nil, nil, '</div>' %} 
    {% endfor %} 
    {% cycle 'end row' : nil, '</div>', '</div>', '</div>' %} 
</div> 

tres columnas:

<div class="container"> 
    {% for post in site.posts %} 
     {% cycle 'add row' : '<div class="row">', nil, nil %} 
      <div class="column"> 
       <!-- liquid tags here --> 
      </div> 
     {% cycle 'end row' : nil, nil, '</div>' %} 
    {% endfor %} 
    {% cycle 'end row' : nil, '</div>', '</div>' %} 
</div> 

dos columnas:

<div class="container"> 
    {% for post in site.posts %} 
     {% cycle 'add row' : '<div class="row">', nil %} 
      <div class="column"> 
       <!-- liquid tags here --> 
      </div> 
     {% cycle 'end row' : nil, '</div>' %} 
    {% endfor %} 
    {% cycle 'end row' : nil, '</div>' %} 
</div> 
3

Me doy cuenta de que la pregunta se ha resuelto para el solicitante, pero recientemente me encontré con este tipo de situación en Liquid y pensé en proporcionar mi solución en caso de que ayudara a alguien con requisitos de marcado similares.

En mi caso, ya he pasado una declaración if que verifica que hay al menos una publicación, así que creé la primera div "fila" fuera del ciclo. También lo cierro después del ciclo for. Esto protege contra un caso donde hay menos de tres publicaciones.

<div class="row"> 

    {% for p in posts %} 
     <div class="column"> 
      <!-- Post code here --> 
     </div> 
     {% unless forloop.last %} 
      {% cycle '', '', '</div><div class="row">' %} 
     {% endunless %} 
    {% endfor %} 

</div> 

Después de cada tres puestos de trabajo, el ciclo se cerrará la fila actual y abrir una nueva unless el puesto era el último en la forloop, en cuyo caso no queremos abrir una nueva fila, y deje que la envoltura </div> lo cierre.

Cuestiones relacionadas