单击外部取消按钮时阻止textarea上的更改事件

时间:2015-08-12 11:56:52

标签: javascript jquery ajax

我有以下情况:textarea当前绑定到change事件的自动保存。当textarea获得焦点时,它还会显示从底部悬挂的“保存”和“取消”按钮,以便用户可以点击一些内容,以防他们感到不舒服,只需移开控件或在外面点击它进入空白区域。

保存按钮基本上只是一个虚拟按钮。当用户单击它时,焦点自然会从textarea中丢失,并且触发更改事件。一切也适用于在textarea外部点击以进行保存。

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

这个例子可以在这里看到: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毫秒,更改有时会在取消之前触发..
  • 在textarea中存储保存ajax调用,并在调用cancel事件之前等待它完成或中止。

在允许更改事件发生之前,我是否可以优雅地检测到(将会)点击取消按钮?

3 个答案:

答案 0 :(得分:1)

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

但无论如何,测试事件的顺序,我发现了一个令人惊讶的事情: &#39;鼠标按下&#39; CANCEL按钮上的事件首先触发,然后才发生变化&#39;在textarea上的活动。尝试一下,也许这样有效,即使没有意义......

答案 1 :(得分:0)

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

仅在点击“保存”按钮后才能将值保存到数据库

答案 2 :(得分:0)

根据我自己的测试和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();
        })));
    }
});