1 /*
  2 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5 
  6 /**
  7  * @file Horizontal Page Break
  8  */
  9 
 10 // Register a plugin named "pagebreak".
 11 CKEDITOR.plugins.add( 'pagebreak',
 12 {
 13 	init : function( editor )
 14 	{
 15 		// Register the command.
 16 		editor.addCommand( 'pagebreak', CKEDITOR.plugins.pagebreakCmd );
 17 
 18 		// Register the toolbar button.
 19 		editor.ui.addButton( 'PageBreak',
 20 			{
 21 				label : editor.lang.pagebreak,
 22 				command : 'pagebreak'
 23 			});
 24 
 25 		var cssStyles = [
 26 			'{' ,
 27 				'background: url(' + CKEDITOR.getUrl( this.path + 'images/pagebreak.gif' ) + ') no-repeat center center;' ,
 28 				'clear: both;' ,
 29 				'width:100%; _width:99.9%;' ,
 30 				'border-top: #999999 1px dotted;' ,
 31 				'border-bottom: #999999 1px dotted;' ,
 32 				'padding:0;' ,
 33 				'height: 5px;' ,
 34 				'cursor: default;' ,
 35 			'}'
 36 			].join( '' ).replace(/;/g, ' !important;' );	// Increase specificity to override other styles, e.g. block outline.
 37 
 38 		// Add the style that renders our placeholder.
 39 		editor.addCss( 'div.cke_pagebreak' + cssStyles );
 40 
 41 		// Opera needs help to select the page-break.
 42 		CKEDITOR.env.opera && editor.on( 'contentDom', function()
 43 		{
 44 			editor.document.on( 'click', function( evt )
 45 			{
 46 				var target = evt.data.getTarget();
 47 				if ( target.is( 'div' ) && target.hasClass( 'cke_pagebreak')  )
 48 					editor.getSelection().selectElement( target );
 49 			});
 50 		});
 51 	},
 52 
 53 	afterInit : function( editor )
 54 	{
 55 		var label = editor.lang.pagebreakAlt;
 56 
 57 		// Register a filter to displaying placeholders after mode change.
 58 		var dataProcessor = editor.dataProcessor,
 59 			dataFilter = dataProcessor && dataProcessor.dataFilter,
 60 			htmlFilter = dataProcessor && dataProcessor.htmlFilter;
 61 
 62 		if ( htmlFilter )
 63 		{
 64 			htmlFilter.addRules(
 65 			{
 66 				attributes : {
 67 					'class' : function( value, element )
 68 					{
 69 						var className =  value.replace( 'cke_pagebreak', '' );
 70 						if ( className != value )
 71 						{
 72 							var span = CKEDITOR.htmlParser.fragment.fromHtml( '<span style="display: none;"> </span>' );
 73 							element.children.length = 0;
 74 							element.add( span );
 75 							var attrs = element.attributes;
 76 							delete attrs[ 'aria-label' ];
 77 							delete attrs.contenteditable;
 78 							delete attrs.title;
 79 						}
 80 						return className;
 81 					}
 82 				}
 83 			}, 5 );
 84 		}
 85 
 86 		if ( dataFilter )
 87 		{
 88 			dataFilter.addRules(
 89 				{
 90 					elements :
 91 					{
 92 						div : function( element )
 93 						{
 94 							var attributes = element.attributes,
 95 								style = attributes && attributes.style,
 96 								child = style && element.children.length == 1 && element.children[ 0 ],
 97 								childStyle = child && ( child.name == 'span' ) && child.attributes.style;
 98 
 99 							if ( childStyle && ( /page-break-after\s*:\s*always/i ).test( style ) && ( /display\s*:\s*none/i ).test( childStyle ) )
100 							{
101 								attributes.contenteditable = "false";
102 								attributes[ 'class' ] = "cke_pagebreak";
103 								attributes[ 'data-cke-display-name' ] = "pagebreak";
104 								attributes[ 'aria-label' ] = label;
105 								attributes[ 'title' ] = label;
106 
107 								element.children.length = 0;
108 							}
109 						}
110 					}
111 				});
112 		}
113 	},
114 
115 	requires : [ 'fakeobjects' ]
116 });
117 
118 CKEDITOR.plugins.pagebreakCmd =
119 {
120 	exec : function( editor )
121 	{
122 		var label = editor.lang.pagebreakAlt;
123 
124 		// Create read-only element that represents a print break.
125 		var pagebreak = CKEDITOR.dom.element.createFromHtml(
126 			'<div style="' +
127 			'page-break-after: always;"' +
128 			'contenteditable="false" ' +
129 			'title="'+ label + '" ' +
130 			'aria-label="'+ label + '" ' +
131 			'data-cke-display-name="pagebreak" ' +
132 			'class="cke_pagebreak">' +
133 			'</div>', editor.document );
134 
135 		var ranges = editor.getSelection().getRanges( true );
136 
137 		editor.fire( 'saveSnapshot' );
138 
139 		for ( var range, i = ranges.length - 1 ; i >= 0; i-- )
140 		{
141 			range = ranges[ i ];
142 
143 			if ( i < ranges.length -1 )
144 				pagebreak = pagebreak.clone( true );
145 
146 			range.splitBlock( 'p' );
147 			range.insertNode( pagebreak );
148 			if ( i == ranges.length - 1 )
149 			{
150 				var next = pagebreak.getNext();
151 				range.moveToPosition( pagebreak, CKEDITOR.POSITION_AFTER_END );
152 
153 				// If there's nothing or a non-editable block followed by, establish a new paragraph
154 				// to make sure cursor is not trapped.
155 				if ( !next || next.type == CKEDITOR.NODE_ELEMENT && !next.isEditable() )
156 					range.fixBlock( true, editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p'  );
157 
158 				range.select();
159 			}
160 		}
161 
162 		editor.fire( 'saveSnapshot' );
163 	}
164 };
165