Fixes #353, enable spellcheck in notes

XUL spellcheck code is on Bugzilla but doesn't look like it'll make 2.0, so we'll copy-and-paste. (And even when it is checked in it might not work with our timed-textarea (which itself is a slightly modified version of Mozilla's timed-textarea) anyway.)

Seems to work, though Firefox did crash once while I was testing it...
This commit is contained in:
Dan Stillman 2006-10-20 20:42:36 +00:00
parent 2d98bdf4b5
commit 6a2f44c07e

View File

@ -1,17 +1,41 @@
<?xml version="1.0"?>
<!--
Mozilla timed-textbox binding applied to the XBL #textarea rather than
#textbox, with the Return key event handler removed
A combination of Mozilla's textarea, timed-textbox, input-box, and
input-box-spell bindings, with the timed-textbox's Return key
event handler removed
Note: It would be much nicer if a) Mozilla offered this natively or b) we
just extended the timed-textbox binding directly, but since it's based on
html:input rather than html:textarea, doing so breaks things in various ways
Note: It would be much nicer if a) Mozilla offered this natively or
b) we just extended the timed-textbox binding directly, but since it's based
on html:input rather than html:textarea, doing so breaks things in various
ways (though it may be possible with some tweaking)
Also note: spellcheck code here is a slightly adjusted version
of a patch by Neil Deakin on Bugzilla that wasn't approved in time for
Firefox 2.0 (https://bugzilla.mozilla.org/show_bug.cgi?id=346787).
When there's native support for spellcheck="true" in XUL, we'll hopefully be
able to use that, though it'll still need to work as a timed textarea...
-->
<!DOCTYPE bindings [
<!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
%textcontextDTD;
]>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="timed-textarea" extends="chrome://global/content/bindings/textbox.xml#textarea">
<binding id="timed-textarea" extends="chrome://global/content/bindings/textbox.xml#textbox">
<implementation>
<field name="mInputField">null</field>
<property name="inputField" readonly="true">
<getter><![CDATA[
if (!this.mInputField)
this.mInputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
return this.mInputField;
]]></getter>
</property>
<field name="_timer">null</field>
<property name="timeout"
onset="this.setAttribute('timeout', val); return val;"
@ -38,7 +62,154 @@
]]>
</body>
</method>
<!-- Spellcheck code -->
<field name="_spellCheckInitialized">false</field>
<property name="spellCheckerUI" readonly="true">
<getter><![CDATA[
if (!this._spellCheckInitialized) {
this._spellCheckInitialized = true;
const CI = Components.interfaces;
if (!document instanceof CI.nsIDOMXULDocument)
return null;
var textbox = this;
if (!textbox || !textbox instanceof CI.nsIDOMXULTextBoxElement)
return null;
try {
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
getService(CI.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://global/content/inlineSpellCheckUI.js", this);
if ("InlineSpellCheckerUI" in this)
this.InlineSpellCheckerUI.init(
textbox.inputField.QueryInterface(CI.nsIDOMNSEditableElement).editor
);
} catch(ex) {
Zotero.debug(ex);
}
}
return this.InlineSpellCheckerUI;
]]></getter>
</property>
<constructor>
<![CDATA[
// can't initialize the spell checker in the constructor as not
// everything is initialized and the editor will fail to create the
// inline spell checker object
setTimeout(this._delayedInitSpellCheck, 0, this)
]]>
</constructor>
<method name="_delayedInitSpellCheck">
<parameter name="me"/>
<body><![CDATA[
var spellui = me.spellCheckerUI;
if (spellui)
spellui.enabled = true;
]]></body>
</method>
<method name="_doPopupItemEnabling">
<parameter name="popupNode"/>
<body>
<![CDATA[
var controller = document.commandDispatcher.getControllerForCommand(command);
var children = popupNode.childNodes;
for (var i = 0; i < children.length; i++) {
var command = children[i].getAttribute("cmd");
if (command) {
var enabled = controller.isCommandEnabled(command);
if (enabled)
children[i].removeAttribute("disabled");
else
children[i].setAttribute("disabled", "true");
}
}
]]>
</body>
</method>
<method name="_doPopupItemEnablingSpell">
<parameter name="popupNode"/>
<body>
<![CDATA[
var spellui = this.spellCheckerUI;
if (!spellui || !spellui.canSpellCheck) {
this._setMenuItemVisibility("spell-no-suggestions", false);
this._setMenuItemVisibility("spell-check-enabled", false);
this._setMenuItemVisibility("spell-check-separator", false);
this._setMenuItemVisibility("spell-add-to-dictionary", false);
this._setMenuItemVisibility("spell-suggestions-separator", false);
this._setMenuItemVisibility("spell-dictionaries", false);
return;
}
spellui.initFromEvent(document.popupRangeParent,
document.popupRangeOffset);
var enabled = spellui.enabled;
document.getAnonymousElementByAttribute(this, "anonid",
"spell-check-enabled").setAttribute("checked", enabled);
var overMisspelling = spellui.overMisspelling;
this._setMenuItemVisibility("spell-add-to-dictionary", overMisspelling);
this._setMenuItemVisibility("spell-suggestions-separator", overMisspelling);
// suggestion list
var suggestionsSeparator = document.getAnonymousElementByAttribute(this,
"anonid", "spell-add-to-dictionary");
var numsug = spellui.addSuggestionsToMenu(popupNode, suggestionsSeparator, 5);
this._setMenuItemVisibility("spell-no-suggestions", overMisspelling && numsug == 0);
// dictionary list
var dictmenu = document.getAnonymousElementByAttribute(this, "anonid",
"spell-dictionaries-menu");
var numdicts = spellui.addDictionaryListToMenu(dictmenu, null);
this._setMenuItemVisibility("spell-dictionaries", enabled && numdicts > 1);
this._doPopupItemEnabling(popupNode);
]]>
</body>
</method>
<method name="_doPopupItemDisabling">
<body><![CDATA[
if (this.spellCheckerUI) {
this.spellCheckerUI.clearSuggestionsFromMenu();
this.spellCheckerUI.clearDictionaryListFromMenu();
}
]]></body>
</method>
<method name="_setMenuItemVisibility">
<parameter name="anonid"/>
<parameter name="visible"/>
<body><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid", anonid).
hidden = ! visible;
]]></body>
</method>
<method name="doTextCommand">
<parameter name="command"/>
<body>
<![CDATA[
var controller = document.commandDispatcher.getControllerForCommand(command);
controller.doCommand(command);
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="input">
<![CDATA[
@ -48,5 +219,41 @@
]]>
</handler>
</handlers>
<content context="_child">
<xul:hbox class="textbox-input-box" flex="1">
<html:textarea class="textbox-textarea" flex="1" anonid="input"
xbl:inherits="onfocus,onblur,xbl:text=value,disabled,tabindex,rows,cols,readonly,wrap"><children/></html:textarea>
<xul:menupopup anonid="input-box-contextmenu"
onpopupshowing="if (document.commandDispatcher.focusedElement != this.parentNode.firstChild)
this.parentNode.firstChild.focus();
this.parentNode.parentNode._doPopupItemEnablingSpell(this);"
onpopuphiding="this.parentNode.parentNode._doPopupItemDisabling(this);"
oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.parentNode.doTextCommand(cmd); event.stopPropagation(); }">
<xul:menuitem label="&spellNoSuggestions.label;" anonid="spell-no-suggestions" disabled="true"/>
<xul:menuitem label="&spellAddToDictionary.label;" accesskey="&spellAddToDictionary.accesskey;" anonid="spell-add-to-dictionary"
oncommand="this.parentNode.parentNode.parentNode.spellCheckerUI.addToDictionary();"/>
<xul:menuseparator anonid="spell-suggestions-separator"/>
<xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/>
<xul:menuseparator/>
<xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/>
<xul:menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;" cmd="cmd_copy"/>
<xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/>
<xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/>
<xul:menuseparator/>
<xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/>
<xul:menuseparator anonid="spell-check-separator"/>
<xul:menuitem label="&spellEnable.label;" type="checkbox" accesskey="&spellEnable.accesskey;" anonid="spell-check-enabled"
oncommand="this.parentNode.parentNode.parentNode.spellCheckerUI.toggleEnabled();"/>
<xul:menu label="&spellDictionaries.label;" accesskey="&spellDictionaries.accesskey;" anonid="spell-dictionaries">
<xul:menupopup anonid="spell-dictionaries-menu"
onpopupshowing="event.stopPropagation();"
onpopuphiding="event.stopPropagation();"/>
</xul:menu>
</xul:menupopup>
</xul:hbox>
</content>
</binding>
</bindings>