【问题标题】:Prevent change event on a textarea when clicking an external cancel button单击外部取消按钮时防止文本区域上的更改事件
【发布时间】:2015-08-12 11:56:51
【问题描述】:

我有以下情况:文本区域有一个自动保存当前绑定到更改事件。当 textarea 获得焦点时,它还会显示悬挂在底部的 Save 和 Cancel 按钮,以便用户可以单击某些内容,以防他们在离开控件或单击控件外部的空白区域时感到不舒服。

保存按钮基本上只是一个虚拟按钮。当用户点击它时,焦点自然会从 textarea 中丢失,并触发 change 事件。在文本区域之外单击以进行保存也一切正常。

问题在于取消按钮。单击取消按钮会导致文本区域失去焦点,从而触发更改事件,该事件在按钮的单击事件之前处理。由于几乎同时将保存和取消事件发送到服务器,因此无法确定它们的处理顺序。

例子可以看这里:http://jsfiddle.net/vwu79wd1/1/

HTML

<div class="largerEventContainer">
    <div class="inlineControls" style="width:200px;">
    <textarea name="SomeText" data-prevvalue="Original Text" style="width:100%">Original Text</textarea>
    </div>
</div>
<div id="log"></div>

CSS

.inlineControls {
    position:relative;
    margin-bottom:1em;
}

.inlineControls textarea, .inlineControls input {
    margin-bottom: 0px;
}

.inlineControls textarea:focus ~ .saveOptions {
    display: block;
}

.saveOptions:hover {
    display:block;
}

.saveOptions {
    display:none;
    position:absolute; 
    right:0px; 
    top:100%;
    background-color: #f0f0f0;
    border: 1px solid #ccc;
    padding: 3px;
    outline: none;
    border-top:none;
    border-radius: 0 0 3px 3px;
}

Javascript

$('.largerEventContainer').on('change', 'input, textarea', function () {
    $('#log').append('<div>saving</div>');
});

$(document).on('focus', '.inlineControls textarea', function () {
    var $control = $(this)

    if ($(this).closest('.inlineControls').find('.saveOptions').length == 0) {
        $(this).closest('.inlineControls')
            .append($(document.createElement('div'))
                .addClass('saveOptions')
                .append($(document.createElement('span'))
                    .css('padding', '4px')
                    .html('Save')
                    .click(function () {
                        $(this).closest('.saveOptions').remove();
                    }))
                    .append($(document.createElement('span'))
                        .css('padding', '4px')
                        .html('Cancel'))
                        .click(function () {
                            var $control =     $(this).closest('.inlineControls').find('textarea')
                            $control.val($control.data('prevvalue'));
                            $('#log').append('<div>reset</div>');
                            $(this).closest('.saveOptions').remove();
            }));
    }
});

我尝试过或考虑过的东西,但因为不起作用或太笨重而被驳回

  • 在更改事件中插入延迟,以允许首先发生取消。奇怪的是,延迟 100 毫秒,更改有时仍会在取消之前触发..
  • 将保存 ajax 调用存储在文本区域中,等待它完成或中止,然后再调用取消事件。

有什么方法可以优雅地检测到在允许更改事件进行之前(将)单击取消按钮?

【问题讨论】:

    标签: javascript jquery ajax


    【解决方案1】:

    我认为解决方案应该是一种不同的方法,例如仅在单击“保存”按钮时实际保存更改,或者在提交之前使用本地存储来保存更改。显然,您应该在用户尝试从页面移出之前发出警报。

    但无论如何,测试事件的顺序,我发现了一件令人惊讶的事情: CANCEL 按钮上的 'mousedown' 事件首先触发,然后是 textarea 上的 'change' 事件。试试吧,也许这行得通,即使没有意义......

    【讨论】:

    • 有趣的方法,但我不会打赌,因为我怀疑这是保证在所有浏览器上以相同顺序执行的官方行为。
    • 仅保存按钮单击对于在字段之间切换或快速单击有点尴尬。我们已经有了自动保存,但我想为用户提供一种简单的取消方式,而不是让保存变得更加困难;)。还发现了mousedown,它实际上似乎工作得很好。只是试图找到一些官方文档说它是一个有效的案例,而不是一个 Firefox 怪癖。在 mousedown 中将数据更改回原始数据会导致更改事件根本不发生(因为数据没有更改)。很可能正是我需要的。
    【解决方案2】:

    我建议您在 mouseOut 事件时将文本区域的内容临时保存到变量中。

    只有在点击“保存”按钮后才将值保存到数据库中

    【讨论】:

    • 这样做会导致难以在字段之间切换或单击以进行快速输入。不太好用。如果用户忘记点击保存怎么办?然后数据就丢失了。
    • 提示警告消息以提供足够的信息以防止数据丢失..或调用保存函数到该页面的 lostfocus 事件。有时我在我的 java 应用程序中使用此方法..试试看..希望这会奏效。当然..运气好
    【解决方案3】:

    根据我自己的测试和 Jav Rok 的回答,mousedown 似乎是要走的路。浏览器的行为确实会有所不同,具体取决于所执行的操作。如果该值恢复为原始值(而不是之前的值),则 Firefox 将触发更改事件,但 chrome、IE 和 iPad Safari 不会。此外,IE 和 iPad Safari 需要手动调用 .blur() ,否则它实际上不会离开控件(在 iPad 上尤其烦人,因为屏幕键盘)。

    因此,通过一些小的调整,可以使用以下小提琴达到可接受的行为:http://jsfiddle.net/Lcyte5h5/14/

    取消按钮处理程序如下:

    $('.largerEventContainer').on('change', 'input, textarea', function () {
        $('#log').append('<div>change</div>');
        if ($(this).val() != $(this).data('prevvalue')) {
        	$('#log').append('<div>saving</div>');
            $(this).data('prevvalue', $(this).val())
        }
    });
    
    
    $(document).on('focus', '.inlineControls textarea', function () {
        var $control = $(this)
    
        if ($(this).closest('.inlineControls').find('.saveOptions').length == 0) {
            $(this).closest('.inlineControls')
                .append($(document.createElement('div'))
                        .addClass('saveOptions')
                        .append($(document.createElement('span'))
                            .css('padding', '4px')
                            .html('Save')
                            .click(function () {
                                $(this).closest('.saveOptions').remove();
            }))
                .append($(document.createElement('span'))
                    .css('padding', '4px')
                    .html('Cancel')
                    .on('mousedown', function () {
                        var $control = $(this).closest('.inlineControls').find('textarea')
                        $control.val($control.data('prevvalue'));
        		        $('#log').append('<div>reset</div>');
                        $control.blur();
                        $(this).closest('.saveOptions').remove();
            })));
        }
    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 2019-07-08
      • 2021-09-04
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多