Come modificare un elemento all'interno di una tabella.

Jakub Lemiszewski

Utente Attivo
5 Dic 2013
119
1
0
Salve,

Ho creato una tabella con dei valori e vorrei rendere i valori di una colonna modificabili.
Quello che vorrei con jquery e di cliccare sull'elemento della colonna che e un testo e trasformarlo in un input field per poter scrivere un nuovo testo. Mi potete mostrare un esempio che sono bloccato? Devo usare solo Jquery no plug ins. Grazie.
Qui sotto il codice che ho fatto:
HTML:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>PAGINATION</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">

    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" />



    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>




  <div class="bs-example" data-example-id="hoverable-table">
      <table class="table table-hover" id="transfers">
        <thead>
          <tr>
            <th>transfer #</th>
            <th>message</th>
            <th>update</th>
          </tr>
        </thead>
        <tbody id="tblTransfers"></tbody>
      </table>
    </div>


<button id="btnBack" input="button">BACK</button>
<button id="btnNext" input="button">NEXT</button>


    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>

    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>


    <script>
    var iLastElement = 0;

    /********************/
    // When the page loads
    $.get("ajax.php?from=0&to=5", function(sData){
      showTransactions(sData);
    });



    /********************/
    // clicking on NEXT
    $("#btnNext").click(function(){
      var sLink = "ajax.php?from="+iLastElement;
      $.get(sLink, function(sData){
        showTransactions(sData);
      });
      iLastElement += 3;
    });


    /********************/
    // show the data that arrived with AJAX
    function showTransactions(sData)
    {
      console.log(sData);
      var jData = JSON.parse(sData);
      if(jData.status){
        return;
      }
      console.log(jData[0].message);
      $("#tblTransfers").empty();
      for(var i = 0 ; i < jData.length; i++)
      {
        var sRow = '<tr><th scope="row">'+jData[i].id+'</th><td id="updateVal">'+jData[i].message+
        '</td><td><a href="#">edit</a></td></tr>';
        $("#tblTransfers").append(sRow);
        iLastElement++;
      }
    }


    $("#btnBack").click(function(){
     iLastElement = iLastElement - 6;
      var sLink = "ajax.php?from="+iLastElement;
      $.get(sLink, function(sData){
        showTransactions(sData);
      });
    });
    $( document ).on( "click", "#updateVal", function() {
      $(this).append('<input type="text">');
      console.log("Clcked...");
});
    </script>

  </body>
</html>
 

WmbertSea

Utente Attivo
28 Nov 2014
194
30
28
Ciao, premetto che si può fare in vari modi.

Prima un chiarimento. Gli id devono essere univoci. Non è consentito avere id uguali all'interno dello stesso documento html, questo è un grave errore. Per cui non puoi usare lo stesso id updateVal per le righe della tua tabella create nel ciclo for:
Codice:
var sRow = '<tr><th scope="row">'+jData[i].id+'</th><td id="updateVal">'+jData[i].message+
Puoi comunque usare una classe, in questo modo:
Codice:
var sRow = '<tr><th scope="row">'+jData[i].id+'</th><td class="updateVal">'+jData[i].message+
Fatta questa correzione, puoi usare uno script del genere:
Codice:
$("#tblTransfers").on( "click", "td.updateVal", editMode);        // applico handler click sulle voci
var appenaEditato;                                                // flag voce appena editata
function editMode() {                                             // funzione che attiva la modalità di editazione
  if (this === appenaEditato) {appenaEditato = null; return}      // esco se ho cliccato sulla stessa voce 
  appenaEditato = this;                                           // aggiorno flag
  var txt = $(this).text();                                       // testo del <td>
  $(this)                                                         // per questo <td>
  .html('<input value="'+txt+'">').children(0)                    // inserisco <input> e testo
  .click(function(e){e.stopPropagation();})                       // prevengo il bubbling al click su <input>
  .blur(function(){                                               // al blur (di <input>)
    $(this).replaceWith($(this).val());                           // rimpiazzo <input> col testo
  })                                                              //
  .focus()[0].setSelectionRange(0, txt.length);                   // seleziono intero testo per la modifica
};
In linea di massima, fa quello che hai chiesto.

Ho commentato quanto meglio possibile. Se comunque hai bisogno di chiarimenti, chiedi pure.

Infine tieni presente che non viene fatto alcun controllo su ciò che viene inserito nell'input dall'utente. Per questo motivo è possibile inserire qualsiasi cosa, tra cui tag html. Questo può comportare non pochi problemi nel momento in cui il testo viene reinserito dentro il <td>. Sarebbe quindi utile, se non necessario, filtrare in qualche modo l'input, ad esempio usando delle espressioni regolari durante la digitazione o eseguendo in qualche modo un escape. Devi comunque valutarlo tu, in base alle tue reali esigenze.

