/**
* Actions.js
*
* Released under LGPL License.
* Copyright (c) 1999-2017 Ephox Corp. All rights reserved
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
define(
'tinymce.plugins.spellchecker.core.Actions',
[
'tinymce.core.util.Tools',
'tinymce.core.util.URI',
'tinymce.core.util.XHR',
'tinymce.plugins.spellchecker.api.Events',
'tinymce.plugins.spellchecker.api.Settings',
'tinymce.plugins.spellchecker.core.DomTextMatcher'
],
function (Tools, URI, XHR, Events, Settings, DomTextMatcher) {
var getTextMatcher = function (editor, textMatcherState) {
if (!textMatcherState.get()) {
var textMatcher = new DomTextMatcher(editor.getBody(), editor);
textMatcherState.set(textMatcher);
}
return textMatcherState.get();
};
var isEmpty = function (obj) {
for (var name in obj) {
return false;
}
return true;
};
var defaultSpellcheckCallback = function (editor, pluginUrl, currentLanguageState) {
return function (method, text, doneCallback, errorCallback) {
var data = { method: method, lang: currentLanguageState.get() }, postData = '';
data[method === "addToDictionary" ? "word" : "text"] = text;
Tools.each(data, function (value, key) {
if (postData) {
postData += '&';
}
postData += key + '=' + encodeURIComponent(value);
});
XHR.send({
url: new URI(pluginUrl).toAbsolute(Settings.getRpcUrl(editor)),
type: "post",
content_type: 'application/x-www-form-urlencoded',
data: postData,
success: function (result) {
result = JSON.parse(result);
if (!result) {
var message = editor.translate("Server response wasn't proper JSON.");
errorCallback(message);
} else if (result.error) {
errorCallback(result.error);
} else {
doneCallback(result);
}
},
error: function () {
var message = editor.translate("The spelling service was not found: (") +
Settings.getRpcUrl(editor) +
editor.translate(")");
errorCallback(message);
}
});
};
};
var sendRpcCall = function (editor, pluginUrl, currentLanguageState, name, data, successCallback, errorCallback) {
var userSpellcheckCallback = Settings.getSpellcheckerCallback(editor);
var spellCheckCallback = userSpellcheckCallback ? userSpellcheckCallback : defaultSpellcheckCallback(editor, pluginUrl, currentLanguageState);
spellCheckCallback.call(editor.plugins.spellchecker, name, data, successCallback, errorCallback);
};
var spellcheck = function (editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState) {
if (finish(editor, startedState, textMatcherState)) {
return;
}
var errorCallback = function (message) {
editor.notificationManager.open({ text: message, type: 'error' });
editor.setProgressState(false);
finish(editor, startedState, textMatcherState);
};
var successCallback = function (data) {
markErrors(editor, startedState, textMatcherState, lastSuggestionsState, data);
};
editor.setProgressState(true);
sendRpcCall(editor, pluginUrl, currentLanguageState, "spellcheck", getTextMatcher(editor, textMatcherState).text, successCallback, errorCallback);
editor.focus();
};
var checkIfFinished = function (editor, startedState, textMatcherState) {
if (!editor.dom.select('span.mce-spellchecker-word').length) {
finish(editor, startedState, textMatcherState);
}
};
var addToDictionary = function (editor, pluginUrl, startedState, textMatcherState, word, spans) {
editor.setProgressState(true);
sendRpcCall(editor, pluginUrl, 'addToDictionary', word, function () {
editor.setProgressState(false);
editor.dom.remove(spans, true);
checkIfFinished(editor, startedState, textMatcherState);
}, function (message) {
editor.notificationManager.open({ text: message, type: 'error' });
editor.setProgressState(false);
});
};
var ignoreWord = function (editor, startedState, textMatcherState, word, spans, all) {
editor.selection.collapse();
if (all) {
Tools.each(editor.dom.select('span.mce-spellchecker-word'), function (span) {
if (span.getAttribute('data-mce-word') === word) {
editor.dom.remove(span, true);
}
});
} else {
editor.dom.remove(spans, true);
}
checkIfFinished(editor, startedState, textMatcherState);
};
var finish = function (editor, startedState, textMatcherState) {
getTextMatcher(editor, textMatcherState).reset();
textMatcherState.set(null);
if (startedState.get()) {
startedState.set(false);
Events.fireSpellcheckEnd(editor);
return true;
}
};
var getElmIndex = function (elm) {
var value = elm.getAttribute('data-mce-index');
if (typeof value === "number") {
return "" + value;
}
return value;
};
var findSpansByIndex = function (editor, index) {
var nodes, spans = [];
nodes = Tools.toArray(editor.getBody().getElementsByTagName('span'));
if (nodes.length) {
for (var i = 0; i < nodes.length; i++) {
var nodeIndex = getElmIndex(nodes[i]);
if (nodeIndex === null || !nodeIndex.length) {
continue;
}
if (nodeIndex === index.toString()) {
spans.push(nodes[i]);
}
}
}
return spans;
};
var markErrors = function (editor, startedState, textMatcherState, lastSuggestionsState, data) {
var suggestions, hasDictionarySupport;
if (data.words) {
hasDictionarySupport = !!data.dictionary;
suggestions = data.words;
} else {
// Fallback to old format
suggestions = data;
}
editor.setProgressState(false);
if (isEmpty(suggestions)) {
var message = editor.translate('No misspellings found.');
editor.notificationManager.open({ text: message, type: 'info' });
startedState.set(false);
return;
}
lastSuggestionsState.set({
suggestions: suggestions,
hasDictionarySupport: hasDictionarySupport
});
getTextMatcher(editor, textMatcherState).find(Settings.getSpellcheckerWordcharPattern(editor)).filter(function (match) {
return !!suggestions[match.text];
}).wrap(function (match) {
return editor.dom.create('span', {
"class": 'mce-spellchecker-word',
"data-mce-bogus": 1,
"data-mce-word": match.text
});
});
startedState.set(true);
Events.fireSpellcheckStart(editor);
};
return {
spellcheck: spellcheck,
checkIfFinished: checkIfFinished,
addToDictionary: addToDictionary,
ignoreWord: ignoreWord,
findSpansByIndex: findSpansByIndex,
getElmIndex: getElmIndex,
markErrors: markErrors
};
}
);
|