-added aspell as plugin, as it is not available by default anymore.

phpgwapi/js/ckeditor3/plugins/aspell
-changed phpgwapi/js/ckeditor3/plugins/aspell/spellerpages/server-scripts/spellchecker.php
 to allow only configured aspell, tmp dirs and language settings
-removed other than php spellchecker pages from phpgwapi/js/ckeditor3/plugins/aspell/spellerpages/server-scripts/
-added toolbar options to reflect the use/change of calls of SpellCheck(er) via toolbar button
configure options for CKeditor to use aspell (if available) or/and scayt
This commit is contained in:
Klaus Leithoff 2010-06-02 15:22:14 +00:00
parent 3a15cdcd6e
commit 97b1130a36
14 changed files with 1611 additions and 12 deletions

View File

@ -598,6 +598,10 @@ class html
static function &initCKEditor($_height, $_mode) static function &initCKEditor($_height, $_mode)
{ {
include_once(EGW_INCLUDE_ROOT."/phpgwapi/js/ckeditor3/ckeditor_php5.php"); include_once(EGW_INCLUDE_ROOT."/phpgwapi/js/ckeditor3/ckeditor_php5.php");
// use the lang and country information to construct a possible lang info for CKEditor UI and scayt_slang
$lang = ($GLOBALS['egw_info']['user']['preferences']['common']['spellchecker_lang'] ? $GLOBALS['egw_info']['user']['preferences']['common']['spellchecker_lang']: $GLOBALS['egw_info']['user']['preferences']['common']['lang']);
$country = $GLOBALS['egw_info']['user']['preferences']['common']['country'];
if (!(strpos($lang,'-')===false)) list($lang,$country) = explode('-',$lang);
//Get the ckeditor base url //Get the ckeditor base url
$basePath = $GLOBALS['egw_info']['server']['webserver_url'].'/phpgwapi/js/ckeditor3/'; $basePath = $GLOBALS['egw_info']['server']['webserver_url'].'/phpgwapi/js/ckeditor3/';
@ -606,7 +610,7 @@ class html
$oCKeditor->returnOutput = true; $oCKeditor->returnOutput = true;
$oCKeditor->config['customConfig'] = 'ckeditor.egwconfig.js'; $oCKeditor->config['customConfig'] = 'ckeditor.egwconfig.js';
$oCKeditor->config['language'] = $lang;
$oCKeditor->config['resize_enabled'] = false; $oCKeditor->config['resize_enabled'] = false;
//switching the encoding as html entities off, as we correctly handle charsets and it messes up the wiki totally //switching the encoding as html entities off, as we correctly handle charsets and it messes up the wiki totally
$oCKeditor->config['entities'] = true; $oCKeditor->config['entities'] = true;
@ -626,14 +630,20 @@ class html
$oCKeditor->config['toolbarStartupExpanded'] = false; $oCKeditor->config['toolbarStartupExpanded'] = false;
// Now setting the admin settings // Now setting the admin settings
/* $spell = ''; $spell = '';
if (isset($GLOBALS['egw_info']['server']['enabled_spellcheck'])) if (isset($GLOBALS['egw_info']['server']['enabled_spellcheck']))
{ {
$spell = '_spellcheck'; $spell = '_spellcheck';
$oFCKeditor->Config['SpellChecker'] = 'SpellerPages'; if (!empty($GLOBALS['egw_info']['server']['aspell_path']) &&
$oFCKeditor->Config['SpellerPagesServerScript'] = 'server-scripts/spellchecker.php?'.$extra; is_executable($GLOBALS['egw_info']['server']['aspell_path']))
$oFCKeditor->Config['FirefoxSpellChecker'] = false; {
}*/ $spell = '_aspell';
$oCKeditor->config['extraPlugins'] = 'aspell';
}
$oCKeditor->config['scayt_autoStartup']=true;
$oCKeditor->config['scayt_sLang']=$lang.'_'.strtoupper($country);
}
$oCKeditor->config['disableNativeSpellChecker'] = true;
// Now setting the user preferences // Now setting the user preferences
if (isset($GLOBALS['egw_info']['user']['preferences']['common']['rte_enter_mode'])) if (isset($GLOBALS['egw_info']['user']['preferences']['common']['rte_enter_mode']))
@ -675,20 +685,18 @@ class html
$oCKeditor->config['skin'] = $skin; $oCKeditor->config['skin'] = $skin;
//$oCKeditor->config['spellchecker'] = 'SpellCheck';
switch($_mode) { switch($_mode) {
case 'simple': case 'simple':
$oCKeditor->config['toolbar'] = 'egw_simple'; $oCKeditor->config['toolbar'] = 'egw_simple'.$spell;
$oCKeditor->config['menu_groups'] = ''; $oCKeditor->config['menu_groups'] = '';
break; break;
default: default:
case 'extended': case 'extended':
$oCKeditor->config['toolbar'] = 'egw_extended'; $oCKeditor->config['toolbar'] = 'egw_extended'.$spell;
break; break;
case 'advanced': case 'advanced':
$oCKeditor->config['toolbar'] = 'egw_advanced'; $oCKeditor->config['toolbar'] = 'egw_advanced'.$spell;
break; break;
} }
return $oCKeditor; return $oCKeditor;

View File

