PageRenderTime 68ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 1ms

/184.168.182.1/wp-content/plugins/jetpack/modules/after-the-deadline/jquery.atd.js

https://gitlab.com/endomorphosis/falkenstein
JavaScript | 414 lines | 286 code | 87 blank | 41 comment | 125 complexity | 6b4932dc3a09940ba0faf853f16c55f9 MD5 | raw file
  1. /*
  2. * jquery.atd.js - jQuery powered writing check with After the Deadline
  3. * Author : Raphael Mudge, Automattic Inc.
  4. * License : LGPL or MIT License (take your pick)
  5. * Project : http://www.afterthedeadline.com/development.slp
  6. * Contact : raffi@automattic.com
  7. *
  8. * Derived from:
  9. *
  10. * jquery.spellchecker.js - a simple jQuery Spell Checker
  11. * Copyright (c) 2008 Richard Willis
  12. * MIT license : http://www.opensource.org/licenses/mit-license.php
  13. * Project : http://jquery-spellchecker.googlecode.com
  14. * Contact : willis.rh@gmail.com
  15. */
  16. var AtD =
  17. {
  18. rpc : '', /* see the proxy.php that came with the AtD/TinyMCE plugin */
  19. rpc_css : 'http://www.polishmywriting.com/atd-jquery/server/proxycss.php?data=', /* you may use this, but be nice! */
  20. rpc_css_lang : 'en',
  21. api_key : '',
  22. i18n : {}, // Back-compat
  23. listener : {}
  24. };
  25. AtD.getLang = function( key, defaultk ) {
  26. return ( window.AtD_l10n_r0ar && window.AtD_l10n_r0ar[key] ) || defaultk;
  27. };
  28. AtD.addI18n = function( obj ) {
  29. // Back-compat
  30. window.AtD_l10n_r0ar = obj;
  31. };
  32. AtD.setIgnoreStrings = function(string) {
  33. AtD.core.setIgnoreStrings(string);
  34. };
  35. AtD.showTypes = function(string) {
  36. AtD.core.showTypes(string);
  37. };
  38. AtD.checkCrossAJAX = function(container_id, callback_f) {
  39. /* checks if a global var for click stats exists and increments it if it does... */
  40. if (typeof AtD_proofread_click_count != "undefined")
  41. AtD_proofread_click_count++;
  42. AtD.callback_f = callback_f; /* remember the callback for later */
  43. AtD.remove(container_id);
  44. var container = jQuery('#' + container_id);
  45. var html = container.html();
  46. text = jQuery.trim(container.html());
  47. text = text.replace(/\&lt;/g, '<').replace(/\&gt;/g, '>').replace(/\&amp;/g, '&');
  48. text = encodeURIComponent( text.replace( /\%/g, '%25' ) ); /* % not being escaped here creates problems, I don't know why. */
  49. /* do some sanity checks based on the browser */
  50. if ((text.length > 2000 && navigator.appName == 'Microsoft Internet Explorer') || text.length > 7800) {
  51. if (callback_f != undefined && callback_f.error != undefined)
  52. callback_f.error("Maximum text length for this browser exceeded");
  53. return;
  54. }
  55. /* do some cross-domain AJAX action with CSSHttpRequest */
  56. CSSHttpRequest.get(AtD.rpc_css + text + "&lang=" + AtD.rpc_css_lang + "&nocache=" + (new Date().getTime()), function(response) {
  57. /* do some magic to convert the response into an XML document */
  58. var xml;
  59. if (navigator.appName == 'Microsoft Internet Explorer') {
  60. xml = new ActiveXObject("Microsoft.XMLDOM");
  61. xml.async = false;
  62. xml.loadXML(response);
  63. }
  64. else {
  65. xml = (new DOMParser()).parseFromString(response, 'text/xml');
  66. }
  67. /* check for and display error messages from the server */
  68. if (AtD.core.hasErrorMessage(xml)) {
  69. if (AtD.callback_f != undefined && AtD.callback_f.error != undefined)
  70. AtD.callback_f.error(AtD.core.getErrorMessage(xml));
  71. return;
  72. }
  73. /* highlight the errors */
  74. AtD.container = container_id;
  75. var count = AtD.processXML(container_id, xml);
  76. if (AtD.callback_f != undefined && AtD.callback_f.ready != undefined)
  77. AtD.callback_f.ready(count);
  78. if (count == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  79. AtD.callback_f.success(count);
  80. AtD.counter = count;
  81. AtD.count = count;
  82. });
  83. };
  84. /* check a div for any incorrectly spelled words */
  85. AtD.check = function(container_id, callback_f) {
  86. /* checks if a global var for click stats exists and increments it if it does... */
  87. if (typeof AtD_proofread_click_count != "undefined")
  88. AtD_proofread_click_count++;
  89. AtD.callback_f = callback_f; /* remember the callback for later */
  90. AtD.remove(container_id);
  91. var container = jQuery('#' + container_id);
  92. var html = container.html();
  93. text = jQuery.trim(container.html());
  94. text = text.replace(/\&lt;/g, '<').replace(/\&gt;/g, '>').replace(/\&amp;/g, '&');
  95. text = encodeURIComponent( text ); /* re-escaping % is not necessary here. don't do it */
  96. jQuery.ajax({
  97. type : "POST",
  98. url : AtD.rpc + '/checkDocument',
  99. data : 'key=' + AtD.api_key + '&data=' + text,
  100. format : 'raw',
  101. dataType : (jQuery.browser.msie) ? "text" : "xml",
  102. error : function(XHR, status, error) {
  103. if (AtD.callback_f != undefined && AtD.callback_f.error != undefined)
  104. AtD.callback_f.error(status + ": " + error);
  105. },
  106. success : function(data) {
  107. /* apparently IE likes to return XML as plain text-- work around from:
  108. http://docs.jquery.com/Specifying_the_Data_Type_for_AJAX_Requests */
  109. var xml;
  110. if (typeof data == "string") {
  111. xml = new ActiveXObject("Microsoft.XMLDOM");
  112. xml.async = false;
  113. xml.loadXML(data);
  114. }
  115. else {
  116. xml = data;
  117. }
  118. if (AtD.core.hasErrorMessage(xml)) {
  119. if (AtD.callback_f != undefined && AtD.callback_f.error != undefined)
  120. AtD.callback_f.error(AtD.core.getErrorMessage(xml));
  121. return;
  122. }
  123. /* on with the task of processing and highlighting errors */
  124. AtD.container = container_id;
  125. var count = AtD.processXML(container_id, xml);
  126. if (AtD.callback_f != undefined && AtD.callback_f.ready != undefined)
  127. AtD.callback_f.ready(count);
  128. if (count == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  129. AtD.callback_f.success(count);
  130. AtD.counter = count;
  131. AtD.count = count;
  132. }
  133. });
  134. };
  135. AtD.remove = function(container_id) {
  136. AtD._removeWords(container_id, null);
  137. };
  138. AtD.clickListener = function(event) {
  139. if (AtD.core.isMarkedNode(event.target))
  140. AtD.suggest(event.target);
  141. };
  142. AtD.processXML = function(container_id, responseXML) {
  143. var results = AtD.core.processXML(responseXML);
  144. if (results.count > 0)
  145. results.count = AtD.core.markMyWords(jQuery('#' + container_id).contents(), results.errors);
  146. jQuery('#' + container_id).unbind('click', AtD.clickListener);
  147. jQuery('#' + container_id).click(AtD.clickListener);
  148. return results.count;
  149. };
  150. AtD.useSuggestion = function(word) {
  151. this.core.applySuggestion(AtD.errorElement, word);
  152. AtD.counter --;
  153. if (AtD.counter == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  154. AtD.callback_f.success(AtD.count);
  155. };
  156. AtD.editSelection = function() {
  157. var parent = AtD.errorElement.parent();
  158. if (AtD.callback_f != undefined && AtD.callback_f.editSelection != undefined)
  159. AtD.callback_f.editSelection(AtD.errorElement);
  160. if (AtD.errorElement.parent() != parent) {
  161. AtD.counter --;
  162. if (AtD.counter == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  163. AtD.callback_f.success(AtD.count);
  164. }
  165. };
  166. AtD.ignoreSuggestion = function() {
  167. AtD.core.removeParent(AtD.errorElement);
  168. AtD.counter --;
  169. if (AtD.counter == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  170. AtD.callback_f.success(AtD.count);
  171. };
  172. AtD.ignoreAll = function(container_id) {
  173. var target = AtD.errorElement.text();
  174. var removed = AtD._removeWords(container_id, target);
  175. AtD.counter -= removed;
  176. if (AtD.counter == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
  177. AtD.callback_f.success(AtD.count);
  178. if (AtD.callback_f != undefined && AtD.callback_f.ignore != undefined) {
  179. AtD.callback_f.ignore(target);
  180. AtD.core.setIgnoreStrings(target);
  181. }
  182. };
  183. AtD.explainError = function() {
  184. if (AtD.callback_f != undefined && AtD.callback_f.explain != undefined)
  185. AtD.callback_f.explain(AtD.explainURL);
  186. };
  187. AtD.suggest = function(element) {
  188. /* construct the menu if it doesn't already exist */
  189. if (jQuery('#suggestmenu').length == 0) {
  190. var suggest = jQuery('<div id="suggestmenu"></div>');
  191. suggest.prependTo('body');
  192. }
  193. else {
  194. var suggest = jQuery('#suggestmenu');
  195. suggest.hide();
  196. }
  197. /* find the correct suggestions object */
  198. errorDescription = AtD.core.findSuggestion(element);
  199. /* build up the menu y0 */
  200. AtD.errorElement = jQuery(element);
  201. suggest.empty();
  202. if (errorDescription == undefined) {
  203. suggest.append('<strong>' + AtD.getLang('menu_title_no_suggestions', 'No suggestions') + '</strong>');
  204. }
  205. else if (errorDescription["suggestions"].length == 0) {
  206. suggest.append('<strong>' + errorDescription['description'] + '</strong>');
  207. }
  208. else {
  209. suggest.append('<strong>' + errorDescription['description'] + '</strong>');
  210. for (var i = 0; i < errorDescription["suggestions"].length; i++) {
  211. (function(sugg) {
  212. suggest.append('<a href="javascript:AtD.useSuggestion(\'' + sugg.replace(/'/, '\\\'') + '\')">' + sugg + '</a>');
  213. })(errorDescription["suggestions"][i]);
  214. }
  215. }
  216. /* do the explain menu if configured */
  217. if (AtD.callback_f != undefined && AtD.callback_f.explain != undefined && errorDescription['moreinfo'] != undefined) {
  218. suggest.append('<a href="javascript:AtD.explainError()" class="spell_sep_top">' + AtD.getLang('menu_option_explain', 'Explain...') + '</a>');
  219. AtD.explainURL = errorDescription['moreinfo'];
  220. }
  221. /* do the ignore option */
  222. suggest.append('<a href="javascript:AtD.ignoreSuggestion()" class="spell_sep_top">' + AtD.getLang('menu_option_ignore_once', 'Ignore suggestion') + '</a>');
  223. /* add the edit in place and ignore always option */
  224. if (AtD.callback_f != undefined && AtD.callback_f.editSelection != undefined) {
  225. if (AtD.callback_f != undefined && AtD.callback_f.ignore != undefined)
  226. suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')">' + AtD.getLang('menu_option_ignore_always', 'Ignore always') + '</a>');
  227. else
  228. suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')">' + AtD.getLang('menu_option_ignore_all', 'Ignore all') + '</a>');
  229. suggest.append('<a href="javascript:AtD.editSelection(\'' + AtD.container + '\')" class="spell_sep_bottom spell_sep_top">' + AtD.getLang('menu_option_edit_selection', 'Edit Selection...') + '</a>');
  230. }
  231. else {
  232. if (AtD.callback_f != undefined && AtD.callback_f.ignore != undefined)
  233. suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')" class="spell_sep_bottom">' + AtD.getLang('menu_option_ignore_always', 'Ignore always') + '</a>');
  234. else
  235. suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')" class="spell_sep_bottom">' + AtD.getLang('menu_option_ignore_all', 'Ignore all') + '</a>');
  236. }
  237. /* show the menu */
  238. var pos = jQuery(element).offset();
  239. var width = jQuery(element).width();
  240. /* a sanity check for Internet Explorer--my favorite browser in every possible way */
  241. if (width > 100)
  242. width = 50;
  243. jQuery(suggest).css({ left: (pos.left + width) + 'px', top: pos.top + 'px' });
  244. jQuery(suggest).fadeIn(200);
  245. /* bind events to make the menu disappear when the user clicks outside of it */
  246. AtD.suggestShow = true;
  247. setTimeout(function() {
  248. jQuery("body").bind("click", function() {
  249. if (!AtD.suggestShow)
  250. jQuery('#suggestmenu').fadeOut(200);
  251. });
  252. }, 1);
  253. setTimeout(function() {
  254. AtD.suggestShow = false;
  255. }, 2);
  256. };
  257. AtD._removeWords = function(container_id, w) {
  258. return this.core.removeWords(jQuery('#' + container_id), w);
  259. };
  260. /*
  261. * Set prototypes used by AtD Core UI
  262. */
  263. AtD.initCoreModule = function() {
  264. var core = new AtDCore();
  265. core.hasClass = function(node, className) {
  266. return jQuery(node).hasClass(className);
  267. };
  268. core.map = jQuery.map;
  269. core.contents = function(node) {
  270. return jQuery(node).contents();
  271. };
  272. core.replaceWith = function(old_node, new_node) {
  273. return jQuery(old_node).replaceWith(new_node);
  274. };
  275. core.findSpans = function(parent) {
  276. return jQuery.makeArray(parent.find('span'));
  277. };
  278. core.create = function(string, isTextNode) {
  279. // replace out all tags with &-equivalents so that we preserve tag text.
  280. string = string.replace(/\&/g, '&amp;');
  281. string = string.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
  282. // find all instances of AtD-created spans
  283. var matches = string.match(/\&lt;span class="hidden\w+?" pre="[^"]*"\&gt;.*?\&lt;\/span\&gt;/g);
  284. // ... and fix the tags in those substrings.
  285. if (matches) {
  286. for (var x = 0; x < matches.length; x++) {
  287. string = string.replace(matches[x], matches[x].replace(/\&lt;/gi, '<').replace(/\&gt;/gi, '>'));
  288. };
  289. }
  290. if (core.isIE()) {
  291. // and... one more round of corrections for our friends over at the Internet Explorer
  292. matches = string.match(/\&lt;span class="mceItemHidden"\&gt;\&amp;nbsp;\&lt;\/span&gt;/g, string);
  293. //|&lt;BR.*?class.*?atd_remove_me.*?\&gt;/gi, string);
  294. if (matches) {
  295. for (var x = 0; x < matches.length; x++) {
  296. string = string.replace(matches[x], matches[x].replace(/\&lt;/gi, '<').replace(/\&gt;/gi, '>').replace(/\&amp;/gi, '&'));
  297. };
  298. }
  299. }
  300. node = jQuery('<span class="mceItemHidden"></span>');
  301. node.html(string);
  302. return node;
  303. };
  304. core.remove = function(node) {
  305. return jQuery(node).remove();
  306. };
  307. core.removeParent = function(node) {
  308. /* unwrap exists in jQuery 1.4+ only. Thankfully because replaceWith as-used here won't work in 1.4 */
  309. if (jQuery(node).unwrap)
  310. return jQuery(node).contents().unwrap();
  311. else
  312. return jQuery(node).replaceWith(jQuery(node).html());
  313. };
  314. core.getAttrib = function(node, name) {
  315. return jQuery(node).attr(name);
  316. };
  317. return core;
  318. };
  319. AtD.core = AtD.initCoreModule();