check_me.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /**
  2. * check_me.js
  3. * ------------
  4. * This JavaScript app is the driving power of the SquirrelSpell's
  5. * main spellchecker window. Hope you have as much pain figuring
  6. * it out as it took to write. ;))
  7. *
  8. * $Id$
  9. *
  10. * @author Konstantin Riabitsev <icon@duke.edu> ($Author$)
  11. * @version $Date$
  12. */
  13. var CurrentError=0;
  14. var CurrentLocation=0;
  15. var CurrentLine;
  16. var CurrentSymbol;
  17. var ChangesMade=false;
  18. /**
  19. * This function loads spellchecking errors into the form
  20. * displayed to the user.
  21. *
  22. * @return void
  23. */
  24. function populateSqspellForm(){
  25. CurrentWord=Word=misses[CurrentError];
  26. WordLocations = locations[CurrentError].split(", ");
  27. CurrentLoc = WordLocations[CurrentLocation];
  28. if(CurrentLocation==WordLocations.length-1) {
  29. CurrentLocation=0;
  30. } else {
  31. CurrentLocation++;
  32. }
  33. tmp = CurrentLoc.split(":");
  34. CurrentLine=parseInt(tmp[0]);
  35. CurrentSymbol=parseInt(tmp[1]);
  36. document.forms[0].sqspell_error.value=Word;
  37. LineValue=sqspell_lines[CurrentLine];
  38. StartWith=0;
  39. NewLineValue="";
  40. if (CurrentSymbol > 40){
  41. StartWith=CurrentSymbol-40;
  42. NewLineValue = "...";
  43. }
  44. EndWith=LineValue.length;
  45. EndLine="";
  46. if (EndWith > CurrentSymbol + 40){
  47. EndWith=CurrentSymbol+40;
  48. EndLine="...";
  49. }
  50. NewLineValue+=LineValue.substring(StartWith, CurrentSymbol) + "*" + Word + "*" + LineValue.substring(CurrentSymbol + Word.length, EndWith) + EndLine;
  51. document.forms[0].sqspell_line_area.value=NewLineValue;
  52. if (suggestions[CurrentError]){
  53. WordSuggestions = suggestions[CurrentError].split(", ");
  54. for (i=0; i<WordSuggestions.length; i++){
  55. document.forms[0].sqspell_suggestion.options[i] = new Option(WordSuggestions[i], WordSuggestions[i]);
  56. }
  57. } else {
  58. document.forms[0].sqspell_suggestion.options[0] = new Option("No Suggestions", "_NONE");
  59. document.forms[0].sqspell_oruse.value=Word;
  60. document.forms[0].sqspell_oruse.focus();
  61. document.forms[0].sqspell_oruse.select();
  62. }
  63. document.forms[0].sqspell_suggestion.selectedIndex=0;
  64. if (!document.forms[0].sqspell_oruse.value)
  65. document.forms[0].sqspell_oruse.value=document.forms[0].sqspell_suggestion.options[document.forms[0].sqspell_suggestion.selectedIndex].value;
  66. occursTimes = WordLocations.length;
  67. if (CurrentLocation) occursTimes += CurrentLocation-1;
  68. document.forms[0].sqspell_likethis.value=occursTimes;
  69. }
  70. /**
  71. * This function updates a line from the message with a new value,
  72. * received from the user.
  73. *
  74. * @param lLine line number.
  75. * @param lSymbol symbol at which the misspelled word starts.
  76. * @param lWord misspelled word
  77. * @param lNewWord corrected word
  78. * @return void
  79. */
  80. function updateLine(lLine, lSymbol, lWord, lNewWord){
  81. sqspell_lines[lLine] = sqspell_lines[lLine].substring(0, lSymbol) + lNewWord + sqspell_lines[lLine].substring(lSymbol+lWord.length, sqspell_lines[lLine].length);
  82. if (lWord.length != lNewWord.length)
  83. updateSymbol(lLine, lSymbol, lNewWord.length-lWord.length);
  84. if (!ChangesMade) ChangesMade=true;
  85. }
  86. /**
  87. * This function is used to add a word user wishes to place in his/her
  88. * user dictionary to the form field for later submission. Since there
  89. * is no sane way to pass arrays between javascript and PHP, all words
  90. * are concatenated into one strings and separated with a "%".
  91. *
  92. * @return void
  93. */
  94. function sqspellRemember(){
  95. CurrentWord = misses[CurrentError] + "%";
  96. document.forms[0].words.value += CurrentWord;
  97. /**
  98. * Now ignore all occurances of this word.
  99. */
  100. sqspellIgnoreAll();
  101. }
  102. /**
  103. * This function is called when the "Change" button is pressed.
  104. *
  105. * @return void
  106. */
  107. function sqspellChange(){
  108. CurrentWord = misses[CurrentError];
  109. NewWord=document.forms[0].sqspell_oruse.value;
  110. updateLine(CurrentLine, CurrentSymbol, CurrentWord, NewWord);
  111. proceed();
  112. }
  113. /**
  114. * This function is called when the "Change All" button is pressed.
  115. *
  116. * @return void
  117. */
  118. function sqspellChangeAll(){
  119. // Called when pressed the "Change All" button
  120. allLoc = locations[CurrentError].split(", ");
  121. if (allLoc.length==1) {
  122. /**
  123. * There's no need to "change all", only one occurance of this
  124. * word in the whole text.
  125. */
  126. sqspellChange();
  127. return;
  128. }
  129. /**
  130. * Dark magic.
  131. */
  132. NewWord=document.forms[0].sqspell_oruse.value;
  133. CurrentWord = misses[CurrentError];
  134. for (z=CurrentLocation-1; z<allLoc.length; z++){
  135. tmp = allLoc[z].split(":");
  136. lLine = parseInt(tmp[0]); lSymbol = parseInt(tmp[1]);
  137. updateLine(lLine, lSymbol, CurrentWord, NewWord);
  138. /**
  139. * Load it again to reflect the changes in symbol data
  140. */
  141. allLoc = locations[CurrentError].split(", ");
  142. }
  143. CurrentLocation=0;
  144. proceed();
  145. }
  146. /**
  147. * This function is only here for consistency. It is called when
  148. * "Ignore" is pressed.
  149. *
  150. * @return void
  151. */
  152. function sqspellIgnore(){
  153. proceed();
  154. }
  155. /**
  156. * This function is called when the "Ignore All" button is pressed.
  157. *
  158. * @return void
  159. */
  160. function sqspellIgnoreAll(){
  161. CurrentLocation=0;
  162. proceed();
  163. }
  164. /**
  165. * This function clears the options in a select box "sqspell_suggestions".
  166. *
  167. * @return void
  168. */
  169. function clearSqspellForm(){
  170. for (i=0; i<document.forms[0].sqspell_suggestion.length; i++){
  171. document.forms[0].sqspell_suggestion.options[i]=null;
  172. }
  173. /**
  174. * Now, I've been instructed by the Netscape Developer docs to call
  175. * history.go(0) to refresh the page after I've changed the options.
  176. * However, that brings so many pains with it that I just decided not
  177. * to do it. It works like it is in Netscape 4.x. If there are problems
  178. * in earlier versions of Netscape, then oh well. I'm not THAT anxious
  179. * to have it working on all browsers... ;)
  180. */
  181. document.forms[0].sqspell_oruse.value="";
  182. }
  183. /**
  184. * This function goes on to the next error, or finishes nicely if
  185. * no more errors are available.
  186. *
  187. * @return void
  188. */
  189. function proceed(){
  190. if (!CurrentLocation) CurrentError++;
  191. if (misses[CurrentError]){
  192. clearSqspellForm();
  193. populateSqspellForm();
  194. } else {
  195. if (ChangesMade || document.forms[0].words.value){
  196. if (confirm(ui_completed))
  197. sqspellCommitChanges();
  198. else self.close();
  199. } else {
  200. confirm (ui_nochange);
  201. self.close();
  202. }
  203. }
  204. }
  205. /**
  206. * This function updates the symbol locations after there have been
  207. * word length changes in the lines. Otherwise SquirrelSpell barfs all
  208. * over your message... ;)
  209. *
  210. * @param lLine line number on which the error occurs
  211. * @param lSymbol symbol number at which error occurs
  212. * @param difference the difference in length between the old word
  213. * and the new word. Can be negative or positive.
  214. * @return void
  215. */
  216. function updateSymbol(lLine, lSymbol, difference){
  217. /**
  218. * Now, I will admit that this is not the best way to do stuff,
  219. * However that's the solution I've come up with.
  220. *
  221. * If you are wondering why I didn't use two-dimensional arrays instead,
  222. * well, sometimes there will be a long line with an error close to the
  223. * end of it, so the coordinates would be something like 2,98 and
  224. * some Javascript implementations will create 98 empty members of an
  225. * array just to have a filled number 98. This is too resource-wasteful
  226. * and I have decided to go with the below solution instead. It takes
  227. * a little more processing, but it saves a lot on memory.
  228. *
  229. * It just looks heinous. In real life it's really nice and sane. ;)
  230. */
  231. for (i=0; i<misses.length; i++){
  232. if(locations[i].indexOf(lLine + ":") >= 0){
  233. allLoc = locations[i].split(", ");
  234. for (j=0; j<allLoc.length; j++){
  235. if (allLoc[j].indexOf(lLine+":")==0){
  236. tmp = allLoc[j].split(":");
  237. tmp[0] = parseInt(tmp[0]); tmp[1] = parseInt(tmp[1]);
  238. if (tmp[1] > lSymbol){
  239. tmp[1] = tmp[1] + difference;
  240. allLoc[j] = tmp.join(":");
  241. }
  242. }
  243. }
  244. locations[i] = allLoc.join(", ");
  245. }
  246. }
  247. }
  248. /**
  249. * This function writes the changes back into the compose form.
  250. *
  251. * @return void
  252. */
  253. function sqspellCommitChanges(){
  254. newSubject = sqspell_lines[0];
  255. newBody = "";
  256. for (i=1; i<sqspell_lines.length; i++){
  257. if (i!=1) newBody+="\r\n";
  258. newBody += sqspell_lines[i];
  259. }
  260. opener.document.forms[0].subject.value=newSubject;
  261. opener.document.forms[0].body.value=newBody;
  262. /**
  263. * See if any words were added to the dictionary.
  264. */
  265. if (document.forms[0].words.value){
  266. /**
  267. * Yeppers.
  268. */
  269. document.forms[0].sqspell_line_area.value=ui_wait;
  270. /**
  271. * pass focus to the parent so we can do background save.
  272. */
  273. window.opener.focus();
  274. document.forms[0].submit();
  275. } else {
  276. self.close();
  277. }
  278. }