@ -14,6 +14,18 @@ CKEDITOR.editorConfig = function( config )
] ; ] ;
config.toolbar_egw_simple_spellcheck = [ config.toolbar_egw_simple_spellcheck = [
['Bold','Italic','Underline'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BulletList','NumberedList','Outdent','Indent','Undo','Redo'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print'],
['Maximize','SpellChecker'],
'/',
['Format','Font','FontSize'],
['TextColor','BGColor'],
['ShowBlocks','-','About']
] ;
config.toolbar_egw_simple_aspell = [
['Bold','Italic','Underline'], ['Bold','Italic','Underline'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BulletList','NumberedList','Outdent','Indent','Undo','Redo'], ['BulletList','NumberedList','Outdent','Indent','Undo','Redo'],
@ -25,6 +37,13 @@ CKEDITOR.editorConfig = function( config )
['ShowBlocks','-','About'] ['ShowBlocks','-','About']
] ; ] ;
// config.toolbar_egw_simple.concat([
// '/',
// ['Format','Font','FontSize'],
// ['TextColor','BGColor'],
// ['ShowBlocks','-','About']
// ]);
config.toolbar_egw_extended = [ config.toolbar_egw_extended = [
['Bold','Italic','Underline'], ['Bold','Italic','Underline'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
@ -40,6 +59,20 @@ CKEDITOR.editorConfig = function( config )
] ; ] ;
config.toolbar_egw_extended_spellcheck = [ config.toolbar_egw_extended_spellcheck = [
['Bold','Italic','Underline'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BulletList','NumberedList','Outdent','Indent','Undo','Redo'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print'],
['Link','Unlink','Anchor'],
['Find','Replace'],
['Maximize','SpellChecker','Image','Table'],
'/',
['Format','Font','FontSize'],
['TextColor','BGColor'],
['ShowBlocks','-','About']
] ;
config.toolbar_egw_extended_aspell = [
['Bold','Italic','Underline'], ['Bold','Italic','Underline'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BulletList','NumberedList','Outdent','Indent','Undo','Redo'], ['BulletList','NumberedList','Outdent','Indent','Undo','Redo'],
@ -70,6 +103,22 @@ CKEDITOR.editorConfig = function( config )
] ; ] ;
config.toolbar_egw_advanced_spellcheck = [ config.toolbar_egw_advanced_spellcheck = [
['Source','DocProps','-','Save','NewPage','Preview','-','Templates'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellChecker'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
'/',
['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BulletList','NumberedList','-','Outdent','Indent'],
['Link','Unlink','Anchor'],
['Maximize','Image',/*'Flash',*/'Table','HorizontalRule',/*'Smiley',*/'SpecialChar','PageBreak'], //,'UniversalKey'
'/',
['Style','Format','Font','FontSize'],
['TextColor','BGColor'],
['ShowBlocks','-','About']
] ;
config.toolbar_egw_advanced_aspell = [
['Source','DocProps','-','Save','NewPage','Preview','-','Templates'], ['Source','DocProps','-','Save','NewPage','Preview','-','Templates'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellCheck'], ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellCheck'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'], ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],

View File

@ -28,3 +28,10 @@ Index: phpgwapi/js/ckeditor3/ckeditor_php5.php
if (is_null($val)) { if (is_null($val)) {
return 'null'; return 'null';
--------------- step 3 --------------------------------------
-added aspell as plugin, as it is not available by default anymore.
phpgwapi/js/ckeditor3/plugins/aspell
-changed phpgwapi/js/ckeditor3/plugins/aspell/spellerpages/server-scripts/spellchecker.php
to allow only configured aspell, tmp dirs and language settings
-removed other than php spellchecker pages from phpgwapi/js/ckeditor3/plugins/aspell/spellerpages/server-scripts/
-added toolbar options to reflect the use/change of calls of SpellCheck(er) via toolbar button

View File

@ -0,0 +1,6 @@
.cke_editor .cke_button_aspell .cke_icon
{
background-position: 0 -192px !important;
}

View File

@ -0,0 +1,170 @@
var FCKLang;
var OnSpellerControlsLoad;
CKEDITOR.dialog.add('aspell', function( editor )
{
var number = CKEDITOR.tools.getNextNumber(),
iframeId = 'cke_frame_' + number,
textareaId = 'cke_data_' + number,
interval,
errorMsg = editor.lang.spellCheck.notAvailable;
var spellHTML =
// Input for exchanging data CK<--->spellcheck
'<textarea name="'+textareaId+'" id="'+textareaId+
'" style="display: none;"></textarea>' +
// Spellcheck iframe
'<iframe src="" style="width:485px; height:380px"' +
' frameborder="0" name="' + iframeId + '" id="' + iframeId + '"' +
' allowtransparency="1"></iframe>';
function spellTime(dialog, errorMsg)
{
var i = 0;
return function()
{
if (typeof window.spellChecker == 'function')
{
// Call from window.setInteval expected at once.
if (typeof interval != 'undefined')
window.clearInterval(interval);
// Create spellcheck object, set options/attributes
var oSpeller = new spellChecker(document.getElementById(textareaId));
oSpeller.spellCheckScript = editor.plugins.aspell.path+'spellerpages/server-scripts/spellchecker.php';
oSpeller.OnFinished = function (numChanges) { oSpeller_OnFinished(dialog, numChanges) };
oSpeller.popUpUrl = editor.plugins.aspell.path+'spellerpages/spellchecker.html';
oSpeller.popUpName = iframeId;
oSpeller.popUpProps = null;
// Place language in global variable;
// A bit of a hack, but how does e.g. controls.html know which language to use?
FCKLang = {};
// spellChecker.js
FCKLang.DlgSpellNoChanges = CKEDITOR.lang[editor.langCode].spellCheck.noChanges;
FCKLang.DlgSpellNoMispell = CKEDITOR.lang[editor.langCode].spellCheck.noMispell;
FCKLang.DlgSpellOneChange = CKEDITOR.lang[editor.langCode].spellCheck.oneChange;
FCKLang.DlgSpellManyChanges = CKEDITOR.lang[editor.langCode].spellCheck.manyChanges;
// controls.html
FCKLang.DlgSpellNotInDic = CKEDITOR.lang[editor.langCode].spellCheck.notInDic;
FCKLang.DlgSpellChangeTo = CKEDITOR.lang[editor.langCode].spellCheck.changeTo;
FCKLang.DlgSpellBtnIgnore = CKEDITOR.lang[editor.langCode].spellCheck.btnIgnore;
FCKLang.DlgSpellBtnIgnoreAll = CKEDITOR.lang[editor.langCode].spellCheck.btnIgnoreAll;
FCKLang.DlgSpellBtnReplace = CKEDITOR.lang[editor.langCode].spellCheck.btnReplace;
FCKLang.DlgSpellBtnReplaceAll = CKEDITOR.lang[editor.langCode].spellCheck.btnReplaceAll;
FCKLang.DlgSpellBtnUndo = CKEDITOR.lang[editor.langCode].spellCheck.btnUndo;
// controlWindow.js
FCKLang.DlgSpellNoSuggestions = CKEDITOR.lang[editor.langCode].spellCheck.noSuggestions;
// spellchecker.html
FCKLang.DlgSpellProgress = CKEDITOR.lang[editor.langCode].spellCheck.progress;
// End language
// Start spellcheck!
oSpeller.openChecker();
}
else if (i++ == 180) // Timeout: 180 * 250ms = 45s.
{
alert(errorMsg);
dialog.hide();
}
};
}
function oSpeller_OnFinished(dialog, numberOCorrections)
{
if (numberOCorrections > 0)
{
editor.focus();
editor.fire('saveSnapshot'); // Best way I could find to trigger undo steps.
dialog.getParentEditor().setData(document.getElementById(textareaId).value,function(){
editor.fire('saveSnapshot'); // But there's a blank one between!
});
}
dialog.hide();
}
// Fx and IE don't see the same sizes, it seems. That or Fx is allowing everything to grow.
var minW = 485;
var minH = 380;
if (document.all)
{
minW = 510;
minH = 405;
}
return {
title: editor.lang.spellCheck.title,
minWidth: minW,
minHeight: minH,
buttons: [ CKEDITOR.dialog.cancelButton ],
onShow: function()
{
// Put spellcheck input and iframe in the dialog content
var contentArea = this.getContentElement('general', 'content').getElement();
contentArea.setHtml(spellHTML);
// Define spellcheck init function
OnSpellerControlsLoad = function (controlsWindow)
{
// Translate the dialog box texts
var spans = controlsWindow.document.getElementsByTagName('span');
var inputs = controlsWindow.document.getElementsByTagName('input');
var i, attr;
for (i=0; i < spans.length; i++)
{
attr = spans[i].getAttribute && spans[i].getAttribute('fckLang');
if (attr)
spans[i].innerHTML = FCKLang[attr];
}
for (i=0; i < inputs.length; i++)
{
attr = inputs[i].getAttribute && inputs[i].getAttribute('fckLang');
if (attr)
inputs[i].value = FCKLang[attr];
}
}
// Add spellcheck script to head
CKEDITOR.document.getHead().append(CKEDITOR.document.createElement('script', {
attributes: {
type: 'text/javascript',
src: editor.plugins.aspell.path+'spellerpages/spellChecker.js'
}}));
// Get the data to be checked.
var sData = editor.getData();
//CKEDITOR.document.getById(textareaId).setValue(sData); <-- doesn't work for some reason
document.getElementById(textareaId).value = sData;
// Wait for spellcheck script to load, then execute
interval = window.setInterval(spellTime(this, errorMsg), 250);
},
onHide: function()
{
window.ooo = undefined;
window.int_framsetLoaded = undefined;
window.framesetLoaded = undefined;
window.is_window_opened = false;
OnSpellerControlsLoad = null;
FCKLang = null;
},
contents: [
{
id: 'general',
label: editor.lang.spellCheck.title,
padding: 0,
elements: [
{
type: 'html',
id: 'content',
style: 'width:485;height:380px',
html: '<div></div>'
}
]
}
]
};
});

View File

@ -0,0 +1,31 @@
/**
* Aspell plug-in for CKeditor 3.0
* Ported from FCKeditor 2.x by Christian Boisjoli, SilenceIT
* Requires toolbar, aspell
*/
CKEDITOR.plugins.add('aspell', {
init: function (editor) {
// Create dialog-based command named "aspell"
editor.addCommand('aspell', new CKEDITOR.dialogCommand('aspell'));
// Add button to toolbar. Not sure why only that name works for me.
editor.ui.addButton('SpellCheck', {
label: editor.lang.spellCheck.toolbar,
command: 'aspell'
});
// Add link dialog code
CKEDITOR.dialog.add('aspell', this.path + 'dialogs/aspell.js');
// Add CSS
var aspellCSS = document.createElement('link');
aspellCSS.setAttribute( 'rel', 'stylesheet');
aspellCSS.setAttribute('type', 'text/css');
aspellCSS.setAttribute('href', this.path+'aspell.css');
document.getElementsByTagName("head")[0].appendChild(aspellCSS);
delete aspellCSS;
},
requires: ['toolbar']
});

View File

@ -0,0 +1,86 @@
////////////////////////////////////////////////////
// controlWindow object
////////////////////////////////////////////////////
function controlWindow( controlForm ) {
// private properties
this._form = controlForm;
// public properties
this.windowType = "controlWindow";
this.noSuggestionSelection = "- No suggestions -";
// set up the properties for elements of the given control form
this.suggestionList = this._form.sugg;
this.evaluatedText = this._form.misword;
this.replacementText = this._form.txtsugg;
this.undoButton = this._form.btnUndo;
// public methods
this.addSuggestion = addSuggestion;
this.clearSuggestions = clearSuggestions;
this.selectDefaultSuggestion = selectDefaultSuggestion;
this.resetForm = resetForm;
this.setSuggestedText = setSuggestedText;
this.enableUndo = enableUndo;
this.disableUndo = disableUndo;
}
function resetForm() {
if( this._form ) {
this._form.reset();
}
}
function setSuggestedText() {
var slct = this.suggestionList;
var txt = this.replacementText;
var str = "";
if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) {
str = slct.options[slct.selectedIndex].text;
}
txt.value = str;
}
function selectDefaultSuggestion() {
var slct = this.suggestionList;
var txt = this.replacementText;
if( slct.options.length == 0 ) {
this.addSuggestion( this.noSuggestionSelection );
} else {
slct.options[0].selected = true;
}
this.setSuggestedText();
}
function addSuggestion( sugg_text ) {
var slct = this.suggestionList;
if( sugg_text ) {
var i = slct.options.length;
var newOption = new Option( sugg_text, 'sugg_text'+i );
slct.options[i] = newOption;
}
}
function clearSuggestions() {
var slct = this.suggestionList;
for( var j = slct.length - 1; j > -1; j-- ) {
if( slct.options[j] ) {
slct.options[j] = null;
}
}
}
function enableUndo() {
if( this.undoButton ) {
if( this.undoButton.disabled == true ) {
this.undoButton.disabled = false;
}
}
}
function disableUndo() {
if( this.undoButton ) {
if( this.undoButton.disabled == false ) {
this.undoButton.disabled = true;
}
}
}

View File

@ -0,0 +1,153 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="spellerStyle.css" />
<script type="text/javascript" src="controlWindow.js"></script>
<script type="text/javascript">
var spellerObject;
var controlWindowObj;
if( parent.opener ) {
spellerObject = parent.opener.speller;
}
function ignore_word() {
if( spellerObject ) {
spellerObject.ignoreWord();
}
}
function ignore_all() {
if( spellerObject ) {
spellerObject.ignoreAll();
}
}
function replace_word() {
if( spellerObject ) {
spellerObject.replaceWord();
}
}
function replace_all() {
if( spellerObject ) {
spellerObject.replaceAll();
}
}
function end_spell() {
if( spellerObject ) {
spellerObject.terminateSpell();
}
}
function undo() {
if( spellerObject ) {
spellerObject.undo();
}
}
function suggText() {
if( controlWindowObj ) {
controlWindowObj.setSuggestedText();
}
}
function init_spell() {
// By FredCK (fckLang attributes have been added to the HTML source of this page)
window.parent.parent.OnSpellerControlsLoad(this);
var controlForm = document.spellcheck;
// create a new controlWindow object
controlWindowObj = new controlWindow( controlForm );
// Let's take this out of the constructor, shall we?
controlWindowObj.noSuggestionSelection = window.parent.parent.FCKLang.DlgSpellNoSuggestions; // By ChrisB
// call the init_spell() function in the parent frameset
if( parent.frames.length ) {
parent.init_spell( controlWindowObj );
} else {
alert( 'This page was loaded outside of a frameset. It might not display properly' );
}
}
</script>
</head>
<body class="controlWindowBody" onLoad="init_spell();" style="OVERFLOW: hidden" scroll="no"> <!-- by FredCK -->
<form name="spellcheck">
<table border="0" cellpadding="0" cellspacing="0" border="0" align="center">
<tr>
<td colspan="3" class="normalLabel"><span fckLang="DlgSpellNotInDic">Not in dictionary</span><span>:</span></td>
</tr>
<tr>
<td colspan="3"><input class="readonlyInput" type="text" name="misword" readonly /></td>
</tr>
<tr>
<td colspan="3" height="5"></td>
</tr>
<tr>
<td class="normalLabel"><span fckLang="DlgSpellChangeTo">Change to</span>:</td>
</tr>
<tr valign="top">
<td>
<table border="0" cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="normalLabel">
<input class="textDefault" type="text" name="txtsugg" />
</td>
</tr>
<tr>
<td>
<select class="suggSlct" name="sugg" size="7" onChange="suggText();" onDblClick="replace_word();">
<option></option>
</select>
</td>
</tr>
</table>
</td>
<td>&nbsp;&nbsp;</td>
<td>
<table border="0" cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnore" value="Ignore" onClick="ignore_word();">
</td>
<td>&nbsp;&nbsp;</td>
<td>
<input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnoreAll" value="Ignore All" onClick="ignore_all();">
</td>
</tr>
<tr>
<td colspan="3" height="5"></td>
</tr>
<tr>
<td>
<input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplace" value="Replace" onClick="replace_word();">
</td>
<td>&nbsp;&nbsp;</td>
<td>
<input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplaceAll" value="Replace All" onClick="replace_all();">
</td>
</tr>
<tr>
<td colspan="3" height="5"></td>
</tr>
<tr>
<td>
<input class="buttonDefault" type="button" name="btnUndo" fckLang="DlgSpellBtnUndo" value="Undo" onClick="undo();"
disabled>
</td>
<td>&nbsp;&nbsp;</td>
<td>
<!-- by FredCK
<input class="buttonDefault" type="button" value="Close" onClick="end_spell();">
-->
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>

View File

@ -0,0 +1,236 @@
<?php
header('Content-type: text/html; charset=utf-8');
// The following variables values must reflect your installation needs.
//$aspell_prog = '"C:\Program Files\Aspell\bin\aspell.exe"'; // by FredCK (for Windows)
//$aspell_prog = 'aspell'; // by FredCK (for Linux)
//$lang = 'en_US';
//$aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; // by FredCK
// This is to prevent abitrary access to FCK's spellchecker.php AND to supply the configured path and lang
function deny_no_egw_session(&$account)
{
die('Access denied, no EGroupware session!');
}
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'home',
'noheader' => true,
'autocreate_session_callback' => 'deny_no_egw_session',
)
);
// will not continue, unless the header get's included and there is a valid eGW session
require('../../../../../../../header.inc.php');
if (!empty($GLOBALS['egw_info']['user']['preferences']['common']['spellchecker_lang']))
{
$lang = $GLOBALS['egw_info']['user']['preferences']['common']['spellchecker_lang'];
}
else
{
$lang = $GLOBALS['egw_info']['user']['preferences']['common']['lang'];
}
$aspell_opts = '-a '.escapeshellarg('--lang='.$lang).' --encoding=utf-8 -H --rem-sgml-check=alt'; // by FredCK
$tempfiledir = "./";
$spellercss = '../spellerStyle.css'; // by FredCK
$word_win_src = '../wordWindow.js'; // by FredCK
$textinputs = $_POST['textinputs']; # array
$input_separator = "A";
# set the JavaScript variable to the submitted text.
# textinputs is an array, each element corresponding to the (url-encoded)
# value of the text control submitted for spell-checking
function print_textinputs_var() {
global $textinputs;
foreach( $textinputs as $key=>$val ) {
# $val = str_replace( "'", "%27", $val );
echo "textinputs[$key] = decodeURIComponent(\"" . $val . "\");\n";
}
}
# make declarations for the text input index
function print_textindex_decl( $text_input_idx ) {
echo "words[$text_input_idx] = [];\n";
echo "suggs[$text_input_idx] = [];\n";
}
# set an element of the JavaScript 'words' array to a misspelled word
function print_words_elem( $word, $index, $text_input_idx ) {
echo "words[$text_input_idx][$index] = '" . escape_quote( $word ) . "';\n";
}
# set an element of the JavaScript 'suggs' array to a list of suggestions
function print_suggs_elem( $suggs, $index, $text_input_idx ) {
echo "suggs[$text_input_idx][$index] = [";
foreach( $suggs as $key=>$val ) {
if( $val ) {
echo "'" . escape_quote( $val ) . "'";
if ( $key+1 < count( $suggs )) {
echo ", ";
}
}
}
echo "];\n";
}
# escape single quote
function escape_quote( $str ) {
return preg_replace ( "/'/", "\\'", $str );
}
# handle a server-side error.
function error_handler( $err ) {
echo "error = '" . preg_replace( "/['\\\\]/", "\\\\$0", $err ) . "';\n";
}
## get the list of misspelled words. Put the results in the javascript words array
## for each misspelled word, get suggestions and put in the javascript suggs array
function print_checker_results() {
global $aspell_prog;
global $aspell_opts;
global $tempfiledir;
global $textinputs;
global $input_separator;
$aspell_err = "";
if (!empty($GLOBALS['egw_info']['server']['aspell_path']) &&
is_executable($GLOBALS['egw_info']['server']['aspell_path']))
{
$aspell_prog = $GLOBALS['egw_info']['server']['aspell_path'];
}
else // little fallback that might save linux users
{
$aspell_prog = 'aspell';
}
# create temp file
// use EGroupware's temp_dir
$tempfile = tempnam( $GLOBALS['egw_info']['server']['temp_dir'], 'aspell_data_' );
# open temp file, add the submitted text.
if( $fh = fopen( $tempfile, 'w' )) {
for( $i = 0; $i < count( $textinputs ); $i++ ) {
$text = urldecode( $textinputs[$i] );
// Strip all tags for the text. (by FredCK - #339 / #681)
$text = preg_replace( "/<[^>]+>/", " ", $text ) ;
$lines = explode( "\n", $text );
fwrite ( $fh, "%\n" ); # exit terse mode
fwrite ( $fh, "^$input_separator\n" );
fwrite ( $fh, "!\n" ); # enter terse mode
foreach( $lines as $key=>$value ) {
# use carat on each line to escape possible aspell commands
fwrite( $fh, "^$value\n" );
}
}
fclose( $fh );
# exec aspell command - redirect STDERR to STDOUT
$cmd = "$aspell_prog $aspell_opts < $tempfile 2>&1";
if( $aspellret = shell_exec( $cmd )) {
$linesout = explode( "\n", $aspellret );
$index = 0;
$text_input_index = -1;
# parse each line of aspell return
foreach( $linesout as $key=>$val ) {
$chardesc = substr( $val, 0, 1 );
# if '&', then not in dictionary but has suggestions
# if '#', then not in dictionary and no suggestions
# if '*', then it is a delimiter between text inputs
# if '@' then version info
if( $chardesc == '&' || $chardesc == '#' ) {
$line = explode( " ", $val, 5 );
print_words_elem( $line[1], $index, $text_input_index );
if( isset( $line[4] )) {
$suggs = explode( ", ", $line[4] );
} else {
$suggs = array();
}
print_suggs_elem( $suggs, $index, $text_input_index );
$index++;
} elseif( $chardesc == '*' ) {
$text_input_index++;
print_textindex_decl( $text_input_index );
$index = 0;
} elseif( $chardesc != '@' && $chardesc != "" ) {
# assume this is error output
$aspell_err .= $val;
}
}
if( $aspell_err ) {
$aspell_err = "Error executing `$cmd`\\n$aspell_err";
error_handler( $aspell_err );
}
} else {
error_handler( "System error: Aspell program execution failed (`$cmd`)" );
}
} else {
error_handler( "System error: Could not open file '$tempfile' for writing" );
}
# close temp file, delete file
unlink( $tempfile );
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="<?php echo $spellercss ?>" />
<script language="javascript" src="<?php echo $word_win_src ?>"></script>
<script language="javascript">
var suggs = new Array();
var words = new Array();
var textinputs = new Array();
var error;
<?php
print_textinputs_var();
print_checker_results();
?>
var wordWindowObj = new wordWindow();
wordWindowObj.originalSpellings = words;
wordWindowObj.suggestions = suggs;
wordWindowObj.textInputs = textinputs;
function init_spell() {
// check if any error occured during server-side processing
if( error ) {
alert( error );
} else {
// call the init_spell() function in the parent frameset
if (parent.frames.length) {
parent.init_spell( wordWindowObj );
} else {
alert('This page was loaded outside of a frameset. It might not display properly');
}
}
}
</script>
</head>
<!-- <body onLoad="init_spell();"> by FredCK -->
<body onLoad="init_spell();" bgcolor="#ffffff">
<script type="text/javascript">
wordWindowObj.writeBody();
</script>
</body>
</html>

View File

@ -0,0 +1,461 @@
////////////////////////////////////////////////////
// spellChecker.js
//
// spellChecker object
//
// This file is sourced on web pages that have a textarea object to evaluate
// for spelling. It includes the implementation for the spellCheckObject.
//
////////////////////////////////////////////////////
// constructor
function spellChecker( textObject ) {
// public properties - configurable
this.popUpUrl = '/speller/spellchecker.html'; // by FredCK
// this.popUpUrl = 'fck_spellerpages/spellerpages/spellchecker.html'; // by FredCK
this.popUpName = 'spellchecker';
this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; // by FredCK
// this.popUpProps = null ; // by FredCK
this.spellCheckScript = '/speller/server-scripts/spellchecker.php'; // by FredCK
//this.spellCheckScript = '/cgi-bin/spellchecker.pl';
// values used to keep track of what happened to a word
this.replWordFlag = "R"; // single replace
this.ignrWordFlag = "I"; // single ignore
this.replAllFlag = "RA"; // replace all occurances
this.ignrAllFlag = "IA"; // ignore all occurances
this.fromReplAll = "~RA"; // an occurance of a "replace all" word
this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word
// properties set at run time
this.wordFlags = new Array();
this.currentTextIndex = 0;
this.currentWordIndex = 0;
this.spellCheckerWin = null;
this.controlWin = null;
this.wordWin = null;
this.textArea = textObject; // deprecated
this.textInputs = arguments;
// private methods
this._spellcheck = _spellcheck;
this._getSuggestions = _getSuggestions;
this._setAsIgnored = _setAsIgnored;
this._getTotalReplaced = _getTotalReplaced;
this._setWordText = _setWordText;
this._getFormInputs = _getFormInputs;
// public methods
this.openChecker = openChecker;
this.startCheck = startCheck;
this.checkTextBoxes = checkTextBoxes;
this.checkTextAreas = checkTextAreas;
this.spellCheckAll = spellCheckAll;
this.ignoreWord = ignoreWord;
this.ignoreAll = ignoreAll;
this.replaceWord = replaceWord;
this.replaceAll = replaceAll;
this.terminateSpell = terminateSpell;
this.undo = undo;
// set the current window's "speller" property to the instance of this class.
// this object can now be referenced by child windows/frames.
window.speller = this;
}
// call this method to check all text boxes (and only text boxes) in the HTML document
function checkTextBoxes() {
this.textInputs = this._getFormInputs( "^text$" );
this.openChecker();
}
// call this method to check all textareas (and only textareas ) in the HTML document
function checkTextAreas() {
this.textInputs = this._getFormInputs( "^textarea$" );
this.openChecker();
}
// call this method to check all text boxes and textareas in the HTML document
function spellCheckAll() {
this.textInputs = this._getFormInputs( "^text(area)?$" );
this.openChecker();
}
// call this method to check text boxe(s) and/or textarea(s) that were passed in to the
// object's constructor or to the textInputs property
function openChecker() {
this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps );
if( !this.spellCheckerWin.opener ) {
this.spellCheckerWin.opener = window;
}
}
function startCheck( wordWindowObj, controlWindowObj ) {
// set properties from args
this.wordWin = wordWindowObj;
this.controlWin = controlWindowObj;
// reset properties
this.wordWin.resetForm();
this.controlWin.resetForm();
this.currentTextIndex = 0;
this.currentWordIndex = 0;
// initialize the flags to an array - one element for each text input
this.wordFlags = new Array( this.wordWin.textInputs.length );
// each element will be an array that keeps track of each word in the text
for( var i=0; i<this.wordFlags.length; i++ ) {
this.wordFlags[i] = [];
}
// start
this._spellcheck();
return true;
}
function ignoreWord() {
var wi = this.currentWordIndex;
var ti = this.currentTextIndex;
if( !this.wordWin ) {
alert( 'Error: Word frame not available.' );
return false;
}
if( !this.wordWin.getTextVal( ti, wi )) {
alert( 'Error: "Not in dictionary" text is missing.' );
return false;
}
// set as ignored
if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) {
this.currentWordIndex++;
this._spellcheck();
}
return true;
}
function ignoreAll() {
var wi = this.currentWordIndex;
var ti = this.currentTextIndex;
if( !this.wordWin ) {
alert( 'Error: Word frame not available.' );
return false;
}
// get the word that is currently being evaluated.
var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
if( !s_word_to_repl ) {
alert( 'Error: "Not in dictionary" text is missing' );
return false;
}
// set this word as an "ignore all" word.
this._setAsIgnored( ti, wi, this.ignrAllFlag );
// loop through all the words after this word
for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
if(( i == ti && j > wi ) || i > ti ) {
// future word: set as "from ignore all" if
// 1) do not already have a flag and
// 2) have the same value as current word
if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
&& ( !this.wordFlags[i][j] )) {
this._setAsIgnored( i, j, this.fromIgnrAll );
}
}
}
}
// finally, move on
this.currentWordIndex++;
this._spellcheck();
return true;
}
function replaceWord() {
var wi = this.currentWordIndex;
var ti = this.currentTextIndex;
if( !this.wordWin ) {
alert( 'Error: Word frame not available.' );
return false;
}
if( !this.wordWin.getTextVal( ti, wi )) {
alert( 'Error: "Not in dictionary" text is missing' );
return false;
}
if( !this.controlWin.replacementText ) {
return false ;
}
var txt = this.controlWin.replacementText;
if( txt.value ) {
var newspell = new String( txt.value );
if( this._setWordText( ti, wi, newspell, this.replWordFlag )) {
this.currentWordIndex++;
this._spellcheck();
}
}
return true;
}
function replaceAll() {
var ti = this.currentTextIndex;
var wi = this.currentWordIndex;
if( !this.wordWin ) {
alert( 'Error: Word frame not available.' );
return false;
}
var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
if( !s_word_to_repl ) {
alert( 'Error: "Not in dictionary" text is missing' );
return false;
}
var txt = this.controlWin.replacementText;
if( !txt.value ) return false;
var newspell = new String( txt.value );
// set this word as a "replace all" word.
this._setWordText( ti, wi, newspell, this.replAllFlag );
// loop through all the words after this word
for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
if(( i == ti && j > wi ) || i > ti ) {
// future word: set word text to s_word_to_repl if
// 1) do not already have a flag and
// 2) have the same value as s_word_to_repl
if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
&& ( !this.wordFlags[i][j] )) {
this._setWordText( i, j, newspell, this.fromReplAll );
}
}
}
}
// finally, move on
this.currentWordIndex++;
this._spellcheck();
return true;
}
function terminateSpell() {
// called when we have reached the end of the spell checking.
var msg = ""; // by FredCK
var numrepl = this._getTotalReplaced();
if( numrepl == 0 ) {
// see if there were no misspellings to begin with
if( !this.wordWin ) {
msg = "";
} else {
if( this.wordWin.totalMisspellings() ) {
// msg += "No words changed."; // by FredCK
msg += FCKLang.DlgSpellNoChanges ; // by FredCK
} else {
// msg += "No misspellings found."; // by FredCK
msg += FCKLang.DlgSpellNoMispell ; // by FredCK
}
}
} else if( numrepl == 1 ) {
// msg += "One word changed."; // by FredCK
msg += FCKLang.DlgSpellOneChange ; // by FredCK
} else {
// msg += numrepl + " words changed."; // by FredCK
msg += FCKLang.DlgSpellManyChanges.replace( /%1/g, numrepl ) ;
}
if( msg ) {
// msg += "\n"; // by FredCK
alert( msg );
}
if( numrepl > 0 ) {
// update the text field(s) on the opener window
for( var i = 0; i < this.textInputs.length; i++ ) {
// this.textArea.value = this.wordWin.text;
if( this.wordWin ) {
if( this.wordWin.textInputs[i] ) {
this.textInputs[i].value = this.wordWin.textInputs[i];
}
}
}
}
// return back to the calling window
// this.spellCheckerWin.close(); // by FredCK
if ( typeof( this.OnFinished ) == 'function' ) // by FredCK
this.OnFinished(numrepl) ; // by FredCK
return true;
}
function undo() {
// skip if this is the first word!
var ti = this.currentTextIndex;
var wi = this.currentWordIndex;
if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) {
this.wordWin.removeFocus( ti, wi );
// go back to the last word index that was acted upon
do {
// if the current word index is zero then reset the seed
if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) {
this.currentTextIndex--;
this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1;
if( this.currentWordIndex < 0 ) this.currentWordIndex = 0;
} else {
if( this.currentWordIndex > 0 ) {
this.currentWordIndex--;
}
}
} while (
this.wordWin.totalWords( this.currentTextIndex ) == 0
|| this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll
|| this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll
);
var text_idx = this.currentTextIndex;
var idx = this.currentWordIndex;
var preReplSpell = this.wordWin.originalSpellings[text_idx][idx];
// if we got back to the first word then set the Undo button back to disabled
if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) {
this.controlWin.disableUndo();
}
var i, j, origSpell ;
// examine what happened to this current word.
switch( this.wordFlags[text_idx][idx] ) {
// replace all: go through this and all the future occurances of the word
// and revert them all to the original spelling and clear their flags
case this.replAllFlag :
for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
if(( i == text_idx && j >= idx ) || i > text_idx ) {
origSpell = this.wordWin.originalSpellings[i][j];
if( origSpell == preReplSpell ) {
this._setWordText ( i, j, origSpell, undefined );
}
}
}
}
break;
// ignore all: go through all the future occurances of the word
// and clear their flags
case this.ignrAllFlag :
for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
if(( i == text_idx && j >= idx ) || i > text_idx ) {
origSpell = this.wordWin.originalSpellings[i][j];
if( origSpell == preReplSpell ) {
this.wordFlags[i][j] = undefined;
}
}
}
}
break;
// replace: revert the word to its original spelling
case this.replWordFlag :
this._setWordText ( text_idx, idx, preReplSpell, undefined );
break;
}
// For all four cases, clear the wordFlag of this word. re-start the process
this.wordFlags[text_idx][idx] = undefined;
this._spellcheck();
}
}
function _spellcheck() {
var ww = this.wordWin;
// check if this is the last word in the current text element
if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) {
this.currentTextIndex++;
this.currentWordIndex = 0;
// keep going if we're not yet past the last text element
if( this.currentTextIndex < this.wordWin.textInputs.length ) {
this._spellcheck();
return;
} else {
this.terminateSpell();
return;
}
}
// if this is after the first one make sure the Undo button is enabled
if( this.currentWordIndex > 0 ) {
this.controlWin.enableUndo();
}
// skip the current word if it has already been worked on
if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) {
// increment the global current word index and move on.
this.currentWordIndex++;
this._spellcheck();
} else {
var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex );
if( evalText ) {
this.controlWin.evaluatedText.value = evalText;
ww.setFocus( this.currentTextIndex, this.currentWordIndex );
this._getSuggestions( this.currentTextIndex, this.currentWordIndex );
}
}
}
function _getSuggestions( text_num, word_num ) {
this.controlWin.clearSuggestions();
// add suggestion in list for each suggested word.
// get the array of suggested words out of the
// three-dimensional array containing all suggestions.
var a_suggests = this.wordWin.suggestions[text_num][word_num];
if( a_suggests ) {
// got an array of suggestions.
for( var ii = 0; ii < a_suggests.length; ii++ ) {
this.controlWin.addSuggestion( a_suggests[ii] );
}
}
this.controlWin.selectDefaultSuggestion();
}
function _setAsIgnored( text_num, word_num, flag ) {
// set the UI
this.wordWin.removeFocus( text_num, word_num );
// do the bookkeeping
this.wordFlags[text_num][word_num] = flag;
return true;
}
function _getTotalReplaced() {
var i_replaced = 0;
for( var i = 0; i < this.wordFlags.length; i++ ) {
for( var j = 0; j < this.wordFlags[i].length; j++ ) {
if(( this.wordFlags[i][j] == this.replWordFlag )
|| ( this.wordFlags[i][j] == this.replAllFlag )
|| ( this.wordFlags[i][j] == this.fromReplAll )) {
i_replaced++;
}
}
}
return i_replaced;
}
function _setWordText( text_num, word_num, newText, flag ) {
// set the UI and form inputs
this.wordWin.setText( text_num, word_num, newText );
// keep track of what happened to this word:
this.wordFlags[text_num][word_num] = flag;
return true;
}
function _getFormInputs( inputPattern ) {
var inputs = new Array();
for( var i = 0; i < document.forms.length; i++ ) {
for( var j = 0; j < document.forms[i].elements.length; j++ ) {
if( document.forms[i].elements[j].type.match( inputPattern )) {
inputs[inputs.length] = document.forms[i].elements[j];
}
}
}
return inputs;
}

