请原谅我,如果这很简单 - 我已经离开电脑和JS一个月了,所以这项任务对我来说似乎是不可能的,我知道它不应该是。
我能想到解释它的最快方法是将它放在代码中,使用注释来解释它是如何工作的。我将在这些评论中指出哪些是我无法弄清楚的部分。
我的文字字段看起来不可编辑,旁边有一个“编辑”按钮,点击后会变成“保存”按钮,并使文本字段看起来可编辑。
$(".edit_btn").click(function() {
// make the associated text field look editable, and change this 'edit'
// button into a 'save' button. Then place focus on the text in
// in the field.
});
$(".save_btn").click(function() {
// if (value in associated text field has changed from when page loaded)
// submit the form and save this new text
// else
// revert to non-editable mode (hide this 'save' button,
// and show 'edit' button)
});
一切正常。但是,如果用户离开可编辑的文本字段,我希望能够检测他们是否已离开字段以单击“保存”按钮,或者只是单击页面上的任何其他位置。因此,在该字段的'blur'事件处理程序中,我需要知道是否已单击“保存”按钮。对于我的生活,我无法弄清楚如何做到这一点:
$('input[name^="tgfld_"]').blur(function() {
// if (save button has been clicked) <- this is the problem
// don't do anything since the save function will handle this
// else if (value in the field hasn't changed)
// revert everything back to non-editable mode
// else if (value in the field HAS changed)
// do a window.confirm and prompt the user to click the 'save'
// button to save their changes
});
所以它正在检测保存按钮是否是触发“模糊”的原因 - 这是我无法弄清楚的。
或者,如果处理这种情况完全是错误的方式,请告诉我。
(我应该指出页面上可能有很多这样的字段/按钮组合,但到目前为止并没有影响任何内容。)
答案 0 :(得分:3)
这是一个非常有趣(并且非平凡的恕我直言)问题。为了解决这个问题,我首先创建了一个示例页面,其中包含多个“组”文本输入框和按钮,用于启用它们:
根据您的问题,默认情况下禁用输入框,并通过单击按钮使其“可编辑”。
最好的解决方案原来是一个简单的状态机。状态机通过查看适用于当前状态的事件并忽略所有其他事件,帮助理解浏览器触发的(大量)事件。
以下是状态机的图表(每个转换箭头旁边的文本指定触发该转换的事件的来源和名称):
Solution in action (JS Fiddle project)
作为参考,我还在这里包含JavaScript代码:
function makeEditable(inputId, btnId) {
var state = "Locked", timeout = null, $input = $("#" + inputId), $btn = $("#" + btnId);
function setStateNow(precondition, newState, e) {
if (!precondition || state === precondition) {
if (window.console) { window.console.log("State change: " + state + " => " + newState + " (from " + e.target.id + "." + e.type + ")"); }
if (newState === "Locked") { // changing from any state to Locked
$input.prop("disabled", true);
$btn.val("Edit");
} else if (state === "Locked") { // changing from Locked to any other state
$input.prop("disabled", false).focus();
$btn.val("Save");
}
if (newState === "LockPending") { // changing from any state to LockPending
timeout = setTimeout(
function () { setStateNow("LockPending", "Locked", { target: { id: e.target.id }, type: "setTimeout" }); },
20);
} else if (state === "LockPending") { // changing from LockPending to any other state
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
}
if (newState === "Editable" && state === "LockPendingMouse") {
$input.focus();
}
state = newState;
return true;
}
return false;
}
function setState(e) {
var r;
if (e.data.rules) {
for (i in e.data.rules) {
r = e.data.rules[i];
if (setStateNow(r.precondition, r.newState, e)) {
return;
}
}
} else {
setStateNow(e.data.precondition, e.data.newState, e);
}
}
$input
.focus ({ precondition: "LockPending", newState: "Editable" }, setState)
.blur({ precondition: "Editable", newState: "LockPending" }, setState);
$btn
.click({ rules: [{ precondition: "Locked", newState: "Editable" }, { precondition: "LockPendingMouse", newState: "Locked" }, { precondition: "Editable", newState: "Locked" }] }, setState)
.mousedown({ precondition: "Editable", newState: "LockPendingMouse" }, setState)
.mouseleave({ precondition: "LockPendingMouse", newState: "Editable" }, setState)
.focus ({ precondition: "LockPending", newState: "Editable" }, setState)
.blur({ precondition: "Editable", newState: "LockPending" }, setState);
}
代码定义了一个函数makeEditable
。此函数接受输入控件的ID和相应按钮的ID,使其可编辑。然后它使用“私有”状态机创建一个闭包。这意味着每个makeEditable
调用我们将有一个状态机(因为不同的输入按钮组可能处于不同的状态)。
当前状态或新状态为setStateNow
时,可以在Locked
私有函数中找到状态更改处理的实际“肉”(使文本框可编辑或禁用)。
我在Chrome 14,Opera 10.51,IE 9,FireFox 5.0.1,Safari 5.1,Mobile Safari(iPad2)中成功测试了该解决方案。
我想指出的一个UI行为是对问题的回答
如果您发现错误或想出改进实施的方法,请随时留下评论。
答案 1 :(得分:1)
我确信可能有更好的解决方案,但这就是我想出的:
$(document).ready(function() {
saved = false;
$('#button').click(function() {
saved = true;
});
$('#input').blur(function() {
var t = setTimeout("if(!saved) {alert('not saved!');}",400);
});
});
我使用setTimeout
稍微延迟了一段时间,因为当点击按钮时,blur
事件似乎总是在按钮的click
事件之前触发。