dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel");
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button. },
onCancel: function(){ // Stub for the click event of the cancel button.
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button. },
onCancel: function(){ // Stub for the click event of the cancel button. },
onEnter: function(){ // Stub for the enter event of the unFound textbox.
It is a base network service component. It transfers text to a remote service port
with cross domain ability enabled. It can split text into specified pieces and send
them out one by one so that it can handle the case when the service has a limitation of
the capability.
The encoding is UTF-8.
ACTION [public const] String
Actions for the server-side piece to take
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button. },
onCancel: function(){ // Stub for the click event of the cancel button. },
onEnter: function(){ // Stub for the enter event of the unFound textbox. },
focus: function(){ // summary: // Set the focus of the control // tags: // public this.unfoundTextBox.focus(); },
_enter: function(/*Event*/ evt){ // summary: // Handle the enter event // evt: // The event object // tags: // private if(evt.keyCode == dojo.keys.ENTER){ this.onEnter(); dojo.stopEvent(evt); } },
_unfoundTextBoxChange: function(){ // summary: // Indicate that the Not Found textbox is changed or not // tags: // private var id = this.textId + "_label"; if(!this.ignoreChange){ dojo.byId(id).innerHTML = this["replaceWith"]; this.isChanged = true; this.suggestionSelect.deselectAll(); }else{ dojo.byId(id).innerHTML = this["unfound"]; } },
_setUnfoundWordAttr: function(/*String*/ value){ // summary: // Set the value of the Not Found textbox // value: // The value of the Not Found textbox // tags: // private value = value || ""; this.unfoundTextBox.set("value", value); },
_getUnfoundWordAttr: function(){ // summary: // Get the value of the Not Found textbox // tags: // private return this.unfoundTextBox.get("value"); },
_setSuggestionListAttr: function(/*Array*/ values){ // summary: // Set the items of the suggestion list // values: // The list of the suggestion items // tags: // private var select = this.suggestionSelect; values = values || []; select.removeItems(); select.addItems(values); },
_getSelectedWordAttr: function(){ // summary: // Get the suggested word. // If the select box is selected, the value is the selected item's value, // else the value the the textbox's value // tags: // private var selected = this.suggestionSelect.getSelected(); if(selected && selected.length > 0){ return selected[0].value; }else{ return this.unfoundTextBox.get("value"); } },
_setInProgressAttr: function(/*Boolean*/ show){ // summary: // Set the visibility of the progress icon // tags: // private var id = this.id + "_progressIcon", cmd = show ? "removeClass" : "addClass"; dojo[cmd](id, "hidden"); } });
dojo.declare("dojox.editor.plugins._SpellCheckScriptMultiPart", null, { // summary: // It is a base network service component. It transfers text to a remote service port // with cross domain ability enabled. It can split text into specified pieces and send // them out one by one so that it can handle the case when the service has a limitation of // the capability. // The encoding is UTF-8.
// ACTION [public const] String // Actions for the server-side piece to take ACTION_QUERY: "query", ACTION_UPDATE: "update",
// callbackHandle [public] String // The callback name of JSONP callbackHandle: "callback",
// maxBufferLength [public] Number // The max number of charactors that send to the service at one time. maxBufferLength: 100,
// delimiter [public] String // A token that is used to identify the end of a word (a complete unit). It prevents the service from // cutting a single word into two parts. For example: // "Dojo toolkit is a ajax framework. It helps the developers buid their web applications." // Without the delimiter, the sentence might be split into the follow pieces which is absolutely // not the result we want. // "Dojo toolkit is a ajax fram", "ework It helps the developers bu", "id their web applications" // Having " " as the delimiter, we get the following correct pieces. // "Dojo toolkit is a ajax framework", " It helps the developers buid", " their web applications" delimiter: " ",
// label [public] String // The leading label of the JSON response. The service will return the result like this: // {response: [ // { // text: "teest", // suggestion: ["test","treat"] // } // ]} label: "response",
// _timeout [private] Number // Set JSONP timeout period _timeout: 30000, SEC: 1000,
constructor: function(){ // The URL of the target service this.serviceEndPoint = ""; // The queue that holds all the xhr request this._queue = []; // Indicate if the component is still working. For example, waiting for collecting all // the responses from the service this.isWorking = false; // The extra command passed to the service this.exArgs = null; // The counter that indicate if all the responses are collected to // assemble the final result. this._counter = 0;
// Temparary list that holds the result returns from the service, which will be // assembled into a completed one. if(!this._result) { this._result = []; }
action = action || this.ACTION_QUERY;
var batchSend = function(){ var plan = []; var plannedSize = 0; if(content && content.length > 0){ _this.isWorking = true; var len = content.length; do{ l = r + 1; if((r += mbl) > len){ r = len; }else{ // If there is no delimiter (emplty string), leave the right boundary where it is. // Else extend the right boundary to the first occurance of the delimiter if // it doesn't meet the end of the content. while(dt && content.charAt(r) != dt && r <= len){ r++; } } // Record the information of the text slices plan.push({l: l, r: r}); plannedSize++; }while(r < len);
dojo.forEach(plan, function(item, index){ var jsonpArgs = { url: serviceEndPoint, action: action, timeout: timeout, callbackParamName: callbackParamName, handle: function(response, ioArgs){ if(++_this._counter <= this.size && !(response instanceof Error) && response[label] && dojo.isArray(response[label])){ // Collect the results var offset = this.offset; dojo.forEach(response[label], function(item){ item.offset += offset; }); // Put the packages in order _this._result[this.number]= response[label]; } if(_this._counter == this.size){ _this._finalizeCollection(this.action); _this.isWorking = false; if(_this._queue.length > 0){ // Call the next request waiting in queue (_this._queue.shift())(); } } } }; jsonpArgs.content = comms ? dojo.mixin(comms, {action: action, content: content.substring(item.l - 1, item.r)}): {action: action, content: content.substring(item.l - 1, item.r)}; jsonpArgs.size = plannedSize; jsonpArgs.number = index; // The index of the current package jsonpArgs.offset = item.l - 1; dojo.io.script.get(jsonpArgs); }); } };
var result = this._result, len = result.length; // Turn the result into a one-dimensional array for(var i = 0; i < len; i++){ var temp = result.shift(); result = result.concat(temp); } if(action == this.ACTION_QUERY){ this.onLoad(result); } this._counter = 0; this._result = [];
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button. },
onCancel: function(){ // Stub for the click event of the cancel button. },
onEnter: function(){ // Stub for the enter event of the unFound textbox. },
focus: function(){ // summary: // Set the focus of the control // tags: // public this.unfoundTextBox.focus(); },
_enter: function(/*Event*/ evt){ // summary: // Handle the enter event // evt: // The event object // tags: // private if(evt.keyCode == dojo.keys.ENTER){ this.onEnter(); dojo.stopEvent(evt); } },
_unfoundTextBoxChange: function(){ // summary: // Indicate that the Not Found textbox is changed or not // tags: // private var id = this.textId + "_label"; if(!this.ignoreChange){ dojo.byId(id).innerHTML = this["replaceWith"]; this.isChanged = true; this.suggestionSelect.deselectAll(); }else{ dojo.byId(id).innerHTML = this["unfound"]; } },
_setUnfoundWordAttr: function(/*String*/ value){ // summary: // Set the value of the Not Found textbox // value: // The value of the Not Found textbox // tags: // private value = value || ""; this.unfoundTextBox.set("value", value); },
_getUnfoundWordAttr: function(){ // summary: // Get the value of the Not Found textbox // tags: // private return this.unfoundTextBox.get("value"); },
_setSuggestionListAttr: function(/*Array*/ values){ // summary: // Set the items of the suggestion list // values: // The list of the suggestion items // tags: // private var select = this.suggestionSelect; values = values || []; select.removeItems(); select.addItems(values); },
_getSelectedWordAttr: function(){ // summary: // Get the suggested word. // If the select box is selected, the value is the selected item's value, // else the value the the textbox's value // tags: // private var selected = this.suggestionSelect.getSelected(); if(selected && selected.length > 0){ return selected[0].value; }else{ return this.unfoundTextBox.get("value"); } },
_setInProgressAttr: function(/*Boolean*/ show){ // summary: // Set the visibility of the progress icon // tags: // private var id = this.id + "_progressIcon", cmd = show ? "removeClass" : "addClass"; dojo[cmd](id, "hidden"); } });
dojo.declare("dojox.editor.plugins._SpellCheckScriptMultiPart", null, { // summary: // It is a base network service component. It transfers text to a remote service port // with cross domain ability enabled. It can split text into specified pieces and send // them out one by one so that it can handle the case when the service has a limitation of // the capability. // The encoding is UTF-8.
// ACTION [public const] String // Actions for the server-side piece to take ACTION_QUERY: "query", ACTION_UPDATE: "update",
// callbackHandle [public] String // The callback name of JSONP callbackHandle: "callback",
// maxBufferLength [public] Number // The max number of charactors that send to the service at one time. maxBufferLength: 100,
// delimiter [public] String // A token that is used to identify the end of a word (a complete unit). It prevents the service from // cutting a single word into two parts. For example: // "Dojo toolkit is a ajax framework. It helps the developers buid their web applications." // Without the delimiter, the sentence might be split into the follow pieces which is absolutely // not the result we want. // "Dojo toolkit is a ajax fram", "ework It helps the developers bu", "id their web applications" // Having " " as the delimiter, we get the following correct pieces. // "Dojo toolkit is a ajax framework", " It helps the developers buid", " their web applications" delimiter: " ",
// label [public] String // The leading label of the JSON response. The service will return the result like this: // {response: [ // { // text: "teest", // suggestion: ["test","treat"] // } // ]} label: "response",
// _timeout [private] Number // Set JSONP timeout period _timeout: 30000, SEC: 1000,
constructor: function(){ // The URL of the target service this.serviceEndPoint = ""; // The queue that holds all the xhr request this._queue = []; // Indicate if the component is still working. For example, waiting for collecting all // the responses from the service this.isWorking = false; // The extra command passed to the service this.exArgs = null; // The counter that indicate if all the responses are collected to // assemble the final result. this._counter = 0; },
send: function(/*String*/ content, /*String?*/ action){ // summary: // Send the content to the service port with the specified action // content: // The text to be sent // action: // The action the service should take. Current support actions are // ACTION_QUERY and ACTION_UPDATE // tags: // public var _this = this, dt = this.delimiter, mbl = this.maxBufferLength, label = this.label, serviceEndPoint = this.serviceEndPoint, callbackParamName = this.callbackHandle, comms = this.exArgs, timeout = this._timeout, l = 0, r = 0;
// Temparary list that holds the result returns from the service, which will be // assembled into a completed one. if(!this._result) { this._result = []; }
action = action || this.ACTION_QUERY;
var batchSend = function(){ var plan = []; var plannedSize = 0; if(content && content.length > 0){ _this.isWorking = true; var len = content.length; do{ l = r + 1; if((r += mbl) > len){ r = len; }else{ // If there is no delimiter (emplty string), leave the right boundary where it is. // Else extend the right boundary to the first occurance of the delimiter if // it doesn't meet the end of the content. while(dt && content.charAt(r) != dt && r <= len){ r++; } } // Record the information of the text slices plan.push({l: l, r: r}); plannedSize++; }while(r < len);
dojo.forEach(plan, function(item, index){ var jsonpArgs = { url: serviceEndPoint, action: action, timeout: timeout, callbackParamName: callbackParamName, handle: function(response, ioArgs){ if(++_this._counter <= this.size && !(response instanceof Error) && response[label] && dojo.isArray(response[label])){ // Collect the results var offset = this.offset; dojo.forEach(response[label], function(item){ item.offset += offset; }); // Put the packages in order _this._result[this.number]= response[label]; } if(_this._counter == this.size){ _this._finalizeCollection(this.action); _this.isWorking = false; if(_this._queue.length > 0){ // Call the next request waiting in queue (_this._queue.shift())(); } } } }; jsonpArgs.content = comms ? dojo.mixin(comms, {action: action, content: content.substring(item.l - 1, item.r)}): {action: action, content: content.substring(item.l - 1, item.r)}; jsonpArgs.size = plannedSize; jsonpArgs.number = index; // The index of the current package jsonpArgs.offset = item.l - 1; dojo.io.script.get(jsonpArgs); }); } };
_finalizeCollection: function(action){ // summary: // Assemble the responses into one result. // action: // The action token // tags: // private var result = this._result, len = result.length; // Turn the result into a one-dimensional array for(var i = 0; i < len; i++){ var temp = result.shift(); result = result.concat(temp); } if(action == this.ACTION_QUERY){ this.onLoad(result); } this._counter = 0; this._result = []; },
onLoad: function(/*String*/ data){ // Stub method for a sucessful call
dojo.declare("dojox.editor.plugins._spellCheckControl", [dijit._Widget, dijit._Templated], { // summary: // The widget that is used for the UI of the batch spelling check
/*************************************************************************/ /** Framework Methods **/ /*************************************************************************/ constructor: function(){ // Indicate if the textbox ignores the text change event of the textbox this.ignoreChange = false; // Indicate if the text of the textbox is changed or not this.isChanged = false; // Indicate if the dialog is open or not this.isOpen = false; // Indicate if the dialog can be closed this.closable = true; },
postCreate: function(){ var select = this.suggestionSelect;
// Customize multi-select to single select dojo.removeAttr(select.domNode, "multiple"); select.addItems = function(/*Array*/ items){ // summary: // Add items to the select widget // items: // An array of items be added to the select // tags: // public var _this = this; var o = null; if(items && items.length > 0){ dojo.forEach(items, function(item, i){ o = dojo.create("option", {innerHTML: item, value: item}, _this.domNode); if(i == 0){ o.selected = true; } }); } }; select.removeItems = function(){ // summary: // Remove all the items within the select widget // tags: // public dojo.empty(this.domNode); };
select.deselectAll = function(){ // summary: // De-select all the selected items // tags: // public this.containerNode.selectedIndex = -1; };
// Connect up all the controls with their event handler this.connect(this, "onKeyPress", "_cancel"); this.connect(this.unfoundTextBox, "onKeyPress", "_enter"); this.connect(this.unfoundTextBox, "onChange", "_unfoundTextBoxChange"); this.connect(this.suggestionSelect, "onKeyPress", "_enter"); this.connect(this.skipButton, "onClick", "onSkip"); this.connect(this.skipAllButton, "onClick", "onSkipAll"); this.connect(this.toDicButton, "onClick", "onAddToDic"); this.connect(this.replaceButton, "onClick", "onReplace"); this.connect(this.replaceAllButton, "onClick", "onReplaceAll"); this.connect(this.cancelButton, "onClick", "onCancel"); },
/*************************************************************************/ /** Public Methods **/ /*************************************************************************/
onSkip: function(){ // Stub for the click event of the skip button. },
onSkipAll: function(){ // Stub for the click event of the skipAll button. },
onAddToDic: function(){ // Stub for the click event of the toDic button. },
onReplace: function(){ // Stub for the click event of the replace button. },
onReplaceAll: function(){ // Stub for the click event of the replaceAll button. },
onCancel: function(){ // Stub for the click event of the cancel button. },
onEnter: function(){ // Stub for the enter event of the unFound textbox. },
focus: function(){ // summary: // Set the focus of the control // tags: // public this.unfoundTextBox.focus(); },
_enter: function(/*Event*/ evt){ // summary: // Handle the enter event // evt: // The event object // tags: // private if(evt.keyCode == dojo.keys.ENTER){ this.onEnter(); dojo.stopEvent(evt); } },
_unfoundTextBoxChange: function(){ // summary: // Indicate that the Not Found textbox is changed or not // tags: // private var id = this.textId + "_label"; if(!this.ignoreChange){ dojo.byId(id).innerHTML = this["replaceWith"]; this.isChanged = true; this.suggestionSelect.deselectAll(); }else{ dojo.byId(id).innerHTML = this["unfound"]; } },
_setUnfoundWordAttr: function(/*String*/ value){ // summary: // Set the value of the Not Found textbox // value: // The value of the Not Found textbox // tags: // private value = value || ""; this.unfoundTextBox.set("value", value); },
_getUnfoundWordAttr: function(){ // summary: // Get the value of the Not Found textbox // tags: // private return this.unfoundTextBox.get("value"); },
_setSuggestionListAttr: function(/*Array*/ values){ // summary: // Set the items of the suggestion list // values: // The list of the suggestion items // tags: // private var select = this.suggestionSelect; values = values || []; select.removeItems(); select.addItems(values); },
_getSelectedWordAttr: function(){ // summary: // Get the suggested word. // If the select box is selected, the value is the selected item's value, // else the value the the textbox's value // tags: // private var selected = this.suggestionSelect.getSelected(); if(selected && selected.length > 0){ return selected[0].value; }else{ return this.unfoundTextBox.get("value"); } },
_setInProgressAttr: function(/*Boolean*/ show){ // summary: // Set the visibility of the progress icon // tags: // private var id = this.id + "_progressIcon", cmd = show ? "removeClass" : "addClass"; dojo[cmd](id, "hidden"); } });
dojo.declare("dojox.editor.plugins._SpellCheckScriptMultiPart", null, { // summary: // It is a base network service component. It transfers text to a remote service port // with cross domain ability enabled. It can split text into specified pieces and send // them out one by one so that it can handle the case when the service has a limitation of // the capability. // The encoding is UTF-8.
// ACTION [public const] String // Actions for the server-side piece to take ACTION_QUERY: "query", ACTION_UPDATE: "update",
// callbackHandle [public] String // The callback name of JSONP callbackHandle: "callback",
// maxBufferLength [public] Number // The max number of charactors that send to the service at one time. maxBufferLength: 100,
// delimiter [public] String // A token that is used to identify the end of a word (a complete unit). It prevents the service from // cutting a single word into two parts. For example: // "Dojo toolkit is a ajax framework. It helps the developers buid their web applications." // Without the delimiter, the sentence might be split into the follow pieces which is absolutely // not the result we want. // "Dojo toolkit is a ajax fram", "ework It helps the developers bu", "id their web applications" // Having " " as the delimiter, we get the following correct pieces. // "Dojo toolkit is a ajax framework", " It helps the developers buid", " their web applications" delimiter: " ",
// label [public] String // The leading label of the JSON response. The service will return the result like this: // {response: [ // { // text: "teest", // suggestion: ["test","treat"] // } // ]} label: "response",
// _timeout [private] Number // Set JSONP timeout period _timeout: 30000, SEC: 1000,
constructor: function(){ // The URL of the target service this.serviceEndPoint = ""; // The queue that holds all the xhr request this._queue = []; // Indicate if the component is still working. For example, waiting for collecting all // the responses from the service this.isWorking = false; // The extra command passed to the service this.exArgs = null; // The counter that indicate if all the responses are collected to // assemble the final result. this._counter = 0; },
send: function(/*String*/ content, /*String?*/ action){ // summary: // Send the content to the service port with the specified action // content: // The text to be sent // action: // The action the service should take. Current support actions are // ACTION_QUERY and ACTION_UPDATE // tags: // public var _this = this, dt = this.delimiter, mbl = this.maxBufferLength, label = this.label, serviceEndPoint = this.serviceEndPoint, callbackParamName = this.callbackHandle, comms = this.exArgs, timeout = this._timeout, l = 0, r = 0;
// Temparary list that holds the result returns from the service, which will be // assembled into a completed one. if(!this._result) { this._result = []; }
action = action || this.ACTION_QUERY;
var batchSend = function(){ var plan = []; var plannedSize = 0; if(content && content.length > 0){ _this.isWorking = true; var len = content.length; do{ l = r + 1; if((r += mbl) > len){ r = len; }else{ // If there is no delimiter (emplty string), leave the right boundary where it is. // Else extend the right boundary to the first occurance of the delimiter if // it doesn't meet the end of the content. while(dt && content.charAt(r) != dt && r <= len){ r++; } } // Record the information of the text slices plan.push({l: l, r: r}); plannedSize++; }while(r < len);
dojo.forEach(plan, function(item, index){ var jsonpArgs = { url: serviceEndPoint, action: action, timeout: timeout, callbackParamName: callbackParamName, handle: function(response, ioArgs){ if(++_this._counter <= this.size && !(response instanceof Error) && response[label] && dojo.isArray(response[label])){ // Collect the results var offset = this.offset; dojo.forEach(response[label], function(item){ item.offset += offset; }); // Put the packages in order _this._result[this.number]= response[label]; } if(_this._counter == this.size){ _this._finalizeCollection(this.action); _this.isWorking = false; if(_this._queue.length > 0){ // Call the next request waiting in queue (_this._queue.shift())(); } } } }; jsonpArgs.content = comms ? dojo.mixin(comms, {action: action, content: content.substring(item.l - 1, item.r)}): {action: action, content: content.substring(item.l - 1, item.r)}; jsonpArgs.size = plannedSize; jsonpArgs.number = index; // The index of the current package jsonpArgs.offset = item.l - 1; dojo.io.script.get(jsonpArgs); }); } };
_finalizeCollection: function(action){ // summary: // Assemble the responses into one result. // action: // The action token // tags: // private var result = this._result, len = result.length; // Turn the result into a one-dimensional array for(var i = 0; i < len; i++){ var temp = result.shift(); result = result.concat(temp); } if(action == this.ACTION_QUERY){ this.onLoad(result); } this._counter = 0; this._result = []; },
onLoad: function(/*String*/ data){ // Stub method for a sucessful call },
dojo.declare("dojox.editor.plugins.SpellCheck", [dijit._editor._Plugin], { // summary: // This plugin provides a spelling check cabability for the editor.
// url [public] String // The url of the spelling check service url: "",
// bufferLength [public] Number // The max length of each XHR request. It is used to divide the large // text into pieces so that the server-side piece can hold. bufferLength: 100,
// interactive [public] Boolean // Indicate if the interactive spelling check is enabled interactive: false,
// timeout [public] Number // The minutes to waiting for the response. The default value is 30 seconds. timeout: 30,
// button [protected] dijit.form.DropDownButton // The button displayed on the editor's toolbar button: null,
// _editor [private] dijit.Editor // The reference to the editor the plug-in belongs to. _editor: null,
// exArgs [private] Object // The object that holds all the parametes passed into the constructor exArgs: null,
// _cursorSpan [private] String // The span that holds the current position of the cursor _cursorSpan: "",
// _cursorSelector [private] String // The CSS selector of the cursor span _cursorSelector: "cursorPlaceHolder",
// _incorrectWordsSpan [private] String // The wrapper that marks the incorrect words _incorrectWordsSpan: "${text}",
// _ignoredIncorrectStyle [private] Object // The style of the ignored incorrect words _ignoredIncorrectStyle: {"cursor": "inherit", "borderBottom": "none", "backgroundColor": "transparent"},
// _normalIncorrectStyle [private] Object // The style of the marked incorrect words. _normalIncorrectStyle: {"cursor": "pointer", "borderBottom": "1px dotted red", "backgroundColor": "yellow"},
// _highlightedIncorrectStyle [private] Object // The style of the highlighted incorrect words _highlightedIncorrectStyle: {"borderBottom": "1px dotted red", "backgroundColor": "#b3b3ff"},
// _selector [private] String // An empty CSS class that identifies the incorrect words _selector: "incorrectWordPlaceHolder",
// _maxItemNumber [private] Number // The max number of the suggestion list items _maxItemNumber: 3,
constructor: function(){ // A list that holds all the spans that contains the incorrect words // It is used to select/replace the specified word. this._spanList = []; // The cache that stores all the words. It looks like the following // { // "word": [], // "wrd": ["word", "world"] // } this._cache = {}; // Indicate if this plugin is enabled or not this._enabled = true; // The index of the _spanList this._iterator = 0;
if(!this._service){ var service = this._service = new dojox.editor.plugins._SpellCheckScriptMultiPart(); service.serviceEndPoint = this.url; service.maxBufferLength = this.bufferLength; service.setWaitingTime(this.timeout); // Pass the other arguments directly to the service if(comms){ delete comms.name; delete comms.url; delete comms.interactive; delete comms.timeout; service.exArgs = comms; } }
editor.contentPostFilters.push(this._spellCheckFilter); // Register the filter dojo.publish(dijit._scopeName + ".Editor.plugin.SpellCheck.getParser", [this]); // Get the language parser if(!this.parser){ console.error("Can not get the word parser!"); }
summary
Connect up all the events with their event handlers
When the plugin is disabled (the button is disabled), reset all to their initial status.
If the interactive mode is on, check the content once it is enabled.
if(this.interactive){ var v = 118, V = 86, cc = evt.charCode; if(!evt.altKey && cc == dojo.keys.SPACE){ this._submitContent(); }else if((evt.ctrlKey && (cc == v || cc == V)) || (!evt.ctrlKey && evt.charCode)){ this._submitContent(true); } }
// Skip the current word if(!noUpdate && iter >= 0 && iter < len){ this._skipWord(iter); }
// Move to the next while(++iter < len && list[iter].edited == true){ /* do nothing */} if(iter < len){ this._iterator = iter; this._populateDialog(iter); this._selectWord(iter); }else{ // Reaches the end of the list this._iterator = -1; cont.set("unfoundWord", this._strings["msg"]); cont.set("suggestionList", null); cont.set("disabled", true); cont.set("inProgress", false); }
setTimeout(function(){ // When moving the focus out of the iframe in WebKit browsers, we // need to focus something else first. So the textbox // can be focused correctly. if(dojo.isWebKit) { cont.skipButton.focus(); } cont.focus(); cont.ignoreChange = false; cont.closable = true; }, 0);
summary
Ignore this word and move to the next unignored one.
var cont = this._dialogContent, list = this._spanList, len = list.length, word = list[this._iterator].innerHTML.toLowerCase(), targetWord = cont.get("selectedWord");
cont.closable = false; for(var iter = 0; iter < len; iter++){ // If this word is not ignored and is the same as the source word, // replace it. if(list[iter].innerHTML.toLowerCase() == word){ this._replaceWord(iter, targetWord); } }
var service = this._service, cache = this._cache, words = this.parser.parseIntoWords(this._html2Text(html)) || []; var content = []; dojo.forEach(words, function(word){ word = word.toLowerCase(); if(!cache[word]){ // New word that need to be send to the server side for check cache[word] = []; cache[word].correct = true; content.push(word); } }); if(content.length > 0){ service.send(content.join(" ")); }else if(!service.isWorking){ this._loadData([]); }
summary
Send the query text to the service. The query text is a string of words
separated by space.
Substitute the tag with white charactors so that the server
can easily process the text. For example:
"<a src="sample.html">Hello, world!</a>" ==>
" Hello, world! "
var ed = this._editor, cp = this._cursorSpan; ed.execCommand("inserthtml", cp); var nv = ed.get("value"), index = nv.indexOf(cp), i = -1; while(++i < index && eValue.charAt(i) == nv.charAt(i)){ /* do nothing */} return i;
summary
Get the cursor position. It is the index of the characters
where the cursor is.
// Get the incorrect words spanList = this._spanList = dojo.withGlobal(editor.window, "query", dojo, ["." + this._selector]); dojo.forEach(spanList, function(span, i){ span.id = selector + i; });
// Set them to the incorrect word style if(!this.interactive){ delete nstyle.cursor; } spanList.style(nstyle);
if(this.interactive){ // Build the context menu if(_this._contextMenu){ _this._contextMenu.uninitialize(); _this._contextMenu = null; } _this._contextMenu = new dijit.Menu({ targetNodeIds: [editor.iframe],
bindDomNode: function(/*String|DomNode*/ node){ // summary: // Attach menu to given node node = dojo.byId(node);
var cn; // Connect node
// Support context menus on iframes. Rather than binding to the iframe itself we need // to bind to the node inside the iframe. var iframe, win; if(node.tagName.toLowerCase() == "iframe"){ iframe = node; win = this._iframeContentWindow(iframe); cn = dojo.withGlobal(win, dojo.body); }else{
// To capture these events at the top level, attach to , not . // Otherwise right-click context menu just doesn't work. cn = (node == dojo.body() ? dojo.doc.documentElement : node); }
// "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode()) var binding = { node: node, iframe: iframe };
// Save info about binding in _bindings[], and make node itself record index(+1) into // _bindings[] array. Prefix w/_dijitMenu to avoid setting an attribute that may // start with a number, which fails on FF/safari. dojo.attr(node, "_dijitMenu" + this.id, this._bindings.push(binding));
// Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished // loading yet, in which case we need to wait for the onload event first, and then connect // On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so // we need to monitor keyboard events in addition to the oncontextmenu event. var doConnects = dojo.hitch(this, function(cn){ return [ // TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu, // rather than shift-F10? dojo.connect(cn, this.leftClickToOpen ? "onclick" : "oncontextmenu", this, function(evt){ var target = evt.target, strings = _this._strings; // Schedule context menu to be opened unless it's already been scheduled from onkeydown handler if(dojo.hasClass(target, selector) && !target.edited){ // Click on the incorrect word dojo.stopEvent(evt);
// Build the on-demand menu items var maxNumber = _this._maxItemNumber, id = target.id, index = id.substring(selector.length), suggestions = cache[target.innerHTML.toLowerCase()], slen = suggestions.length;
// Add the suggested words menu items this.destroyDescendants(); if(slen == 0){ this.addChild(new dijit.MenuItem({ label: strings["iMsg"], disabled: true })); }else{ for(var i = 0 ; i < maxNumber && i < slen; i++){ this.addChild(new dijit.MenuItem({ label: suggestions[i], onClick: (function(){ var idx = index, txt = suggestions[i]; return function(){ _this._replaceWord(idx, txt); editor.focus(); }; })() })); } }
if(iframe){ // Setup handler to [re]bind to the iframe when the contents are initially loaded, // and every time the contents change. // Need to do this b/c we are actually binding to the iframe's node. // Note: can't use dojo.connect(), see #9609.
binding.onloadHandler = dojo.hitch(this, function(){ // want to remove old connections, but IE throws exceptions when trying to // access the node because it's already gone, or at least in a state of limbo
var list = this._spanList, win = this._editor.window;
if(index < list.length && list.length > 0){ dojo.withGlobal(win, "selectElement", dijit._editor.selection, [list[index]]); dojo.withGlobal(win, "collapse", dijit._editor.selection, [true]); this._findText(list[index].innerHTML, false, false); if(dojo.isIE){ // Because the selection in the iframe will be lost when the outer window get the // focus, we need to mimic the highlight ourselves. dojo.style(list[index], this._highlightedIncorrectStyle); } }
summary
Select the incorrect word. Move to it and highlight it
var service = this._service; service.send(word || this._spanList[index].innerHTML.toLowerCase(), service.ACTION_UPDATE); this._skipWordAll(index, word);
summary
Add the word at the index to the dictionary
tags:
dojox.editor.plugins.SpellCheck._findText
type
Function
parameters:
txt: (typeof String)
The text to locate in the document.
caseSensitive: (typeof Boolean)
Whether or ot to search case-sensitively.
backwards: (typeof Boolean)
Whether or not to search backwards in the document.