View File

@ -0,0 +1,71 @@
<script>
var wordWindow = null;
var controlWindow = null;
function init_spell( spellerWindow ) {
if( spellerWindow ) {
if( spellerWindow.windowType == "wordWindow" ) {
wordWindow = spellerWindow;
} else if ( spellerWindow.windowType == "controlWindow" ) {
controlWindow = spellerWindow;
}
}
if( controlWindow && wordWindow ) {
// populate the speller object and start it off!
var speller = opener.speller;
wordWindow.speller = speller;
speller.startCheck( wordWindow, controlWindow );
}
}
// encodeForPost
function encodeForPost( str ) {
var s = new String( str );
s = encodeURIComponent( s );
// additionally encode single quotes to evade any PHP
// magic_quotes_gpc setting (it inserts escape characters and
// therefore skews the btye positions of misspelled words)
return s.replace( /\'/g, '%27' );
}
// post the text area data to the script that populates the speller
function postWords() {
var bodyDoc = window.frames[0].document;
bodyDoc.open();
bodyDoc.write('<html>');
bodyDoc.write('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">');
bodyDoc.write('<link rel="stylesheet" type="text/css" href="spellerStyle.css"/>');
if (opener) {
var speller = opener.speller;
bodyDoc.write('<body class="normalText" onLoad="document.forms[0].submit();">');
bodyDoc.write('<p>' + window.parent.FCKLang.DlgSpellProgress + '<\/p>'); // by FredCK
bodyDoc.write('<form action="'+speller.spellCheckScript+'" method="post">');
for( var i = 0; i < speller.textInputs.length; i++ ) {
bodyDoc.write('<input type="hidden" name="textinputs[]" value="'+encodeForPost(speller.textInputs[i].value)+'">');
}
bodyDoc.write('<\/form>');
bodyDoc.write('<\/body>');
} else {
bodyDoc.write('<body class="normalText">');
bodyDoc.write('<p><b>This page cannot be displayed<\/b><\/p><p>The window was not opened from another window.<\/p>');
bodyDoc.write('<\/body>');
}
bodyDoc.write('<\/html>');
bodyDoc.close();
}
</script>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head>
<title>Speller Pages</title>
</head>
<frameset rows="*,201" onLoad="postWords();">
<frame src="blank.html">
<frame src="controls.html">
</frameset>
</html>

View File

@ -0,0 +1,49 @@
.blend {
font-family: courier new;
font-size: 10pt;
border: 0;
margin-bottom:-1;
}
.normalLabel {
font-size:8pt;
}
.normalText {
font-family:arial, helvetica, sans-serif;
font-size:10pt;
color:000000;
background-color:FFFFFF;
}
.plainText {
font-family: courier new, courier, monospace;
font-size: 10pt;
color:000000;
background-color:FFFFFF;
}
.controlWindowBody {
font-family:arial, helvetica, sans-serif;
font-size:8pt;
padding-top: 7px; /* by FredCK */
margin: 0px; /* by FredCK */
color:000000;
background-color:DADADA;
}
.readonlyInput {
background-color:DADADA;
color:000000;
font-size:8pt;
width:392px;
}
.textDefault {
font-size:8pt;
width: 200px;
}
.buttonDefault {
width:90px;
height:22px;
font-size:8pt;
}
.suggSlct {
width:200px;
margin-top:2;
font-size:8pt;
}

View File

@ -0,0 +1,272 @@
////////////////////////////////////////////////////
// wordWindow object
////////////////////////////////////////////////////
function wordWindow() {
// private properties
this._forms = [];
// private methods
this._getWordObject = _getWordObject;
//this._getSpellerObject = _getSpellerObject;
this._wordInputStr = _wordInputStr;
this._adjustIndexes = _adjustIndexes;
this._isWordChar = _isWordChar;
this._lastPos = _lastPos;
// public properties
this.wordChar = /[a-zA-Z]/;
this.windowType = "wordWindow";
this.originalSpellings = new Array();
this.suggestions = new Array();
this.checkWordBgColor = "pink";
this.normWordBgColor = "white";
this.text = "";
this.textInputs = new Array();
this.indexes = new Array();
//this.speller = this._getSpellerObject();
// public methods
this.resetForm = resetForm;
this.totalMisspellings = totalMisspellings;
this.totalWords = totalWords;
this.totalPreviousWords = totalPreviousWords;
//this.getTextObjectArray = getTextObjectArray;
this.getTextVal = getTextVal;
this.setFocus = setFocus;
this.removeFocus = removeFocus;
this.setText = setText;
//this.getTotalWords = getTotalWords;
this.writeBody = writeBody;
this.printForHtml = printForHtml;
}
function resetForm() {
if( this._forms ) {
for( var i = 0; i < this._forms.length; i++ ) {
this._forms[i].reset();
}
}
return true;
}
function totalMisspellings() {
var total_words = 0;
for( var i = 0; i < this.textInputs.length; i++ ) {
total_words += this.totalWords( i );
}
return total_words;
}
function totalWords( textIndex ) {
return this.originalSpellings[textIndex].length;
}
function totalPreviousWords( textIndex, wordIndex ) {
var total_words = 0;
for( var i = 0; i <= textIndex; i++ ) {
for( var j = 0; j < this.totalWords( i ); j++ ) {
if( i == textIndex && j == wordIndex ) {
break;
} else {
total_words++;
}
}
}
return total_words;
}
//function getTextObjectArray() {
// return this._form.elements;
//}
function getTextVal( textIndex, wordIndex ) {
var word = this._getWordObject( textIndex, wordIndex );
if( word ) {
return word.value;
}
}
function setFocus( textIndex, wordIndex ) {
var word = this._getWordObject( textIndex, wordIndex );
if( word ) {
if( word.type == "text" ) {
word.focus();
word.style.backgroundColor = this.checkWordBgColor;
}
}
}
function removeFocus( textIndex, wordIndex ) {
var word = this._getWordObject( textIndex, wordIndex );
if( word ) {
if( word.type == "text" ) {
word.blur();
word.style.backgroundColor = this.normWordBgColor;
}
}
}
function setText( textIndex, wordIndex, newText ) {
var word = this._getWordObject( textIndex, wordIndex );
var beginStr;
var endStr;
if( word ) {
var pos = this.indexes[textIndex][wordIndex];
var oldText = word.value;
// update the text given the index of the string
beginStr = this.textInputs[textIndex].substring( 0, pos );
endStr = this.textInputs[textIndex].substring(
pos + oldText.length,
this.textInputs[textIndex].length
);
this.textInputs[textIndex] = beginStr + newText + endStr;
// adjust the indexes on the stack given the differences in
// length between the new word and old word.
var lengthDiff = newText.length - oldText.length;
this._adjustIndexes( textIndex, wordIndex, lengthDiff );
word.size = newText.length;
word.value = newText;
this.removeFocus( textIndex, wordIndex );
}
}
function writeBody() {
var d = window.document;
var is_html = false;
d.open();
// iterate through each text input.
for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) {
var end_idx = 0;
var begin_idx = 0;
d.writeln( '<form name="textInput'+txtid+'">' );
var wordtxt = this.textInputs[txtid];
this.indexes[txtid] = [];
if( wordtxt ) {
var orig = this.originalSpellings[txtid];
if( !orig ) break;
//!!! plain text, or HTML mode?
d.writeln( '<div class="plainText">' );
// iterate through each occurrence of a misspelled word.
for( var i = 0; i < orig.length; i++ ) {
// find the position of the current misspelled word,
// starting at the last misspelled word.
// and keep looking if it's a substring of another word
do {
begin_idx = wordtxt.indexOf( orig[i], end_idx );
end_idx = begin_idx + orig[i].length;
// word not found? messed up!
if( begin_idx == -1 ) break;
// look at the characters immediately before and after
// the word. If they are word characters we'll keep looking.
var before_char = wordtxt.charAt( begin_idx - 1 );
var after_char = wordtxt.charAt( end_idx );
} while (
this._isWordChar( before_char )
|| this._isWordChar( after_char )
);
// keep track of its position in the original text.
this.indexes[txtid][i] = begin_idx;
// write out the characters before the current misspelled word
for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) {
// !!! html mode? make it html compatible
d.write( this.printForHtml( wordtxt.charAt( j )));
}
// write out the misspelled word.
d.write( this._wordInputStr( orig[i] ));
// if it's the last word, write out the rest of the text
if( i == orig.length-1 ){
d.write( printForHtml( wordtxt.substr( end_idx )));
}
}
d.writeln( '</div>' );
}
d.writeln( '</form>' );
}
//for ( var j = 0; j < d.forms.length; j++ ) {
// alert( d.forms[j].name );
// for( var k = 0; k < d.forms[j].elements.length; k++ ) {
// alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value );
// }
//}
// set the _forms property
this._forms = d.forms;
d.close();
}
// return the character index in the full text after the last word we evaluated
function _lastPos( txtid, idx ) {
if( idx > 0 )
return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length;
else
return 0;
}
function printForHtml( n ) {
return n ; // by FredCK
/*
var htmlstr = n;
if( htmlstr.length == 1 ) {
// do simple case statement if it's just one character
switch ( n ) {
case "\n":
htmlstr = '<br/>';
break;
case "<":
htmlstr = '&lt;';
break;
case ">":
htmlstr = '&gt;';
break;
}
return htmlstr;
} else {
htmlstr = htmlstr.replace( /</g, '&lt' );
htmlstr = htmlstr.replace( />/g, '&gt' );
htmlstr = htmlstr.replace( /\n/g, '<br/>' );
return htmlstr;
}
*/
}
function _isWordChar( letter ) {
if( letter.search( this.wordChar ) == -1 ) {
return false;
} else {
return true;
}
}
function _getWordObject( textIndex, wordIndex ) {
if( this._forms[textIndex] ) {
if( this._forms[textIndex].elements[wordIndex] ) {
return this._forms[textIndex].elements[wordIndex];
}
}
return null;
}
function _wordInputStr( word ) {
var str = '<input readonly ';
str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">';
return str;
}
function _adjustIndexes( textIndex, wordIndex, lengthDiff ) {
for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) {
this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff;
}
}