plugin.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.html or http://ckeditor.com/license
  4. */
  5. CKEDITOR.plugins.add('wordcount', {
  6. lang: ['ca', 'de', 'en', 'es', 'fr', 'it', 'jp', 'no', 'pl', 'pt-BR'],
  7. version : 1.08,
  8. init: function (editor) {
  9. if (editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE) {
  10. return;
  11. }
  12. var defaultFormat = '<span class="cke_path_item">',
  13. intervalId,
  14. lastWordCount,
  15. lastCharCount = 0,
  16. limitReachedNotified = false,
  17. limitRestoredNotified = false;
  18. // Default Config
  19. var defaultConfig = {
  20. showWordCount: true,
  21. showCharCount: false,
  22. charLimit: 'unlimited',
  23. wordLimit: 'unlimited',
  24. countHTML: false
  25. };
  26. // Get Config & Lang
  27. var config = CKEDITOR.tools.extend(defaultConfig, editor.config.wordcount || {}, true);
  28. if (config.showCharCount) {
  29. var charLabel = editor.lang.wordcount[config.countHTML ? 'CharCountWithHTML' : 'CharCount'];
  30. defaultFormat += charLabel + '&nbsp;%charCount%';
  31. if (config.charLimit != 'unlimited') {
  32. defaultFormat += '&nbsp;(' + editor.lang.wordcount.limit + '&nbsp;' + config.charLimit + ')';
  33. }
  34. }
  35. if (config.showCharCount && config.showWordCount) {
  36. defaultFormat += ',&nbsp;';
  37. }
  38. if (config.showWordCount) {
  39. defaultFormat += editor.lang.wordcount.WordCount + ' %wordCount%';
  40. if (config.wordLimit != 'unlimited') {
  41. defaultFormat += '&nbsp;(' + editor.lang.wordcount.limit + '&nbsp;' + config.wordLimit + ')';
  42. }
  43. }
  44. defaultFormat += '</span>';
  45. var format = defaultFormat;
  46. CKEDITOR.document.appendStyleSheet(this.path + 'css/wordcount.css');
  47. function counterId(editorInstance) {
  48. return 'cke_wordcount_' + editorInstance.name;
  49. }
  50. function counterElement(editorInstance) {
  51. return document.getElementById(counterId(editorInstance));
  52. }
  53. function strip(html) {
  54. var tmp = document.createElement("div");
  55. tmp.innerHTML = html;
  56. if (tmp.textContent == '' && typeof tmp.innerText == 'undefined') {
  57. return '0';
  58. }
  59. return tmp.textContent || tmp.innerText;
  60. }
  61. function updateCounter(editorInstance) {
  62. var wordCount = 0,
  63. charCount = 0,
  64. normalizedText,
  65. text;
  66. if (text = editorInstance.getData()) {
  67. if (config.showCharCount) {
  68. if (config.countHTML) {
  69. charCount = text.length;
  70. } else {
  71. normalizedText = text.
  72. replace(/(\r\n|\n|\r)/gm, "").
  73. replace(/^\s+|\s+$/g, "").
  74. replace("&nbsp;", "").
  75. replace(" ", "");
  76. normalizedText = strip(normalizedText);
  77. charCount = normalizedText.length;
  78. }
  79. }
  80. if (config.showWordCount) {
  81. normalizedText = text.
  82. replace(/(\r\n|\n|\r)/gm, " ").
  83. replace(/^\s+|\s+$/g, "").
  84. replace("&nbsp;", " ");
  85. normalizedText = strip(normalizedText);
  86. wordCount = normalizedText.split(/\s+/).length;
  87. }
  88. }
  89. var html = format.replace('%wordCount%', wordCount).replace('%charCount%', charCount);
  90. counterElement(editorInstance).innerHTML = html;
  91. if (charCount == lastCharCount) {
  92. return true;
  93. }
  94. lastWordCount = wordCount;
  95. lastCharCount = charCount;
  96. // Check for word limit
  97. if (config.showWordCount && wordCount > config.wordLimit) {
  98. limitReached(editor, limitReachedNotified);
  99. } else if (config.showWordCount && wordCount == config.wordLimit) {
  100. // create snapshot to make sure only the content after the limit gets deleted
  101. editorInstance.fire('saveSnapshot');
  102. } else if (!limitRestoredNotified && wordCount < config.wordLimit) {
  103. limitRestored(editor);
  104. }
  105. // Check for char limit
  106. if (config.showCharCount && charCount > config.charLimit) {
  107. limitReached(editor, limitReachedNotified);
  108. } else if (config.showCharCount && charCount == config.charLimit) {
  109. // create snapshot to make sure only the content after the limit gets deleted
  110. editorInstance.fire('saveSnapshot');
  111. } else if (!limitRestoredNotified && charCount < config.charLimit) {
  112. limitRestored(editor);
  113. }
  114. return true;
  115. }
  116. function limitReached(editorInstance, notify) {
  117. limitReachedNotified = true;
  118. limitRestoredNotified = false;
  119. editorInstance.execCommand('undo');
  120. if (!notify) {
  121. //counterElement(editorInstance).className = "cke_wordcount cke_wordcountLimitReached";
  122. editorInstance.fire('limitReached', {}, editor);
  123. }
  124. // lock editor
  125. editorInstance.config.Locked = 1;
  126. }
  127. function limitRestored(editorInstance) {
  128. limitRestoredNotified = true;
  129. limitReachedNotified = false;
  130. editorInstance.config.Locked = 0;
  131. counterElement(editorInstance).className = "cke_wordcount";
  132. }
  133. editor.on('key', function (event) {
  134. updateCounter(event.editor);
  135. }, editor, null, 100);
  136. editor.on('uiSpace', function (event) {
  137. if (event.data.space == 'bottom') {
  138. event.data.html += '<div id="' + counterId(event.editor) + '" class="cke_wordcount" style=""' + ' title="' + editor.lang.wordcount.title + '"' + '>&nbsp;</div>';
  139. }
  140. }, editor, null, 100);
  141. editor.on('dataReady', function (event) {
  142. updateCounter(event.editor);
  143. }, editor, null, 100);
  144. /*editor.on('change', function (event) {
  145. updateCounter(event.editor);
  146. }, editor, null, 100);*/
  147. editor.on('afterPaste', function (event) {
  148. updateCounter(event.editor);
  149. }, editor, null, 100);
  150. /*editor.on('focus', function (event) {
  151. editorHasFocus = true;
  152. intervalId = window.setInterval(function () {
  153. updateCounter(editor);
  154. }, 300, event.editor);
  155. }, editor, null, 300);*/
  156. editor.on('blur', function () {
  157. if (intervalId) {
  158. window.clearInterval(intervalId);
  159. }
  160. }, editor, null, 300);
  161. if (!String.prototype.trim) {
  162. String.prototype.trim = function () {
  163. return this.replace(/^\s+|\s+$/g, '');
  164. };
  165. }
  166. }
  167. });