jQuery/Javascript: búsqueda y reemplazo más complejos en un documento HTML

He hecho algunas cosas en jQuery y Javascript antes, pero desafortunadamente no soy un experto. No pude encontrar ninguna pista sobre cómo realizar mi tarea utilizando la menor cantidad de recursos posible. Ustedes probablemente me pueden ayudar:

Esto es lo que quiero hacer:

Quiero encontrar (usando expresiones regulares) todos los elementos similares al código BB en una página que se vea así:

[índice aquí=parámetro randomdata]

Luego quiero reemplazar cada uno de ellos con el contenido que recibo de una llamada ajax que se ve así:

call.php?ndex=here=parámetro datos aleatorios

o cualquier parámetro que recoja dentro de la etiqueta [ndex] correspondiente.

Aquí está mi solución/proceso de pensamiento hasta ahora:

$(document).ready(function() {
    var pattern = /\[ndex\s+(.*?)\]/mg;
    var documentText = $(document.body).text();
    var matches = documentText.match(pattern);

    $('*').each(function () { 
        var searchText = this;
        if ($(searchText).children().length == 0) { 
            $.each(matches, function() {
                //here is where I would need to check for a match and make a call 
                }
            }); 
        } 
    });
});

Realmente no sé cómo trabajar desde aquí. Mi boceto parece realmente torpe y complicado. Debe haber una solución más elegante y directa.

Muchas gracias chicos por su ayuda. :)

preguntado el 30 de junio de 12 a las 17:06

No estoy seguro de que esta sea la manera de lograr lo que quieres. Debería reemplazar el lado del servidor de texto, no a través de llamadas ajax:

Gracias por su respuesta. Necesito hacer llamadas ajax porque el documento que tiene reemplazos no necesariamente se ejecuta en un servidor con php. -

2 Respuestas

Yo haría algo como esto:

function ndex_treat(n) {
  // If element is ELEMENT_NODE
  if(n.nodeType==1)
  {
    // If element node has child, we pass them to function ndex_treat
    if(n.hasChildNodes())
      for(var i= 0; i<n.childNodes.length; i++)
        ndex_treat(n.childNodes[i]);
  }
  // If element is TEXT_NODE we replace [ndex ...]
  else if(n.nodeType==3)
  {
    var matches, elemNdex, elemText;
    // While there is one
    while(/\[ndex\s+(.*?)\]/m.test(n.nodeValue))
    {
      // Taking what's before (matches[1]), the "attribute" (matches[2]) and what's after (matches[3])
      matches= n.nodeValue.match(/^([\s\S]*?)\[ndex\s+(.*?)\]([\s\S]*)$/m)
      // Creating a node <span class="ndex-to-replace" title="..."></span> and inserting it before current text node element
      elemNdex= document.createElement("span");
      elemNdex.className= 'ndex-to-replace';
      elemNdex.title= matches[2];
      n.parentNode.insertBefore(elemNdex, n);
      // If there was text before [ndex ...] we add it as a node before
      if(matches[1]!=="")
      {
        elemText = document.createTextNode(matches[1]);
        elemNdex.parentNode.insertBefore(elemText, elemNdex);
      }
      // We replace content of current node with what was after [ndex ...]
      n.nodeValue=matches[3];
    }
  }
}

$(function(){
  // Get the elements we want to scan ( being sharper would be better )
  $('body').each(function(){
    // Passing them to function ndex_treat
    ndex_treat(this);        
  });

  // Make the ajax calls
  $('.ndex-to-replace').each(function(){
    // Don't know if necessary
    var current= this;
    $.get('call.php?ndex='+encodeURIComponent(this.title),function(data){
      $(current).replaceWith(data);
    });
  });
});

lo reemplacé por nodo en lugar de por jquery porque me parece bastante malo trabajar en textNode con jquery. si no le importa y prefiere hacerlo de la manera bárbara, puede reemplazar toda la primera parte simplemente con:

$(function(){
  // Get the elements we want to scan ( being sharper would be better )
  $('body').each(function(){
    // With no " in argument of [ndex ...]
    $(this).html( $(this).html().replace(/\[ndex\s+([^"]*?)\]/mg,'<span class="ndex-to-replace" title="$1"></span>') );
    // With no ' in argument of [ndex ...]
    //$(this).html( $(this).html().replace(/\[ndex\s+([^']*?)\]/mg,'<span class="ndex-to-replace" title='$1'></span>') );
  });

  // Make the ajax calls
  /* ... */
});

Respondido el 30 de junio de 12 a las 18:06

Muchísimas gracias. Has dado una respuesta que funciona con copiar y pegar. ¡Eso es genial! :) Sin embargo, intentaré trabajar con la solución sugerida por Pablo. Hasta que lo tenga funcionando, solo usaré su solución. Me has ayudado a comprender mucho mejor la forma en que funciona la búsqueda/reemplazo en Javascript, ¡gracias por tu ayuda! - Macks

Mi consejo es mantener las llamadas ajax al mínimo. Realice la búsqueda en primer lugar, y en otra ronda reemplace cada objeto con los datos correspondientes.

$(document).ready(function() {
var pattern = /\[ndex\s+(.*?)\]/mg;
var documentText = $(document.body).text();
var matches = documentText.match(pattern);


$.ajax({ 
       url:'call.php',
       method:'POST',
       data: matches,
       success: function(data){
          //replace every matched element with the corresponding data
       });


}); 

Sin embargo, tendrá que modificar su call.php para tener esto en cuenta, pero está ahorrando muchas llamadas al servidor y, por lo tanto, tiempo.

Respondido el 30 de junio de 12 a las 17:06

¡Gracias! ¡Esto es genial! Estoy un poco preocupado por pasar objetos javascript a un archivo php, pero estoy bastante seguro de que descubriré cómo operar eso. Sin embargo, mi pregunta real es: necesito reemplazar el código bb con el código html (que es generado por mi archivo php) y no estoy seguro de cómo reemplazar el texto del documento con el código html correspondiente. es decir derivado de un objeto (?). ¿Algun consejo? - Macks

solo puedes hacer data:{ndex:matches} tendrá acceso a él como $_POST['ndex'] una matriz en la página php, en cuanto al reemplazo por nodo dom o HTML interno (o jquery html() equivalente) - arco

Muchas gracias chicos, sois geniales! :) - Macks

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.