2017-06-22 1 views
0

J'ai donc une table où vous pouvez vérifier une ligne de table et elle obtiendra les valeurs de chaque cellule de cette ligne et affichera également une autre colonne nommée Quantity #. La colonne Quantity # contient une entrée type="number". Après avoir entré un nombre, un utilisateur sera en mesure d'actualiser la page et la colonne Quantity # et la valeur entrée dans l'entrée restera visible. Un utilisateur peut également cliquer sur un bouton "Commander" et il affichera ces données dans un corps de courrier électronique.Fonctionne dans Chrome/Safari mais pas Firefox

Tout fonctionne très bien dans Safari et Google Chrome. Cependant, dans Firefox, si vous entrez une valeur dans l'entrée et que vous l'actualisez par exemple, la valeur ne sera plus dans l'entrée. En outre, si vous cliquez sur le bouton Commander et que vous collez les données dans l'e-mail, la valeur d'entrée ne sera pas collée comme dans Safari/Chrome.

Pourquoi est-ce et que puis-je faire pour résoudre ce problème dans Firefox?

JavaScript:

$(function($) { 
    var RowData = (function(storage, storageKey) { 
     var rowData = readFromSession(); 
     var dataItems = ['loc', 'rp-code', 'sku', 'special-id', 'description', 'quantity', 'unit']; 
     var emailDelimiters = { 
      'row': '%0D%0A', 
      'dataItem': '\xa0\xa0' 
     }; 

     function readFromSession() { 
      return JSON.parse(storage.getItem(storageKey) || '{}'); 
     } 
     function writeToSession() { 
      storage.setItem(storageKey, JSON.stringify(rowData)); 
     } 
     function writeRow(tr) { 
      var $tr = $(tr), 
       id = $tr.prop('id'); 
      if($tr.find('.check').is(':checked')) { 
       rowData[id] = {}; 
       for(var i=0; i<dataItems.length; i++) { 
        rowData[id][dataItems[i]] = $tr.find('.' + dataItems[i]).text(); 
       } 
       rowData[id].quantity_num = $tr.find('.spinner').val(); 
      } else { 
       delete rowData[id]; 
      } 
      writeToSession(); 
     } 
     function readRow(tr) { 
      // restore tr's checkbox and spinner value from stored data 
      var $tr = $(tr), 
       id = $tr.prop('id'), 
       row = rowData[id]; 
      if(row) { 
       $tr.find('.check').prop('checked', true).end() 
        // .find('.spinner').spinner('value', row.quantity_num); // if using spinner widget 
        .find('.spinner').val(row.quantity_num); // if using HTML5 <input type="number"> 
      } 
     } 
     function toEmailString() { 
      return $.map(rowData, function(row, id) { 
       return $.map(row, window.encodeURIComponent).join(emailDelimiters.dataItem); 
      }).join(emailDelimiters.row); 
     } 
     // selectively expose functions as methods of RowData 
     return { 
      'writeRow': writeRow, 
      'readRow': readRow, 
      'toEmailString': toEmailString 
     }; 
    })(window.sessionStorage, 'checkedRowData'); 

    $('#merchTable').on('change', '.check', function() { // on changing a table row ... 
     RowData.writeRow($(this).closest('tr').get(0)); // ... set the corresponding row object in RowData and sessionStorage 
    }).on('blur', '.spinner', function() { // on leaving a spinner widget 
     RowData.writeRow($(this).closest('tr').get(0)); 
    }); 
    $('#checkout').on('click', function() { // on clicking the [Checkout] button 
     var link = "mailto:[email protected]" + "?subject=" + encodeURIComponent("Order") + "&body=" + RowData.toEmailString(); 
     console.log(link); 
     window.location.href = link; 
    }); 

    // Call this function on completion of every pagination/search 
    function restoreVisibleRows() { 
     $('#merchTable tbody tr').get().forEach(RowData.readRow); 
    } 

    restoreVisibleRows(); 

}); 

JavaScript qui maintient la valeur d'entrée et la quantité colonne # affichée lors de l'actualisation:

