plugin.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * @file change event plugin for CKEditor
  3. * Copyright (C) 2011 Alfonso Mart�nez de Lizarrondo
  4. *
  5. * == BEGIN LICENSE ==
  6. *
  7. * Licensed under the terms of any of the following licenses at your
  8. * choice:
  9. *
  10. * - GNU General Public License Version 2 or later (the "GPL")
  11. * http://www.gnu.org/licenses/gpl.html
  12. *
  13. * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
  14. * http://www.gnu.org/licenses/lgpl.html
  15. *
  16. * - Mozilla Public License Version 1.1 or later (the "MPL")
  17. * http://www.mozilla.org/MPL/MPL-1.1.html
  18. *
  19. * == END LICENSE ==
  20. *
  21. */
  22. // Keeps track of changes to the content and fires a "change" event
  23. CKEDITOR.plugins.add( 'onchange',
  24. {
  25. init : function( editor )
  26. {
  27. // // Test:
  28. // editor.on( 'change', function(e) { console.log( e ) });
  29. var timer,
  30. theMutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
  31. observer;
  32. // http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#mutation-observers
  33. // http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/
  34. // Avoid firing the event too often
  35. function somethingChanged()
  36. {
  37. // don't fire events if the editor is readOnly as they are false detections
  38. if (editor.readOnly)
  39. return;
  40. if (timer)
  41. return;
  42. timer = setTimeout( function() {
  43. timer = 0;
  44. editor.fire( 'change' );
  45. }, editor.config.minimumChangeMilliseconds || 100);
  46. }
  47. // Kill the timer on editor destroy
  48. editor.on( 'destroy', function() { if ( timer ) clearTimeout( timer ); timer = null; });
  49. // in theory this block should be enabled only for browsers that don't support MutationObservers,
  50. // but it doesn't seem to fire correctly in all the situations. Maybe in the future...
  51. {
  52. // Set several listeners to watch for changes to the content
  53. editor.on( 'saveSnapshot', function( evt )
  54. {
  55. if ( !evt.data || !evt.data.contentOnly )
  56. somethingChanged();
  57. });
  58. var undoCmd = editor.getCommand('undo');
  59. undoCmd && undoCmd.on( 'afterUndo', somethingChanged);
  60. var redoCmd = editor.getCommand('redo');
  61. redoCmd && redoCmd.on( 'afterRedo', somethingChanged);
  62. editor.on( 'afterCommandExec', function( event )
  63. {
  64. if ( event.data.name == 'source' )
  65. return;
  66. if ( event.data.command.canUndo !== false )
  67. somethingChanged();
  68. } );
  69. }
  70. if ( theMutationObserver )
  71. {
  72. observer = new theMutationObserver( function( mutations ) {
  73. somethingChanged();
  74. } );
  75. // To check that we are using a cool browser.
  76. if (window.console && window.console.log)
  77. console.log("Detecting changes using MutationObservers");
  78. }
  79. // Changes in WYSIWYG mode
  80. editor.on( 'contentDom', function()
  81. {
  82. if ( observer )
  83. {
  84. // A notification is fired right now, but we don't want it so soon
  85. var interval = setInterval( function() {
  86. if ( typeof editor.document === 'object' ) {
  87. observer.observe( editor.document.getBody().$, {
  88. attributes: true,
  89. childList: true,
  90. characterData: true
  91. });
  92. clearInterval(interval);
  93. }
  94. }, 100);
  95. }
  96. editor.document.on( 'keydown', function( event )
  97. {
  98. // Do not capture CTRL hotkeys.
  99. if ( event.data.$.ctrlKey ||event.data.$.metaKey )
  100. return;
  101. var keyCode = event.data.$.keyCode;
  102. // Filter movement keys and related
  103. if (keyCode==8 || keyCode == 13 || keyCode == 32 || ( keyCode >= 46 && keyCode <= 90) || ( keyCode >= 96 && keyCode <= 111) || ( keyCode >= 186 && keyCode <= 222) || keyCode == 229)
  104. somethingChanged();
  105. });
  106. // Firefox OK
  107. editor.document.on( 'drop', somethingChanged);
  108. // IE OK
  109. editor.document.getBody().on( 'drop', somethingChanged);
  110. });
  111. // Detect changes in source mode
  112. editor.on( 'mode', function( e )
  113. {
  114. if ( editor.mode != 'source' )
  115. return;
  116. var textarea = (editor.textarea || editor._.editable);
  117. textarea.on( 'keydown', function( event )
  118. {
  119. // Do not capture CTRL hotkeys.
  120. if ( !event.data.$.ctrlKey && !event.data.$.metaKey )
  121. somethingChanged();
  122. });
  123. textarea.on( 'drop', somethingChanged);
  124. textarea.on( 'input', somethingChanged);
  125. if (CKEDITOR.env.ie)
  126. {
  127. textarea.on( 'cut', somethingChanged);
  128. textarea.on( 'paste', somethingChanged);
  129. }
  130. });
  131. } //Init
  132. } );