plugin.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or http://ckeditor.com/license
  4. */
  5. /**
  6. * @fileOverview Horizontal Page Break
  7. */
  8. 'use strict';
  9. ( function() {
  10. // Register a plugin named "pagebreak".
  11. CKEDITOR.plugins.add( 'pagebreak', {
  12. requires: 'fakeobjects',
  13. // jscs:disable maximumLineLength
  14. lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
  15. // jscs:enable maximumLineLength
  16. icons: 'pagebreak,pagebreak-rtl', // %REMOVE_LINE_CORE%
  17. hidpi: true, // %REMOVE_LINE_CORE%
  18. onLoad: function() {
  19. var cssStyles = (
  20. 'background:url(' + CKEDITOR.getUrl( this.path + 'images/pagebreak.gif' ) + ') no-repeat center center;' +
  21. 'clear:both;' +
  22. 'width:100%;' +
  23. 'border-top:#999 1px dotted;' +
  24. 'border-bottom:#999 1px dotted;' +
  25. 'padding:0;' +
  26. 'height:7px;' +
  27. 'cursor:default;'
  28. ).replace( /;/g, ' !important;' ); // Increase specificity to override other styles, e.g. block outline.
  29. // Add the style that renders our placeholder.
  30. CKEDITOR.addCss( 'div.cke_pagebreak{' + cssStyles + '}' );
  31. },
  32. init: function( editor ) {
  33. if ( editor.blockless )
  34. return;
  35. // Register the command.
  36. editor.addCommand( 'pagebreak', CKEDITOR.plugins.pagebreakCmd );
  37. // Register the toolbar button.
  38. editor.ui.addButton && editor.ui.addButton( 'PageBreak', {
  39. label: editor.lang.pagebreak.toolbar,
  40. command: 'pagebreak',
  41. toolbar: 'insert,12'
  42. } );
  43. // Webkit based browsers needs help to select the page-break.
  44. CKEDITOR.env.webkit && editor.on( 'contentDom', function() {
  45. editor.document.on( 'click', function( evt ) {
  46. var target = evt.data.getTarget();
  47. if ( target.is( 'div' ) && target.hasClass( 'cke_pagebreak' ) )
  48. editor.getSelection().selectElement( target );
  49. } );
  50. } );
  51. },
  52. afterInit: function( editor ) {
  53. // Register a filter to displaying placeholders after mode change.
  54. var dataProcessor = editor.dataProcessor,
  55. dataFilter = dataProcessor && dataProcessor.dataFilter,
  56. htmlFilter = dataProcessor && dataProcessor.htmlFilter,
  57. styleRegex = /page-break-after\s*:\s*always/i,
  58. childStyleRegex = /display\s*:\s*none/i;
  59. function upcastPageBreak( element ) {
  60. CKEDITOR.tools.extend( element.attributes, attributesSet( editor.lang.pagebreak.alt ), true );
  61. element.children.length = 0;
  62. }
  63. if ( htmlFilter ) {
  64. htmlFilter.addRules( {
  65. attributes: {
  66. 'class': function( value, element ) {
  67. var className = value.replace( 'cke_pagebreak', '' );
  68. if ( className != value ) {
  69. var span = CKEDITOR.htmlParser.fragment.fromHtml( '<span style="display: none;">&nbsp;</span>' ).children[ 0 ];
  70. element.children.length = 0;
  71. element.add( span );
  72. var attrs = element.attributes;
  73. delete attrs[ 'aria-label' ];
  74. delete attrs.contenteditable;
  75. delete attrs.title;
  76. }
  77. return className;
  78. }
  79. }
  80. }, { applyToAll: true, priority: 5 } );
  81. }
  82. if ( dataFilter ) {
  83. dataFilter.addRules( {
  84. elements: {
  85. div: function( element ) {
  86. // The "internal form" of a pagebreak is pasted from clipboard.
  87. // ACF may have distorted the HTML because "internal form" is
  88. // different than "data form". Make sure that element remains valid
  89. // by re-upcasting it (#11133).
  90. if ( element.attributes[ 'data-cke-pagebreak' ] )
  91. upcastPageBreak( element );
  92. // Check for "data form" of the pagebreak. If both element and
  93. // descendants match, convert them to internal form.
  94. else if ( styleRegex.test( element.attributes.style ) ) {
  95. var child = element.children[ 0 ];
  96. if ( child && child.name == 'span' && childStyleRegex.test( child.attributes.style ) )
  97. upcastPageBreak( element );
  98. }
  99. }
  100. }
  101. } );
  102. }
  103. }
  104. } );
  105. // TODO Much probably there's no need to expose this object as public object.
  106. CKEDITOR.plugins.pagebreakCmd = {
  107. exec: function( editor ) {
  108. // Create read-only element that represents a print break.
  109. var pagebreak = editor.document.createElement( 'div', {
  110. attributes: attributesSet( editor.lang.pagebreak.alt )
  111. } );
  112. editor.insertElement( pagebreak );
  113. },
  114. context: 'div',
  115. allowedContent: {
  116. div: {
  117. styles: '!page-break-after'
  118. },
  119. span: {
  120. match: function( element ) {
  121. var parent = element.parent;
  122. return parent && parent.name == 'div' && parent.styles && parent.styles[ 'page-break-after' ];
  123. },
  124. styles: 'display'
  125. }
  126. },
  127. requiredContent: 'div{page-break-after}'
  128. };
  129. // Returns an object representing all the attributes
  130. // of the "internal form" of the pagebreak element.
  131. function attributesSet( label ) {
  132. return {
  133. 'aria-label': label,
  134. 'class': 'cke_pagebreak',
  135. contenteditable: 'false',
  136. 'data-cke-display-name': 'pagebreak',
  137. 'data-cke-pagebreak': 1,
  138. style: 'page-break-after: always',
  139. title: label
  140. };
  141. }
  142. } )();