check_me.js 8.5 KB

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