$(function(){ 
    var showQuantityHeader = false; 
    $(':checkbox').each(function() { 
     // Iterate over the checkboxes and set their "check" values based on the session data 
     var $el = $(this); 
     //console.log('element id: ',$el.prop('id'),' sessionStorage[id]: ',sessionStorage[$el.prop('id')]); 
     $el.prop('checked', sessionStorage[$el.prop('id')] === 'true'); 
     if ($el.prop('checked')) {   
      //show the quantity cell in the column under header with class num 
      $el.closest('tr').find('td.quantity_num').toggle(this.checked); 
      showQuantityHeader = true; 
      //setupSpinner(this); 
      var quantity = sessionStorage['value_'+$el.prop('id')]; 

     } 
    }); 

    if (showQuantityHeader) { 
      $('#merchTable').find('th.num').show(); 
     //console.log('header with class num: ',$('#merchTable').find('th.num')); 
    } 

    $('input:checkbox').on('change', function() { 
     // save the individual checkbox in the session inside the `change` event, 
     // using the checkbox "id" attribute 
     var $el = $(this); 
     sessionStorage[$el.prop('id')] = $el.is(':checked'); 
     console.log($el); 
    }); 
}); 

HTML:

<section id="checkout-btn"> 
<button id="checkout" name="order">Checkout</button> 
</section> 

<br> 

<table id="merchTable" cellspacing="5" class="sortable"> 
    <thead> 
     <tr class="ui-widget-header"> 
      <th class="sorttable_nosort"></th> 
      <th class="sorttable_nosort">Loc</th> 
      <th class="merchRow">Report Code</th> 
      <th class="merchRow">SKU</th> 
      <th class="merchRow">Special ID</th> 
      <th class="merchRow">Description</th> 
      <th class="merchRow">Quantity</th> 
      <th class="sorttable_nosort">Unit</th> 
      <th style="display: none;" class="num">Quantity #</th> 
     </tr> 
    </thead> 
    <tbody> 

     <?php foreach ($dbh->query($query) as $row) {?> 

     <tr id="<?php echo intval ($row['ID'])?>"> 
      <td class="ui-widget-content"><input type="checkbox" class="check" name="check" id="checkid-<?php echo intval ($row['ID'])?>"></td> 
      <td class="loc ui-widget-content" data-loc="<?php echo $row['Loc'] ?>"><input type="hidden"><?php echo $row['Loc'];?></td> 
      <td class="rp-code ui-widget-content" align="center" data-rp-code="<?php echo $row['Rp-Code'] ?>" id="rp-code-<?php echo intval ($row['Rp-Code'])?>"><?php echo $row['Rp-Code'];?></td> 
      <td class="sku ui-widget-content" data-sku="<?php echo $row['SKU'] ?>" id="sku-<?php echo intval ($row['SKU'])?>"><?php echo $row['SKU'];?></td> 
      <td class="special-id ui-widget-content" data-special-id="<?php echo $row['Special-ID'] ?>" align="center" id="special-id-<?php echo intval ($row['Special-ID'])?>"><?php echo $row['Special-ID'];?></td> 
      <td class="description ui-widget-content" data-description="<?php echo htmlspecialchars($row['Description']) ?>" id="description-<?php echo intval ($row['Description'])?>"><?php echo $row['Description'];?></td> 
      <td class="quantity ui-widget-content" data-quantity="<?php echo $row['Quantity'] ?>" align="center" id="quantity-<?php echo intval ($row['Quantity'])?>"><?php echo $row['Quantity'];?></td> 
      <td class="unit ui-widget-content" data-unit="<?php echo $row['Unit'] ?>" id="unit-<?php echo intval ($row['Unit'])?>"><?php echo $row['Unit'];?></td> 
      <td style="display: none;" class="quantity_num ui-widget-content"><input type="number" min="1" max="<?php echo $row['Quantity'];?>" step="1" style="width: 100px;" class="spinner" /></td> 
     </tr> 

    <?php } ?> 

    </tbody> 
</table> 

