【问题标题】:Function works in Chrome/Safari but not Firefox功能适用于 Chrome/Safari 但不适用于 Firefox
【发布时间】:2017-11-25 22:13:45
【问题描述】:

所以我有一个表格,您可以在其中检查表格行,它将获取该行中每个单元格的值,并显示另一个名为 Quantity # 的列。 Quantity # 列包含 type="number" 输入。输入数字后,用户将能够刷新页面,Quantity # 列和输入的值都将保持可见。用户还可以点击“结帐”按钮,然后它将该数据发布到电子邮件正文中。

这一切在 Safari 和 Google Chrome 中运行良好。但是,在 Firefox 中,如果您在输入中输入一个值然后刷新,例如,该值将不再在输入中。此外,如果您点击 Checkout 按钮并将数据粘贴到电子邮件中,它也不会像在 Safari/Chrome 中那样粘贴输入值。

为什么会这样?我可以做些什么来解决 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:me@example.com" + "?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:

$(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>

编辑:

【问题讨论】:

  • FireFox 是否给出任何控制台错误?
  • 我用错误截图进行了编辑
  • 这些是与 CSS 相关的错误。是否有任何 JavaScript 错误?
  • 不,不是我看到的
  • 我确保 JS 错误/警告过滤器已打开并且我没有收到任何错误

标签: javascript jquery html google-chrome firefox


【解决方案1】:

@Rataiczak24,看来 FF 不会以与其他浏览器完全相同的方式触发其 blur 事件。

当前存储行的状态是为了响应quantity_num 输入的blur 事件。出于性能原因,我希望您不需要这样做,但您需要响应“更改”事件而不是“模糊”事件。 quantity_num 输入的响应性可能会受到影响。

这应该可以解决报告的两个问题。

还有一些其他的东西:

有了我的RowData 对象,您不应该直接与sessionStorage 交互(当然,除非您将它用于其他目的)。所有交互都应该通过 RowData API,RowData() 之外的所有代码都不应读取或写入 sessionStorage

如果在任何时候您需要确信表行可能需要恢复到存储在sessionStorage 中的状态,然后调用RowData.readRow(tr) 或调用restoreVisibleRows() 来恢复所有可见行。

如果您按照我的说明“在每次分页/搜索完成时调用此函数”,并在页面加载时调用 restoreVisibleRows();,则不需要在其他地方解决行恢复问题。

上面$(function() { var showQuantityHeader = false; ...; ...; ...; }); 中的几乎所有内容都是不必要的。 RowData 中唯一没有满足的部分是 $('#merchTable').find('th.num').show();。为此,您只需在restoreVisibleRows() 中添加几行,类似地响应选中/取消选中的复选框。

所以,总而言之,我的代码建议的底部应该如下所示:

$('#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:me@example.com" + "?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();
    }
}

您自己的$(".check").change(function(){...})(如果仍然存在)可以删除。

【讨论】:

  • 你好!感谢您的回复!当我尝试使用微调器为输入设置数字时,它说$tr 未在第二个on change 函数下的RowData.writeRow($tr.get(0)); 中定义
  • 实际上,看起来我明白了……你说得对,FF 似乎没有触发blur 事件。我所做的只是将blur 事件更改为change 事件,它现在似乎可以在chrome、safari 和firefox 上运行!谢谢!
猜你喜欢
  • 2013-06-30
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多