Ver Mensaje Individual
  #11 (permalink)  
Antiguo 05/12/2015, 14:22
Avatar de Alexis88
Alexis88
Philosopher
 
Fecha de Ingreso: noviembre-2011
Ubicación: Tacna, Perú
Mensajes: 5.552
Antigüedad: 13 años
Puntos: 977
Respuesta: Funcion toggle ¿2 clicks para funcionar? Mi intención es en un click

Buen punto el tocado por edel. Si habrá varios comentarios, no te conviene trabajar con un id puesto que no puede repetirse. Como bien te comentan, dependerá de la estructura de tu DOM para poder determinar la mejor manera de implementar lo que necesitas.

Una estructura que se me ocurre consiste en lo siguiente:
Código HTML:
Ver original
  1. <section class="comentario">
  2.     <article>
  3.         El comentario
  4.     </article>
  5.     <div class="respuestas"></div>
  6.     <div class="respuesta">
  7.         <span class="toggle">Responder</span>
  8.         <form>
  9.             <textarea></textarea>
  10.             <input type="submit" />
  11.         </form>
  12.     </div>

Básicamente, se trata de una sección (también puede ser un <div>) que contiene un artículo en el cual irá el comentario principal, una división para las respuestas que pueda tener y otra con un botón y un formulario para escribir la respuesta. La idea es que el formulario esté oculto y cuando se pulse el botón, se muestre y el botón se oculte. Una vez que se envíe la respuesta, se oculta el formulario y se muestra el botón.

Como algunos de los elementos son dinámicos y puede haber muchas respuestas, lo conveniente es delegar los eventos al documento. Esto sería más o menos así (puede variar según la estructura que tengas):
Código Javascript:
Ver original
  1. document.addEventListener("click", function(event){
  2.     if (event.target.className == "toggle"){
  3.         var form = event.target.parentNode.querySelector("form"),
  4.             toggle = event.target;
  5.        
  6.         if (!form.offsetHeight){
  7.             toggle.innerHTML = "Cancelar";                     
  8.             form.style.display = "block";
  9.             form.style.opacity = 1;    
  10.             form.querySelector(".mensaje").focus();
  11.         }
  12.         else{
  13.             toggle.innerHTML = "Responder";
  14.             form.style.opacity = 0;
  15.             setTimeout(function(){     
  16.                 form.style.display = "none";
  17.             }, 150);
  18.             form.reset();
  19.         }
  20.     }
  21. }, false);
  22.  
  23. document.addEventListener("submit", function(event){
  24.     event.preventDefault();
  25.     var self = event.target,
  26.         toggle = self.parentNode.querySelector(".toggle"),     
  27.         respuestas = self.parentNode.parentNode.querySelector(".respuestas"),
  28.         respuesta = self.querySelector(".mensaje").value,
  29.         parrafo = document.createElement("p");
  30.        
  31.     if (respuesta.length){
  32.         parrafo.innerHTML = respuesta;
  33.         respuestas.appendChild(parrafo);   
  34.         toggle.innerHTML = "Responder";
  35.         self.style.opacity = 0;
  36.         setTimeout(function(){     
  37.             self.style.display = "none";
  38.         }, 150);       
  39.         self.reset();
  40.     }
  41.     else{
  42.         self.querySelector(".mensaje").focus();
  43.     }
  44. }, false);

En el primer bloque, detectamos la ejecución del evento click en el documento, tomando al elemento directamente afectado mediante la propiedad event.target y comprobando que su clase sea "toggle". Si esto se cumple, quiere decir que se le dio un clic a cualquiera de los botones para responder. Dentro del bloque de instrucciones, tomamos al formulario, buscándolo en el elemento padre del botón (propiedad parentNode), además del propio botón. Enseguida, compruebo si la altura del formulario es mayor a cero (recordemos que el cero se evalúa como falso, por lo que una cifra distinta será el caso contrario, es decir, verdadero); de ser así, cambio el texto del botón por el de "Cancelar", hago visible al formulario y le doy el enfoque al área de texto del formulario; caso contrario, es decir, si el usuario cancela la respuesta, cambio el texto del botón por el de "Responder", oculto al formulario y lo limpio mediante el método .reset(). Cuando un elemento es oculto por el valor none asignado a la propiedad display, este no tiene presencia en el formulario, por lo que si posee una altura, quiere decir que es visible.

Cabe señalar que utilizo las propiedades opacity y display para darle un efecto especial al momento de mostrar u ocultar al botón o al formulario. La presencia del temporizador (método setTimeout()), se debe a que utilizo la propiedad transition de CSS3 para dilatar unas milésimas de segundo el cambio de opacidad. Si deseas, puedes trabajar solo con la propiedad display.

En el segundo bloque, detectamos la ejecución del evento submit en el documento, el cual se produce cuando se inicia el procesamiento de datos de un formulario. Acto seguido, cancelamos la ejecución de dicho evento mediante el método .preventDefault() para evitar que se recargue la página y se realice el envío. A continuación, tomamos a distintos elementos, como el formulario (que es el elemento en el cual se produjo el evento), el botón para mostrar el formulario, el bloque de respuestas, la respuesta escrita por el usuario y creamos un párrafo en el cual se insertará la respuesta. Si la longitud de la respuesta es superior a cero (el mismo caso del primer bloque de código, solo que ahora se trata de longitud y no de altura), insertamos la respuesta en el párrafo recién creado y lo adherimos al bloque de respuestas mediante el método .appendChild(). Finalmente, cambiamos el texto del formulario por el de "Responder", ocultamos a este último y lo limpiamos para que cuando se desee realizar una futura respuesta al mismo comentario, el área de texto esté vacío. Si no se ha escrito la respuesta pero se pulsa el botón de envío, solo se le dará el enfoque al área de texto.

DEMO

Y otro DEMO que muestra la fecha y hora de cada respuesta.

Como trabajamos con clases y delegando los eventos, puedes tener uno o más comentarios con una o más respuestas. Y si deseas guardar la información en una base de datos, puedes aprovechar que se cancela el evento submit para realizar una petición asíncrona (AJAX).

P. D.: Disculpa si el diseño no es adaptable; lo hice un poco rápido para efectos del ejemplo.

Un saludo
__________________
«Juro por mi vida y mi amor por ella, que jamás viviré para el provecho de otro hombre, ni le pediré a otro hombre que viva para el mío».

Ayn Rand

Última edición por Alexis88; 05/12/2015 a las 16:13 Razón: Mejora