jquery :nth-child()
Hola!
necesito implementar este método de selección de jquery en un proyecto.
Básicamente tengo una lista de items que necesito que cada x elementos se genere una clase para ese elemento en concreto. Esto es, en una <ul> tengo 60 <li> y cada 20 <li> quiero asignar la clase .break.
Pensé en este método a través de jquery, pero no sé implementarlo bien, alguien puede echarme un cable a crear esta función, seguro que es muy básica pero no me aclaro!
Tiene que ser algo así, verdad? Es que no termina de funcionar:
$("#item-works:nth-child(20n)").addClass("break");
El método funciona con las mismas reglas que lo hace la regla en CSS3 - http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
http://api.jquery.com/nth-child-selector/
Muchas gracias!
maddundee
Eres un craaack!! Ahora sí!
Solo dos cosas, la primera es que si seleccionas branding en filtros sigue haciendo un extraño que no entiendo en scrollTo. Voy a subir el cambio.
Por otra, me puedes dar tu correo electrónico? Me gustaría agradecer tu ayuda vía paypal y además tener tu contacto para posibles proyectos que no pueda abarcar a nivel de programación. Te parece?
Muuuuuchas gracias!!
andrewman
Mad, el problema es que el plugin filterable 'dispara' dos eventos que animan la opacidad y la funcion que definimos se mezcla entre medio de ellas, y no funciona como debe.
Prueba con lo siguiente, cambia la función a esto:
function addBreakClass(target) {
var visibles = 0;
$('#list-works li').each(function() {
$(this).removeClass('break');
if (target=='all' || $(this).hasClass(target)) {
visibles++;
if (visibles==1 || visibles%20 == 0 ) $(this).addClass('break');
}
});
}
y agrega o modifica lo siguiente (en custom-low)
var $paneTarget = $('#list-works');
$('.works-filters li a').click(function(){
var categoria = $(this).attr('href').substr(1);
var $target = $paneTarget.find('li:eq(0)');
$paneTarget.stop().scrollTo( $target , 800 );
addBreakClass(categoria);
});
y en la última línea pones:
addBreakClass('all');
En resumen, en vez de depender de la opacidad (que está siendo animada), ahora la función usa la misma variable que el filtro, si el elemento tiene la clase a mostrar lo contabiliza y añade 'break' cuando debe.
maddundee
http://kamchatka.es/themes/templates/new-folio-test/index.html
maddundee
Andrew, ya lo probé y lo acabo de probar de nuevo y no funciona correctamente. Y sí, necesito que el primer elemento de todos los visibles también se le aplique la clase. Todo es por el tema del filtrado y el scrollTo que te comentaba al principio. Subí el sitio para que pudieras orientarte un poco más.
Gracias!!
andrewman
¿Puedes probar con la función tal cual te la di? (con el cambio mencionado claro)
Otra cosa, ¿necesitas que el primer elemento tenga clase break?
maddundee
Me di cuenta de ello, es normal el error ya que no conoces el código. He estado usando la clase que tienen todo los <li>, así:
$('.work-item').each(function() {..}
Es así como tampoco me funciona. Creo que tiene algo que ver con el sistema de filtro. Ya que este lo que hace es modificar el width de cada elemento mediante animation. Con lo cual no termino de estar seguro de la visibilidad del elemento. Aunque luego con firebug veo que efectivamente a cada <li> se le aplica un display:none con lo cual simplemente habría que comprobar el estado actual y seguir con la función. Lo que tengo ahora en custom-low.js es lo siguente:
function addBreakClass() {
// contador que hará de índice para los elementos no filtrados
var visibles = 0;
// recorremos TODOS los elementos de la lista
$('.work-item').each(function() {
// primero le quitamos la clase
$(this).removeClass('break');
// si el elemento no ha sido filtrado
if ($(this).css('display', 'block')) {
// le sumamos uno al contador de elementos visibles
visibles++;
/* si el contador nos indica que el índice
* del elemento es múltiplo de 20,
* le añadimos la clase */
if (visibles%20 == 0 ) $(this).addClass('break');
$('.work-item:eq(0)').addClass('break');
}
});
}
andrewman
vale, el problema es que no hay ningún $('#item-works'), por eso no funciona.
Cambia la id del selector en la función que te di:
// recorremos TODOS los elementos de la lista
$('#item-works li').each(function() {
por
// recorremos TODOS los elementos de la lista
$('#list-works li').each(function() {
maddundee
Andrew, te agradezco muchísimo tu interés, de verdad!
He probado la función tal cual, incluso con ciertas modificaciones, pero no sé qué sucede. Asigna la clase cada 20 elementos, como quería. Pero no tiene en cuenta si están visibles o no, así que siempre los asigna a los mimos elementos. Te voy a dejar un link al sitio por si puedes echarle un vistazo, no te sientas con el compromiso porque ya has hecho mucho. Yo voy a seguir a ver si puedo dar con la solución.
El problema tiene que ver con la paginación, cuando pulsas pre/next cuando has filtrado los trabajos de branding, por ejemplo. Necesito poner una clase (break) para que scrollTo pueda localizar el objeto. Y necesito que sea en los elementos visibles y cada 20 de estos.
En cualquier caso muchísimas gracias!!
http://kamchatka.es/themes/templates/new-folio-test/index.html
andrewman
Utiliza esta función:
function addBreakClass() {
// contador que hará de índice para los elementos no filtrados
var visibles = 0;
// recorremos TODOS los elementos de la lista
$('#item-works li').each(function() {
// primero le quitamos la clase
$(this).removeClass('break');
// si el elemento no ha sido filtrado
if ($(this).is(':visible')) {
// le sumamos uno al contador de elementos visibles
visibles++;
/* si el contador nos indica que el índice
* del elemento es múltiplo de 20,
* le añadimos la clase */
if (visibles%20 == 0 ) $(this).addClass('break');
}
});
}
Los comentarios son excesivos, deberías borrarlos cuando pongas el código en tu script.
p.d: Creo recordar que el tag '[code]' mantenía el formato hace un tiempo.
maddundee
He modificado mi código, pero no consigo hacerlo funcionar. Alguna sugerencia? Soy pésimo programando, lo siento:
function addBreakClass() {
var visibles = $("#item-works li").is(':visible');
if ( $('#item-works li').is(':visible')){
$("#item-works li").removeClass("break");
$(visibles+":nth-child(20n)").addClass("break");
}
}
addBreakClass();
var $paneTarget = $('#list-works');
$('.works-filters li a').click(function(){
var $target = $paneTarget.find('li:eq(1)');
$paneTarget.stop().scrollTo( $target , 800 );
addBreakClass();
});
Ni siquiera sé si la sintaxis es correcta, he buscado en google pero no encuentro nada que pueda ayudarme. En cualquier caso, muchas gracias por la orientación, seguiré dándole vueltas!
andrewman
El método sí busca todos sus nodos hijos, si tienes una etiqueta p o a, o un div, también será tomando en cuenta, por eso es mejor especificar.
El nth-child funciona independiente del estado del elemento (visible u oculto), por ende, le estás añadiendo la clase 'break' siempre a los mismos. Bastaría con que filtres los elementos dentro de tu función addBreakClass, para que se añada la clase sólo a elementos visibles.
maddundee
Hola Andrew,
di por hecho que el método buscaba dentro de sus nodos hijos, es decir, los <li>. Veo que no es así, pero el caso es que pruebo del modo que me indicas también y tampoco consigo hacer que funcione, mira este es el código que estoy usando:
function addBreakClass() {
$("#item-works li").removeClass("break");
$("#item-works li:nth-child(20n)").addClass("break");
}
addBreakClass();
var $paneTarget = $('#list-works');
$('.works-filters li a').click(function(){
var $target = $paneTarget.find('li:eq(1)');
$paneTarget.stop().scrollTo( $target , 800 );
addBreakClass();
});
Todo forma parte de un sistema de filtrado en un panel que hace slide. Cuando el usuario realiza una parte del slide (vertical) y este se encuentra a mitad del conteniod y filtra por tipos de trabajos lo envío de nuevo al principio, si no es así no vería algunos trabajos que se quedarían en la parte de arriba por el overflow. Y ahí lanzo de nuevo la función....per claro, meintras te escribo acabo de caer en que realmente cuando se filtran los items dejan de verse con lo cual quizá tenga que comprobar primero si son visibles y luego aplicar la función addBreakclass();
Cómo comprobarías la visibilidad de un elemento que se oculta con un display:none y luego lanzar la funcion para estos? No consigo ver bien tampoco la estructura del if para comprobar esto.
andrewman
Tienes que aplicarlo al elemento li, asumiendo que #item-works es el id del ul, tendrías entonces
$("#item-works li:nth-child(20n)").addClass("break");
Por otro lado, cuando usas "n" dentro de nth-child, éste es base cero, o sea te incluye el primer li (20 x 0), si no quieres eso, en vez de "20n" usa "20n+20".