Forum Feature requests

JavaScript support property scrollWidth & scrollHeight

ontic
I'm trying to do some JavaScript manipulation on the page following the two-pass tutorial.
https://www.princexml.com/doc/two-pass/#two-pass

My goal is to manipulate the font size, but it seems the properties scrollWidth and scrollHeight are not supported? I'm also confused why the jQuery.outerWdith() & jQuery.outerHeight() methods return values whereas the DOM properties offsetWidth, offsetHeight and scrollHeight all return "undefined".

Any help would be much appreciated. Below is the template you can use for testing.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script src="jquery.js"></script>
<style>
.no-resize, .resize {
  width: 100px;
  height: 50px;
  border: 1px solid #000;
  color: #000;
  margin: 20px 0;
  font-size: 15px
}
.nowrap {
  width: 250px;
  white-space: nowrap;
}
</style>
</head>

<body>
<div class='container'>
  <div class='no-resize'>This text won't be resized and will go out of the div.</div>
  <div class='resize'>This text will be resized and wont go out of the div.</div>
  <div class='no-resize nowrap'>This text won't be resized and will go out of the div.</div>
  <div class='resize nowrap'>This text will also be resized and wont go out of the div.</div>
  <div id="test" class='resize nowrap'>This text will also be resized and wont go out of the div.<br/>New Line<br/>New Line<br/>New Line<br/>New Line</div>
</div>
<script>

$(document).ready(function()
	{
		var elements = $('.resize');
			
		if (elements.length < 0)
		{
			return;
		}
		
		elements.each(function(i, element)
			{
				// Debug: these output values
                // $(element).outerWidth();
                // $(element).outerHeight();
                //
                // Debug: these all output "undefined"
                // element.offsetWidth
                // element.offsetHeight
                // element.scrollHeight
				
				while (element.scrollWidth > element.offsetWidth || element.scrollHeight > element.offsetHeight)
				{
					var newFontSize = (parseFloat($(element).css('font-size').slice(0, -2)) * 0.95) + 'px';
					$(element).css('font-size', newFontSize);
				}
			}
		);
	}
);

Prince.trackBoxes = true;
Prince.addEventListener("complete", resizeText, false);

function resizeText()
{
	var htmlString = document.documentElement.innerHTML;
	console.log(htmlString);
}

</script>
</body>
</html>
mikeday
Perhaps the jQuery functions are calling getComputedStyle, which is supported, although it is not quite compatible with the browser as it returns the actual computed value while browsers return the used value.
ontic
@mikeday Does that mean it is not possible to possible to retrieve the calculated width/height of elements and or text?
mikeday
Not through the standard DOM properties, it requires using our box tracking API which is available after typesetting has finished.
ontic
I'm looking to make text fit within a container. The JavaScript above basically scales down the font size until both the width and height of the text fit perfectly within the bounds of a div element. Is something like this possible with Prince or the box tracking API? Is there any documentation or examples I could use as a guide?
mikeday
This may be quite slow if it requires running Prince multiple times until the correct size is reached, I think you would need to do it by scaling the font-size down by the correct factor in one go.

http://www.princexml.com/doc/two-pass/

http://www.princexml.com/forum/topic/3516/changebars
ontic
Thanks for the link. I'm sceptical whether this is possible (or performant) since I actually require the dimensions of the text (which is over-flowed) in order to scale it to fit the parent container. Because we're dealing with text, using Math (and a scale factor) isn't likely going to give accurate results, when attempting this in one go.

I created a prototype months ago for doing what I need, but it involves server side processing and third-party software.The general idea is to render text to SVG paths, injecting it into the HTML while settings the SVG to scale responsively E.g. 100% width and height, so fitting the parent container perfectly.

Given the third-party software used is open source and written in C, you could probably integrate something like this directly within Prince. I wouldn't be surprised if Prince was already using some of these libraries under the hood.

Let me know if this is of interest or would like to discuss further.

Edited by ontic

mikeday
Prince isn't performing hinting so the text is resolution independent and should scale down linearly if it's a single line, but not if it's multiple lines.

Feel free to email me (mikeday@yeslogic.com) if you would like to discuss further.
ontic
Thanks. I'll be in touch once I find time to put something together, with use-cases and possible ways of integrating this approach natively. E.g. through a custom event before the layout is finished https://www.princexml.com/doc/javascript/#js-event.

Edited by ontic