EDIT: aggiungo giusto una semplice soluzione per il controllo del testo:
Codice:
$("#tblTransfers").on( "click", "td.updateVal", editMode);        // applico handler click sulle voci
var appenaEditato;                                                // flag voce appena editata
function editMode() {                                             // funzione che attiva la modalità di editazione
  if (this === appenaEditato) {appenaEditato = null; return}      // esco se ho cliccato sulla stessa voce 
  appenaEditato = this;                                           // aggiorno flag
  var txt = $(this).text();                                       // testo del <td>
  $(this)                                                         // per questo <td>
  .html('<input value="'+txt+'">').children(0)                    // inserisco <input> e testo
  .click(function(e){e.stopPropagation();})                       // prevengo il bubbling al click su <input>
  .blur(function(){                                               // al blur (di <input>)
    $(this).parent().text($(this).val());                         // rimpiazzo <input> col testo
  })                                                              //
  .focus()[0].setSelectionRange(0, txt.length);                   // seleziono intero testo per la modifica
};
In questo modo il testo dell'input viene restituito (nel <td>) esattamente come testo e non come html. Dovrebbe risolvere il problema.
 
Ultima modifica:

Jakub Lemiszewski

Utente Attivo
5 Dic 2013
119
1
0
Grazie questo mi ha aiutato. Ce solo un problema quando faccio il refresh della pagina il testo all'interno della tabella ritorna al testo iniziale e non a quello modificato.
Hai una soluzione per questo?
Grazie mille.
Ciao, premetto che si può fare in vari modi.

Prima un chiarimento. Gli id devono essere univoci. Non è consentito avere id uguali all'interno dello stesso documento html, questo è un grave errore. Per cui non puoi usare lo stesso id updateVal per le righe della tua tabella create nel ciclo for:
Codice:
var sRow = '<tr><th scope="row">'+jData[i].id+'</th><td id="updateVal">'+jData[i].message+
Puoi comunque usare una classe, in questo modo:
Codice:
var sRow = '<tr><th scope="row">'+jData[i].id+'</th><td class="updateVal">'+jData[i].message+
Fatta questa correzione, puoi usare uno script del genere:
Codice:
$("#tblTransfers").on( "click", "td.updateVal", editMode);        // applico handler click sulle voci
var appenaEditato;                                                // flag voce appena editata
function editMode() {                                             // funzione che attiva la modalità di editazione
  if (this === appenaEditato) {appenaEditato = null; return}      // esco se ho cliccato sulla stessa voce 
  appenaEditato = this;                                           // aggiorno flag
  var txt = $(this).text();                                       // testo del <td>
  $(this)                                                         // per questo <td>
  .html('<input value="'+txt+'">').children(0)                    // inserisco <input> e testo
  .click(function(e){e.stopPropagation();})                       // prevengo il bubbling al click su <input>
  .blur(function(){                                               // al blur (di <input>)
    $(this).replaceWith($(this).val());                           // rimpiazzo <input> col testo
  })                                                              //
  .focus()[0].setSelectionRange(0, txt.length);                   // seleziono intero testo per la modifica
};
In linea di massima, fa quello che hai chiesto.

Ho commentato quanto meglio possibile. Se comunque hai bisogno di chiarimenti, chiedi pure.

Infine tieni presente che non viene fatto alcun controllo su ciò che viene inserito nell'input dall'utente. Per questo motivo è possibile inserire qualsiasi cosa, tra cui tag html. Questo può comportare non pochi problemi nel momento in cui il testo viene reinserito dentro il <td>. Sarebbe quindi utile, se non necessario, filtrare in qualche modo l'input, ad esempio usando delle espressioni regolari durante la digitazione o eseguendo in qualche modo un escape. Devi comunque valutarlo tu, in base alle tue reali esigenze.

EDIT: aggiungo giusto una semplice soluzione per il controllo del testo:
Codice:
$("#tblTransfers").on( "click", "td.updateVal", editMode);        // applico handler click sulle voci
var appenaEditato;                                                // flag voce appena editata
function editMode() {                                             // funzione che attiva la modalità di editazione
  if (this === appenaEditato) {appenaEditato = null; return}      // esco se ho cliccato sulla stessa voce 
  appenaEditato = this;                                           // aggiorno flag
  var txt = $(this).text();                                       // testo del <td>
  $(this)                                                         // per questo <td>
  .html('<input value="'+txt+'">').children(0)                    // inserisco <input> e testo
  .click(function(e){e.stopPropagation();})                       // prevengo il bubbling al click su <input>
  .blur(function(){                                               // al blur (di <input>)
    $(this).parent().text($(this).val());                         // rimpiazzo <input> col testo
  })                                                              //
  .focus()[0].setSelectionRange(0, txt.length);                   // seleziono intero testo per la modifica
};
In questo modo il testo dell'input viene restituito (nel <td>) esattamente come testo e non come html. Dovrebbe risolvere il problema.
 

WmbertSea

Utente Attivo
28 Nov 2014
194
30
28
Dipende da ciò che devi fare.

Se i dati devono essere salvati sul server, per essere disponibili in seguito, ti servirà un database con relativo script lato server che lo interroghi e aggiorni i nuovi dati. Eventualmente puoi integrarci AJAX per avere un sistema più performante.

Se ti serve solo avere dei dati disponibili finché non chiudi il browser, puoi usare delle variabili di sessione gestite con linguaggio lato server, o dei cookie gestiti con javascript (quindi lato client).

Ad ogni modo si tratta di un argomento che prescinde dall'oggetto di questa discussione, sarebbe quindi opportuno aprire una nuova discussione.

PS: Ti prego, quando rispondi non citare l'intero post se non è necessario. Grazie.