TinyMCE - A4 page Ruler

www.Zvarik.cz

by mzvarik

HTML

<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
<textarea><h1>What's poppin?</h1>
<p>
You get the idea, right? This is <b>pagebreak</b> here.
</p>
  <!-- pagebreak -->
  <p>
  This is after pagebreak... and you will see red line that goes for new page.
  </p>
  <p>
  <br><br><br><br><br><br><br><br><br><br><br>
  <br><br><br><br><br><br><br><br><br><br><br>Lot's of space..
  <br><br><br><br><br><br><br><br><br><br><br>Lot's of space...
  <br><br><br><br><br><br><br><br><br><br><br>Lot's of space..<br><br><br><br><br><br>
  AND THIS IS ON NEXT PAGE
  </p>
  
</textarea>

<tinystyle style="display:none">
/* THIS WOULD GO TO CONTENT_CSS - BUT I CANT DO THIS ON FIDDLE */
HTML{
    background: #686c6f;
    box-shadow: inset 1px 0 2px #00000091;
}
BODY#tinymce{
    width: 15cm; /* this should be 21 cm as the page size, but I have little space here in fiddle */
    min-height: 24.2cm; /* this should be 29.7 cm (A4 page) */
    background: #fff;
    display: block;
    box-shadow: 0 2px 7px rgba(0,0,0,0.7);
    margin: 5px auto 20px auto;
    padding: 1cm 1.10cm;
    box-sizing: border-box;
}
BODY#tinymce img.mce-pagebreak{
    cursor: default;
    cursor: grab;
    display: block;
    width: 100%;
    width: calc(100% + 2.2cm);
    margin-left: -1.1cm;
    margin-right: -1.1cm;
    height: 14px;
    margin-top: 20px;
    margin-bottom: 20px;
    page-break-before: always;
    border: 0;
    box-shadow: inset 0 5px 8px -6px rgba(0,0,0,1);
    border-bottom: 1px solid #555;
    background: linear-gradient(to right, #686C6F, #7F8284);
}
BODY#tinymce img.mce-pagebreak:hover{
    opacity: .9;
}
</tinystyle>

JavaScript

// plugin pravĂ­tko
		tinymce.PluginManager.add('ruler', function(editor) {
			
			var domHtml;
			var lastPageBreaks;
			
			function refreshRuler()
			{
				try {
          	domHtml = $( editor.getDoc().getElementsByTagName('HTML')[0] );
           
           // HACK - erase this, I have to put my CSS here
           console.log($('tinystyle').html() );
           domHtml.find('head').append( $('<style>'+$('tinystyle').html()+'</style>'));
            
				} catch (e) {
					return setTimeout(refreshRuler, 50);
				}
				
				var dpi = 96
				var cm = dpi/2.54;
				var a4px = cm * (29.7-5.7); // A4 height in px, -5.5 are my additional margins in my PDF print

				// ruler begins (in px)
				var startMargin = 4;
				
				// max size (in px) = document size + extra to be sure, idk, the height is too small for some reason
				var imgH = domHtml.height() + a4px*5;
				
				var pageBreakHeight = 14; // height of the pagebreak line in tinyMce
				
				var pageBreaks = [];
				domHtml.find('.mce-pagebreak').each(function(){
					pageBreaks[pageBreaks.length] = $(this).offset().top;
				});
				pageBreaks.sort();
				
				// if pageBreak is too close next page, then ignore it
				
				if (lastPageBreaks == pageBreaks) {
					return; // no change
				}
				lastPageBreaks = pageBreaks;
				
				console.log("Redraw ruler");
				
				var s = '';
				s+= '<svg width="100%" height="'+imgH+'" xmlns="http://www.w3.org/2000/svg">';

				s+= '<style>';
				s+= '.pageNumber{font-weight:bold;font-size:19px;font-family:verdana;text-shadow:1px 1px 1px rgba(0,0,0,.6);}';
				s+= '</style>';
				
				var pages = Math.ceil(imgH/a4px);

				var i, j, curY = startMargin;
				for (i=0; i<pages; i++)
				{
					var blockH = a4px;
					
					var isPageBreak = 0;
					for (var j=0; j<pageBreaks.length; j++) {
						if (pageBreaks[j] < curY + blockH) {
							// musime zmensit velikost stranky
							blockH = pageBreaks[j] - curY;
							// pagebreak prijde na konec stranky
							isPageBreak...