plugin.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
  3. For licensing, see LICENSE.html or http://ckeditor.com/license
  4. */
  5. /**
  6. * @file Plugin for inserting Drupal teaser and page breaks.
  7. */
  8. ( function() {
  9. var pluginRequires = [ 'fakeobjects' ];
  10. if (Drupal.ckeditor_ver == 3) {
  11. pluginRequires = [ 'fakeobjects', 'htmldataprocessor' ];
  12. }
  13. CKEDITOR.plugins.add( 'drupalbreaks',
  14. {
  15. requires : pluginRequires,
  16. init : function( editor )
  17. {
  18. var addCssObj = CKEDITOR;
  19. if (Drupal.ckeditor_ver == 3) {
  20. addCssObj = editor;
  21. }
  22. // Add the styles that renders our fake objects.
  23. addCssObj.addCss(
  24. 'img.cke_drupal_pagebreak,img.cke_drupal_break' +
  25. '{' +
  26. 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/pagebreak.gif' ) + ');' +
  27. 'background-position: center center;' +
  28. 'background-repeat: no-repeat;' +
  29. 'clear: both;' +
  30. 'display: block;' +
  31. 'float: none;' +
  32. 'width: 100%;' +
  33. 'border-top: #999999 1px dotted;' +
  34. 'border-bottom: #999999 1px dotted;' +
  35. 'height: 5px;' +
  36. '}' +
  37. 'img.cke_drupal_break' +
  38. '{' +
  39. 'border-top: #FF0000 1px dotted;' +
  40. 'border-bottom: #FF0000 1px dotted;' +
  41. '}'
  42. );
  43. // Register the toolbar buttons.
  44. editor.ui.addButton( 'DrupalBreak',
  45. {
  46. label : Drupal.t('Insert Teaser Break'),
  47. icon : this.path + 'images/drupalbreak.png',
  48. command : 'drupalbreak'
  49. });
  50. editor.addCommand( 'drupalbreak',
  51. {
  52. exec : function()
  53. {
  54. // There should be only one <!--break--> in document. So, look
  55. // for an image with class "cke_drupal_break" (the fake element).
  56. var images = editor.document.getElementsByTag( 'img' );
  57. for ( var i = 0, len = images.count() ; i < len ; i++ )
  58. {
  59. var img = images.getItem( i );
  60. if ( img.hasClass( 'cke_drupal_break' ) )
  61. {
  62. if ( confirm( Drupal.t( 'The document already contains a teaser break. Do you want to proceed by removing it first?' ) ) )
  63. {
  64. img.remove();
  65. break;
  66. }
  67. else
  68. return;
  69. }
  70. }
  71. insertComment( 'break' );
  72. }
  73. } );
  74. editor.ui.addButton( 'DrupalPageBreak',
  75. {
  76. label : Drupal.t( 'Insert Page Break' ),
  77. icon : this.path + 'images/drupalpagebreak.png',
  78. command : 'drupalpagebreak'
  79. });
  80. editor.addCommand( 'drupalpagebreak',
  81. {
  82. exec : function()
  83. {
  84. insertComment( 'pagebreak' );
  85. }
  86. } );
  87. // This function effectively inserts the comment into the editor.
  88. function insertComment( text )
  89. {
  90. // Create the fake element that will be inserted into the document.
  91. // The trick is declaring it as an <hr>, so it will behave like a
  92. // block element (and in effect it behaves much like an <hr>).
  93. if ( !CKEDITOR.dom.comment.prototype.getAttribute ) {
  94. CKEDITOR.dom.comment.prototype.getAttribute = function() {
  95. return '';
  96. };
  97. CKEDITOR.dom.comment.prototype.attributes = {
  98. align : ''
  99. };
  100. }
  101. var fakeElement = editor.createFakeElement( new CKEDITOR.dom.comment( text ), 'cke_drupal_' + text, 'hr' );
  102. // This is the trick part. We can't use editor.insertElement()
  103. // because we need to put the comment directly at <body> level.
  104. // We need to do range manipulation for that.
  105. // Get a DOM range from the current selection.
  106. var range = editor.getSelection().getRanges()[0],
  107. elementsPath = new CKEDITOR.dom.elementPath( range.getCommonAncestor( true ) ),
  108. element = ( elementsPath.block && elementsPath.block.getParent() ) || elementsPath.blockLimit,
  109. hasMoved;
  110. // If we're not in <body> go moving the position to after the
  111. // elements until reaching it. This may happen when inside tables,
  112. // lists, blockquotes, etc.
  113. while ( element && element.getName() != 'body' )
  114. {
  115. range.moveToPosition( element, CKEDITOR.POSITION_AFTER_END );
  116. hasMoved = 1;
  117. element = element.getParent();
  118. }
  119. // Split the current block.
  120. if ( !hasMoved )
  121. range.splitBlock( 'p' );
  122. // Insert the fake element into the document.
  123. range.insertNode( fakeElement );
  124. // Now, we move the selection to the best possible place following
  125. // our fake element.
  126. var next = fakeElement;
  127. while ( ( next = next.getNext() ) && !range.moveToElementEditStart( next ) )
  128. {}
  129. range.select();
  130. }
  131. },
  132. afterInit : function( editor )
  133. {
  134. // Adds the comment processing rules to the data filter, so comments
  135. // are replaced by fake elements.
  136. editor.dataProcessor.dataFilter.addRules(
  137. {
  138. comment : function( value )
  139. {
  140. if ( !CKEDITOR.htmlParser.comment.prototype.getAttribute ) {
  141. CKEDITOR.htmlParser.comment.prototype.getAttribute = function() {
  142. return '';
  143. };
  144. CKEDITOR.htmlParser.comment.prototype.attributes = {
  145. align : ''
  146. };
  147. }
  148. if ( value == 'break' || value == 'pagebreak' )
  149. return editor.createFakeParserElement( new CKEDITOR.htmlParser.comment( value ), 'cke_drupal_' + value, 'hr' );
  150. return value;
  151. }
  152. });
  153. }
  154. });
  155. } )();