source: sandbox/expressoAgenda/library/ckeditor/plugins/aspell/spellerpages/wordWindow.js @ 5081

Revision 5081, 13.3 KB checked in by airton, 13 years ago (diff)

Ticket #2086 - Troca do atual editor de emails do expresso - Adicionando a biblioteca ckeditor

  • Property svn:executable set to *
Line 
1////////////////////////////////////////////////////
2// wordWindow object
3////////////////////////////////////////////////////
4function wordWindow() {
5        // private properties
6        this._forms = [];
7
8        // private methods
9        this._getWordObject = _getWordObject;
10        //this._getSpellerObject = _getSpellerObject;
11        this._wordInputStr = _wordInputStr;
12        this._adjustIndexes = _adjustIndexes;
13        this._isWordChar = _isWordChar;
14        this._lastPos = _lastPos;
15
16        // public properties
17        this.wordChar = /[a-zA-Z]/;
18        this.windowType = "wordWindow";
19        this.originalSpellings = new Array();
20        this.suggestions = new Array();
21        this.checkWordBgColor = "pink";
22        this.normWordBgColor = "white";
23        this.text = "";
24        this.textInputs = new Array();
25        this.indexes = new Array();
26        //this.speller = this._getSpellerObject();
27
28        // public methods
29        this.resetForm = resetForm;
30        this.totalMisspellings = totalMisspellings;
31        this.totalWords = totalWords;
32        this.totalPreviousWords = totalPreviousWords;
33        //this.getTextObjectArray = getTextObjectArray;
34        this.getTextVal = getTextVal;
35        this.setFocus = setFocus;
36        this.removeFocus = removeFocus;
37        this.setText = setText;
38        //this.getTotalWords = getTotalWords;
39        this.writeBody = writeBody;
40        this.printForHtml = printForHtml;
41}
42
43function resetForm() {
44        if( this._forms ) {
45                for( var i = 0; i < this._forms.length; i++ ) {
46                        this._forms[i].reset();
47                }
48        }
49        return true;
50}
51
52function totalMisspellings() {
53        var total_words = 0;
54        for( var i = 0; i < this.textInputs.length; i++ ) {
55                total_words += this.totalWords( i );
56        }
57        return total_words;
58}
59
60function totalWords( textIndex ) {
61        return this.originalSpellings[textIndex].length;
62}
63
64function totalPreviousWords( textIndex, wordIndex ) {
65        var total_words = 0;
66        for( var i = 0; i <= textIndex; i++ ) {
67                for( var j = 0; j < this.totalWords( i ); j++ ) {
68                        if( i == textIndex && j == wordIndex ) {
69                                break;
70                        } else {
71                                total_words++;
72                        }
73                }
74        }
75        return total_words;
76}
77
78//function getTextObjectArray() {
79//      return this._form.elements;
80//}
81
82function getTextVal( textIndex, wordIndex ) {
83        var word = this._getWordObject( textIndex, wordIndex );
84        if( word ) {
85                return word.value;
86        }
87}
88
89function setFocus( textIndex, wordIndex ) {
90        var word = this._getWordObject( textIndex, wordIndex );
91        if( word ) {
92                if( word.type == "text" ) {
93                        word.focus();
94                        word.style.backgroundColor = this.checkWordBgColor;
95                }
96        }
97}
98
99function removeFocus( textIndex, wordIndex ) {
100        var word = this._getWordObject( textIndex, wordIndex );
101        if( word ) {
102                if( word.type == "text" ) {
103                        word.blur();
104                        word.style.backgroundColor = this.normWordBgColor;
105                }
106        }
107}
108
109function setText( textIndex, wordIndex, newText ) {
110        var word = this._getWordObject( textIndex, wordIndex );
111        var beginStr;
112        var endStr;
113        if( word ) {
114                var pos = this.indexes[textIndex][wordIndex];
115                var oldText = word.value;
116                // update the text given the index of the string
117                beginStr = this.textInputs[textIndex].substring( 0, pos );
118                endStr = this.textInputs[textIndex].substring(
119                        pos + oldText.length,
120                        this.textInputs[textIndex].length
121                );
122                this.textInputs[textIndex] = beginStr + newText + endStr;
123
124                // adjust the indexes on the stack given the differences in
125                // length between the new word and old word.
126                var lengthDiff = newText.length - oldText.length;
127                this._adjustIndexes( textIndex, wordIndex, lengthDiff );
128
129                word.size = newText.length;
130                word.value = newText;
131                this.removeFocus( textIndex, wordIndex );
132        }
133}
134
135
136/* This should be more robust for extracting words from HTML.
137 * Many repercussions = project for another time; possibly
138 * make it a server side project with return of everything
139 * already done where only client side change (other than deleting
140 * the way we're processing) would be insertion of corrections into
141 * possible html markup within original spellings OR do it ALL
142 * here and give the server nothing but plain text words - MWB
143 * (Either way, give only plain text to spell checker)
144 */
145// redesigned to handle plain text search failure to find words
146// returned by server
147function writeBody() {
148        var d = window.document;
149        d.open();
150
151        // iterate through each text input.
152        for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) {
153                d.writeln( '<form name="textInput'+txtid+'">' );
154                var wordtxt = this.textInputs[txtid];
155                //this.indexes[txtid] = []; // we'll copy after this is known
156                if( wordtxt ) {
157                        var orig = this.originalSpellings[txtid];
158                        if( !orig ) break;
159
160/* Create array of word locations
161 *
162 * Following logic is based on four assumptions:
163 * 1. Server always returns misspelled words in doc sequence
164 * 2. We'll never find a misspell occurrence the server didn't find.
165 *    (but handle the exception if it happens)
166 * 3. Our plain text method of locating words the server found can fail
167 * 4. HTML is always valid
168 *
169 * We end up with arrays of only those words with their locations we could find
170 * using plain text search method.
171 */
172                        var i,j,k;
173
174                        // initialize our locations working structure:
175                        //    serverTotal/dupFlag, totalFound/dupRef, positionArray/position
176                        var locations = new Array(orig.length);
177                        for(i=0;i<locations.length;i++) locations[i] = new Array(1,0,null);
178
179                        // now mark multiple misspell occurrences the server found
180                        for(i=0;i<locations.length;i++) {
181                                if(locations[i][0] == -1) continue; // already dup of a previous word
182                                for(j=i+1;j<locations.length;j++) {
183                                        if(orig[j]==orig[i]) {
184                                                locations[i][0]++;    // add up number server found
185                                                locations[j][0] = -1; // mark as dup reference
186                                                locations[j][1] = i;  // reference to first occurrence
187                                        }
188                                }
189                        }
190
191                        // find all misspell locations we can with verbatim text search for each unique
192                        // word and only search between tags.
193                        // end up with locations[i][2] == Array of all positions we found word
194                        var keepLooking;
195                        var end_idx;
196                        var begin_idx;
197                        var tagNextStart;
198                        for(i=0;i<locations.length;i++) {
199                                if(locations[i][0] == -1) continue; // dup, we've already done this word
200                                locations[i][2] = new Array();
201                                keepLooking = true;
202                                end_idx = 0;
203                                tagNextStart = wordtxt.indexOf("<"); // we only look between tags
204                                if(tagNextStart == -1) tagNextStart = wordtxt.length; // no tags
205                                do {
206                                        begin_idx = wordtxt.indexOf( orig[i], end_idx );
207                                        if(begin_idx == -1) keepLooking = false;
208                                        else if(tagNextStart<begin_idx) { // prevents getting a FUBAR doc
209                                                end_idx=wordtxt.indexOf(">",tagNextStart+1)+1; // always found if valid html
210                                                tagNextStart=wordtxt.indexOf("<",end_idx);
211                                                if(tagNextStart == -1) tagNextStart=wordtxt.length; // no more tags
212                                        }
213                                        else if( !this._isWordChar(wordtxt.charAt(begin_idx+orig[i].length)) &&
214                                                 !this._isWordChar(wordtxt.charAt(begin_idx-1)) ) {
215                                                locations[i][2].push(begin_idx);
216                                                end_idx = begin_idx + orig[i].length + 1;
217                                        }
218                                        else end_idx = begin_idx + orig[i].length + 1;
219                                } while(keepLooking);
220                                locations[i][1] = locations[i][2].length;
221                                // Enforce one of our assumptions. This 'should' never happen, but if
222                                // we found more occurances of any word than the server found,
223                                // prevent mess up by getting rid of em
224                                if(locations[i][1]>locations[i][0]) locations[i][1]=0;
225                        }
226
227                        // Define all locations that have only one possibility.
228                        // Those for which server and we found the same number of
229                        // misspell occurrences for given misspelling of a word.
230                        for(i=0;i<locations.length;i++) {
231                                if(locations[i][0]==locations[i][1] && typeof(locations[i][2])=="object") {
232                                        locations[i][0]=1;
233                                        locations[i][1]=1;
234                                        var foundarray=locations[i][2];
235                                        locations[i][2]=foundarray.shift();
236                                        for(j=i+1;j<locations.length && foundarray.length>0;j++) {
237                                                if(locations[j][0] == -1 && locations[j][1]==i) {
238                                                        locations[j][0]=1; // total 1
239                                                        locations[j][1]=1; // found 1
240                                                        locations[j][2]=foundarray.shift(); // the location
241                                                }
242                                        }
243                                }
244                        }
245
246                        // now reduce multiple possibilities (never a known case when using Aspell)
247                        //
248                        // Extract array of referenced words of which we've found
249                        // at least one that have more locations in the original
250                        // sequence than we could find
251                        var multiwords = new Array(); // each item = [ref, docPosition]
252                        for(i=0;i<locations.length;i++) {
253                                if(locations[i][0]>locations[i][1] && locations[i][1]>0) {
254                                        for(j=0;j<locations[i][2].length;j++) {
255                                                multiwords.push(new Array(i,locations[i][2][j]));
256                                        }
257                                        locations[i][0] = -1; // mark as referenced after we've extracted info
258                                        locations[i][1] = i;
259                                }
260                        }
261
262                        // now sort this array by sequence we found in doc (presumably like server)
263                        multiwords.sort(new Function("a","b","return a[1]-b[1]"));
264
265                        // Shift each location of this array to the location
266                        // they fit in original server sequence
267                        var keepLooking = true;
268                        var maxcheck = true;
269                        var minIdx = 0;
270                        var minLoc = 0;
271                        for(j=0;j<multiwords.length;j++) {
272                                // check each position for this word in doc order; look for
273                                // word location to pass minimum criteria, then look for upper
274                                // criteria. if it doesn't fit, go to the next occurrence
275                                for(keepLooking=true,i=minIdx;i<locations.length && keepLooking;i++) {
276                                        if(locations[i][0]==-1 && locations[i][1]==multiwords[j][0]) { // if a ref
277                                                if(multiwords[j][1]>minLoc) { // if beyond last word
278                                                        for(maxcheck=true,k=i+1;k<locations.length && maxcheck;k++) {
279                                                                if(locations[k][0] != -1 && locations[k][1]>0) {
280                                                                        if(locations[k][2]>multiwords[j][1]) { // and if before next word
281                                                                                locations[i][0] = 1;
282                                                                                locations[i][1] = 1;
283                                                                                locations[i][2] = multiwords[j][1];
284                                                                                minIdx = i+1; // no point starting next word search before here
285                                                                                keepLooking=false;
286                                                                        }
287                                                                        maxcheck=false;
288                                                                }
289                                                        }
290                                                        if(maxcheck) { //nothing is after this location
291                                                                locations[i][0] = 1;
292                                                                locations[i][1] = 1;
293                                                                locations[i][2] = multiwords[j][1];
294                                                                minIdx = i+1;
295                                                                keepLooking=false;
296                                                        }
297                                                }
298                                        }
299                                        else if(locations[i][0] != -1) {
300                                                minLoc=locations[i][2];
301                                                minIdx=i+1; // where to start next word search
302                                        }
303                                }
304                        }
305
306                        // splice arrays to get rid of unfound words and their suggestions
307                        // (should only omit words that plain text search can't find)
308                        for(i=locations.length-1;i>=0;i--) { // reverse is simpler
309                                if(locations[i][0] == -1 || locations[i][1]==0) { // unfound ref OR none found
310                                        locations.splice(i,1);
311                                        this.originalSpellings[txtid].splice(i,1);
312                                        this.suggestions[txtid].splice(i,1);
313                                }
314                        }
315
316                        // finally, write out the doc and word locations
317                        this.indexes[txtid]= new Array(locations.length);
318                        d.writeln('<div class="plainText">');
319                        for(minLoc=0,i=0;i<locations.length;i++) {
320                                this.indexes[txtid][i] = locations[i][2];
321                                d.write(wordtxt.substring(minLoc,locations[i][2])); // before word
322                                d.write( this._wordInputStr(this.originalSpellings[txtid][i],txtid,i)); // the word
323                                minLoc = locations[i][2]+this.originalSpellings[txtid][i].length; // where to write from next
324                        }
325                        d.write(wordtxt.substring(minLoc)); // end of doc
326                        d.writeln('</div>');
327                        d.writeln('</form>');
328                }
329        }
330        d.close();
331
332        // set the _forms property
333        this._forms = d.forms;
334
335        // Replace all hyperlinks with spans without the href's that look like links.
336        // This prevents being able to break it by navigating the wordWindow with links.
337        var find = /<a(\s[^\>]*)href=\"[^\"]*\"(.*?)\<\/a\>/gi;
338        var repl = '<span style="color:blue;text-decoration:underline"$1$2</span>';
339        // memory leak for IE?
340        //d.body.innerHTML = d.body.innerHTML.replace(find,repl);       
341        var doc = d.body.innerHTML.replace(find,repl);
342        d.body.innerHTML = doc;
343}
344
345// return the character index in the full text after the last word we evaluated
346function _lastPos( txtid, idx ) {
347        if( idx > 0 )
348                return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length;
349        else
350                return 0;
351}
352
353function printForHtml( n ) {
354        return n ;              // by FredCK
355/*
356        var htmlstr = n;
357        if( htmlstr.length == 1 ) {
358                // do simple case statement if it's just one character
359                switch ( n ) {
360                        case "\n":
361                                htmlstr = '<br/>';
362                                break;
363                        case "<":
364                                htmlstr = '&lt;';
365                                break;
366                        case ">":
367                                htmlstr = '&gt;';
368                                break;
369                }
370                return htmlstr;
371        } else {
372                htmlstr = htmlstr.replace( /</g, '&lt' );
373                htmlstr = htmlstr.replace( />/g, '&gt' );
374                htmlstr = htmlstr.replace( /\n/g, '<br/>' );
375                return htmlstr;
376        }
377*/
378}
379
380function _isWordChar( letter ) {
381        if( letter.search( this.wordChar ) == -1 ) {
382                return false;
383        } else {
384                return true;
385        }
386}
387
388function _getWordObject( textIndex, wordIndex ) {
389        if( this._forms[textIndex] ) {
390                if( this._forms[textIndex].elements[wordIndex] ) {
391                        return this._forms[textIndex].elements[wordIndex];
392                }
393        }
394        return null;
395}
396
397function _wordInputStr( word ) {
398        var str = '<input readonly ';
399        str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">';
400        return str;
401}
402
403function _adjustIndexes( textIndex, wordIndex, lengthDiff ) {
404        for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) {
405                this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff;
406        }
407}
Note: See TracBrowser for help on using the repository browser.