Bug 472302 - get rid of fragile timeouts in textbox binding. r=enn

This commit is contained in:
Dão Gottwald 2009-01-12 20:55:37 +01:00
parent f81c16ba91
commit 08b1baef9f
4 changed files with 60 additions and 61 deletions

View File

@ -68,8 +68,6 @@
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
function doTest() {
var t1 = $("t1");
var t2 = $("t2");
@ -79,19 +77,15 @@
var t1CanUndo = {};
t1.editor.canUndo(t1Enabled, t1CanUndo);
ok(t1CanUndo.value, "undo correctly enabled when emptyText was not changed through property");
t2.emptyText = "reallyempty";
// Remaining tests after timeout - emptyText is displayed asynchronously.
setTimeout(function () {
is(t2.inputField.value, "reallyempty", "updated emptyText displayed");
t2.click();
synthesizeKey("2", {});
var t2Enabled = {};
var t2CanUndo = {};
t2.editor.canUndo(t2Enabled, t2CanUndo);
ok(t2CanUndo.value, "undo correctly enabled when emptyText explicitly changed through property");
SimpleTest.finish();
}, 100);
t2.emptyText = "reallyempty";
is(t2.inputField.value, "reallyempty", "updated emptyText displayed");
t2.click();
synthesizeKey("2", {});
var t2Enabled = {};
var t2CanUndo = {};
t2.editor.canUndo(t2Enabled, t2CanUndo);
ok(t2CanUndo.value, "undo correctly enabled when emptyText explicitly changed through property");
}
]]></script>

View File

@ -43,16 +43,13 @@ function doTests() {
ok("1" === t1.emptyText, "emptyText persists after setting value");
t1.value = "";
// More tests after a timeout, because the emptyText is displayed asynchronously.
setTimeout(function () {
is(t1.inputField.value, 1, "emptyText is displayed");
is(t1.textLength, 0, "textLength while emptyText is displayed");
is(t1.inputField.value, 1, "emptyText is displayed");
is(t1.textLength, 0, "textLength while emptyText is displayed");
t1.focus();
is(t1.inputField.value, "", "emptyText is not displayed as the textbox has focus");
t1.focus();
is(t1.inputField.value, "", "emptyText is not displayed as the textbox has focus");
SimpleTest.finish();
}, 100);
SimpleTest.finish();
}
]]></script>

View File

@ -164,23 +164,24 @@
<method name="_updateVisibleText">
<body><![CDATA[
if (!this.hasAttribute("focused") &&
!this.hasAttribute("empty") &&
!this.value &&
this.emptyText) {
// This section is a wee bit hacky; without the timeout, the CSS
// style corresponding to the "empty" attribute doesn't kick in
// until the text has changed, leading to an unpleasant moment
// where the emptyText flashes black before turning gray.
this.setAttribute("empty", true);
setTimeout(function (textbox) {
if (textbox.hasAttribute("empty")) {
try {
textbox.editor.transactionManager.beginBatch();
} catch (e) {}
textbox.inputField.value = textbox.emptyText;
}
}, 0, this);
if (!this.hasAttribute("empty")) {
this.setAttribute("empty", "true");
// Hide the emptytext for a bit, in case the textbox will be focused subsequently
this.inputField.setAttribute("emptytextdelay", "true");
setTimeout(function (textbox) {
textbox.inputField.removeAttribute("emptytextdelay");
}, 100, this);
try {
this.editor.transactionManager.beginBatch();
} catch (e) {}
}
this.inputField.value = this.emptyText;
}
]]></body>
</method>
@ -204,13 +205,8 @@
this.boxObject.removeProperty("value");
}
// this.editor may not be initialized yet in
// bindings that inherit from xul:textbox, so
// do this after construction
setTimeout(function (a) {
a._updateVisibleText();
a._setNewlineHandling();
}, 0, this);
this._updateVisibleText();
this._setNewlineHandling();
]]></constructor>
<destructor>
@ -226,27 +222,34 @@
<handlers>
<handler event="focus" phase="capturing">
<![CDATA[
this._clearEmptyText();
if (this.hasAttribute("focused"))
return;
if (!this.hasAttribute("focused")) {
if (event.originalTarget == this)
this.inputField.focus(); // Forward focus to actual HTML input
else if (event.originalTarget != this.inputField)
return; // Allow other children (e.g. URL bar buttons) to get focus
else if (this.mIgnoreFocus)
this.mIgnoreFocus = false;
else if (this.clickSelectsAll) {
try {
const nsIEditorIMESupport =
Components.interfaces.nsIEditorIMESupport;
var imeEditor = this.editor.QueryInterface(nsIEditorIMESupport);
if (!imeEditor || !imeEditor.composing)
this.editor.selectAll();
} catch (e) {}
}
switch (event.originalTarget) {
case this:
// Forward focus to actual HTML input
this.inputField.focus();
break;
case this.inputField:
this._clearEmptyText();
this.setAttribute("focused", "true");
if (this.mIgnoreFocus) {
this.mIgnoreFocus = false;
} else if (this.clickSelectsAll) {
try {
const nsIEditorIMESupport =
Components.interfaces.nsIEditorIMESupport;
let imeEditor = this.editor.QueryInterface(nsIEditorIMESupport);
if (!imeEditor || !imeEditor.composing)
this.editor.selectAll();
} catch (e) {}
}
break;
default:
// Allow other children (e.g. URL bar buttons) to get focus
return;
}
this.setAttribute("focused", "true");
]]>
</handler>

View File

@ -658,6 +658,11 @@ html|*.textbox-textarea {
text-shadow: inherit;
}
textbox[empty="true"] html|*.textbox-input[emptytextdelay="true"] ,
textbox[empty="true"] html|*.textbox-textarea[emptytextdelay="true"] {
color: transparent !important;
}
.textbox-input-box {
-moz-binding: url("chrome://global/content/bindings/textbox.xml#input-box");
}