EDIT: Console errors

+0

Est-ce que FireFox donne des erreurs de console? – samanime

+0

J'ai fait un montage avec une capture d'écran des erreurs – Rataiczak24

+0

Ce sont des erreurs liées à CSS. Y a-t-il des erreurs JavaScript? – str

Répondre

1

@ Rataiczak24, il semblerait que FF ne déclenche pas son événement blur exactement de la même manière que les autres navigateurs.

Le stockage de l'état d'une ligne est actuellement effectué dans la réponse quantity_num pour les événements blur. Pour des raisons de performances, j'espérais que vous n'auriez pas besoin de faire cela, mais vous devez répondre à l'événement 'change' au lieu de l'événement 'blur'. La réactivité de l'entrée quantity_num peut en souffrir.

Cela devrait résoudre les deux problèmes signalés.

Il y a d'autres choses aussi:

Avec mon objet RowData en place, vous ne devriez pas être Interagir avec sessionStorage directement (à moins bien sûr que vous l'utiliser pour d'autres fins). Toutes les interactions doivent se faire via l'API RowData, et tout le code en dehors de RowData() ne doit ni lire ni écrire à sessionStorage.

Si à tout moment vous avez besoin de confiance qu'une ligne de table peut-être besoin d'être restauré à l'état stocké dans sessionStorage, puis appelez RowData.readRow(tr), ou appelez restoreVisibleRows() pour restaurer toutes les lignes visibles. Si vous suivez mon instruction "Appeler cette fonction à la fin de chaque pagination/recherche" et appelez le restoreVisibleRows(); au chargement de la page, la restauration de ligne ne doit pas être traitée ailleurs.

Presque tout ce qui se trouve dans votre $(function() { var showQuantityHeader = false; ...; ...; ...; }); ci-dessus n'est pas nécessaire. La seule partie qui n'est pas prévue dans RowData est $('#merchTable').find('th.num').show();. Pour cela, il vous suffit d'ajouter quelques lignes à restoreVisibleRows(), et de la même manière en réponse aux cases cochées/décochées.

Alors, devrait ressembler à ceci tout-en-tout, la partie inférieure de ma suggestion de code:

$('#merchTable').on('change', '.check', function() { // on cliking a checkbox 
    var $this = $(this), 
     $tr = $this.closest('tr'); 
    $tr.find('td.quantity_num').toggle(this.checked); 
    $this.closest('table').find('th.num').toggle($('input:checkbox:checked', '#merchTable tbody').length > 0); 
    RowData.writeRow($tr.get(0)); // store row state 
}).on('change', '.spinner', function() { // on changing the value of a "spinner" widget 
    RowData.writeRow($this.closest('tr').get(0)); // store row state 
}); 
$('#checkout').on('click', function() { // on clicking the [Checkout] button 
    setTimeout(function() { 
     var link = "mailto:[email protected]" + "?subject=" + encodeURIComponent("Order") + "&body=" + RowData.toEmailString(); 
     console.log(link); 
     window.location.href = link; 
    }, 0); 
}); 

function restoreVisibleRows() { 
    $('#merchTable tbody tr').get().forEach(RowData.readRow); 
    if($('input:checkbox:checked', '#merchTable tbody').length > 0) { 
     $('#merchTable').find('th.num').show(); 
    } else { 
     $('#merchTable').find('th.num').hide(); 
    } 
} 

Votre propre $(".check").change(function(){...}) (si elle existe encore) peut être retiré.

+0

Hey encore! Merci pour la réponse! Il est dit que '$ tr' n'est pas défini à' RowData.writeRow ($ tr.get (0)); 'sous la deuxième fonction' on change' quand j'essaie d'utiliser le compteur pour définir un numéro pour l'entrée – Rataiczak24

+0

, on dirait que je l'ai eu ... tu avais raison de dire que FF ne semble pas déclencher des événements «flous». Tout ce que j'ai fait était de changer l'événement 'blur' en un événement' change' et il semble fonctionner sur chrome, safari et firefox maintenant! Merci! – Rataiczak24