//////////////////////////////////////////////////// // 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 ); } } /* This should be more robust for extracting words from HTML. * Many repercussions = project for another time; possibly * make it a server side project with return of everything * already done where only client side change (other than deleting * the way we're processing) would be insertion of corrections into * possible html markup within original spellings OR do it ALL * here and give the server nothing but plain text words - MWB * (Either way, give only plain text to spell checker) */ // redesigned to handle plain text search failure to find words // returned by server function writeBody() { var d = window.document; d.open(); // iterate through each text input. for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) { d.writeln( '
' ); var wordtxt = this.textInputs[txtid]; //this.indexes[txtid] = []; // we'll copy after this is known if( wordtxt ) { var orig = this.originalSpellings[txtid]; if( !orig ) break; /* Create array of word locations * * Following logic is based on four assumptions: * 1. Server always returns misspelled words in doc sequence * 2. We'll never find a misspell occurrence the server didn't find. * (but handle the exception if it happens) * 3. Our plain text method of locating words the server found can fail * 4. HTML is always valid * * We end up with arrays of only those words with their locations we could find * using plain text search method. */ var i,j,k; // initialize our locations working structure: // serverTotal/dupFlag, totalFound/dupRef, positionArray/position var locations = new Array(orig.length); for(i=0;i",tagNextStart+1)+1; // always found if valid html tagNextStart=wordtxt.indexOf("<",end_idx); if(tagNextStart == -1) tagNextStart=wordtxt.length; // no more tags } else if( !this._isWordChar(wordtxt.charAt(begin_idx+orig[i].length)) && !this._isWordChar(wordtxt.charAt(begin_idx-1)) ) { locations[i][2].push(begin_idx); end_idx = begin_idx + orig[i].length + 1; } else end_idx = begin_idx + orig[i].length + 1; } while(keepLooking); locations[i][1] = locations[i][2].length; // Enforce one of our assumptions. This 'should' never happen, but if // we found more occurances of any word than the server found, // prevent mess up by getting rid of em if(locations[i][1]>locations[i][0]) locations[i][1]=0; } // Define all locations that have only one possibility. // Those for which server and we found the same number of // misspell occurrences for given misspelling of a word. for(i=0;i0;j++) { if(locations[j][0] == -1 && locations[j][1]==i) { locations[j][0]=1; // total 1 locations[j][1]=1; // found 1 locations[j][2]=foundarray.shift(); // the location } } } } // now reduce multiple possibilities (never a known case when using Aspell) // // Extract array of referenced words of which we've found // at least one that have more locations in the original // sequence than we could find var multiwords = new Array(); // each item = [ref, docPosition] for(i=0;ilocations[i][1] && locations[i][1]>0) { for(j=0;jminLoc) { // if beyond last word for(maxcheck=true,k=i+1;k0) { if(locations[k][2]>multiwords[j][1]) { // and if before next word locations[i][0] = 1; locations[i][1] = 1; locations[i][2] = multiwords[j][1]; minIdx = i+1; // no point starting next word search before here keepLooking=false; } maxcheck=false; } } if(maxcheck) { //nothing is after this location locations[i][0] = 1; locations[i][1] = 1; locations[i][2] = multiwords[j][1]; minIdx = i+1; keepLooking=false; } } } else if(locations[i][0] != -1) { minLoc=locations[i][2]; minIdx=i+1; // where to start next word search } } } // splice arrays to get rid of unfound words and their suggestions // (should only omit words that plain text search can't find) for(i=locations.length-1;i>=0;i--) { // reverse is simpler if(locations[i][0] == -1 || locations[i][1]==0) { // unfound ref OR none found locations.splice(i,1); this.originalSpellings[txtid].splice(i,1); this.suggestions[txtid].splice(i,1); } } // finally, write out the doc and word locations this.indexes[txtid]= new Array(locations.length); d.writeln('
'); for(minLoc=0,i=0;i'); d.writeln(''); } } d.close(); // set the _forms property this._forms = d.forms; // Replace all hyperlinks with spans without the href's that look like links. // This prevents being able to break it by navigating the wordWindow with links. var find = /]*)href=\"[^\"]*\"(.*?)\<\/a\>/gi; var repl = ''; // memory leak for IE? //d.body.innerHTML = d.body.innerHTML.replace(find,repl); var doc = d.body.innerHTML.replace(find,repl); d.body.innerHTML = doc; } // 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 = '
'; break; case "<": htmlstr = '<'; break; case ">": htmlstr = '>'; break; } return htmlstr; } else { htmlstr = htmlstr.replace( //g, '>' ); htmlstr = htmlstr.replace( /\n/g, '
' ); 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 = ''; 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; } }