Dynamically update images

It is possible to dynamically update or add images to the DOM via JavaScript. However, image loading takes place asynchron from the rendering. This is usually not a problem in a web browser, since it will just display images after they have been loaded. But obviously this is indeed a problem in pdfChip and therefore the JavaScript code has to make sure that all images are loaded before the PDF page is created.

This article first describes a few approaches to overcome this problem. The last download does in addition contain a utility script "cchipUtils.js" that provides a convenient way to resolve this problem.

A way to resolve the problem of dynamic image loading is the cchip.onPrintReady() function that is built into pdfChip.

The cchip.onPrintReady() function

cchip.onPrintReady( f ) installs a callback function f() that is called when the DOM is ready for printing, e.g. all images are loaded. The normal way to use this function is to first manipulate the DOM, then call cchip.onPrintReady( f ) that calls f() when the DOM is ready and exit the cchipPrintLoop(). The function f() must call cchip.printPages() in order to actually create PDF pages from the DOM and initiate further DOM manipulations and printing if required.

The following example illustrates how this function can be used.

<html>
    <head>
        <script>
            function cchipPrintLoop(){
                var img = document.getElementById("myimg");
                img.src = "files/image.jpg";
                cchip.onPrintReady( cchip.printPages );
            }
        </script>
	</head>
	<body>
	    <img id="myimg" src="files/2.png">
	</body>
</html>

The cchipPrintLoop() function is used to place an image (image.jpg) into the DOM. Instead of directly calling cchip.printPages it calls the cchip.onPrintReady function that installs cchip.printPages as a callback function which makes sure that it will only be used after all images have been loaded.

Dynamically load images

cchip.onPrintReady has, however, one severe problem: It cannot be used in a loop, so that iterating over a number of images would not work. Instead a more complex way has to be used.

<html>
	<head>
		<script type="text/javascript">

		   	function setImage(i) {
				if ( i != 1 ) {
					cchip.printPages()
				}
				if (i<9) {
					var img = document.getElementById("myimg");
					img.src = "files/" + i + ".png";
					cchip.onPrintReady(function () {setImage(i+1)} );
				}
			}
			function cchipPrintLoop() {
				setImage(1);
			}

	    </script>
	</head>
	<body>
	    <img id="myimg" style="width:100mm" src="files/2.png">
	</body>
</html>

In this example the cchip.PrintLoop calls a setImage function with a parameter 1. For this first time (i=1) cchip.printPages is not called but the image object on the page is replaced with 1.png and then cchip.onPrintReady calls this function again for the next page. Since cchip.onPrintReady waits until all images are loaded this will only take place after the image is in the DOM and then cchip.printPages will be executed as the first statement in the next setImage run.

 

Dynamically load images using an array

The previous example is not ideal because image names need to have numbers to address them. The example below uses an array instead that lists all image paths, so that images may have arbitrary names.

It is even possible to use this example and put arbitrary objects into the "data" array and they will be placed into the corresponding CSS ID. Only the type of object identified by the ID has to work with the entries of the data array; in this example it has to be an image.

Dynamically load images using cchipUtils.js

This example uses a utility JavaScript that you may use in your HTML instead. That allows you to get rid of the rather complex code inside of your own JavaScript but to only reference the utility script instead. The utility script provides a function "cchip.modifyAndPrintDom" that can be used inside of a cchipPrintLoop.

<html>
	<head>
	    <script src="js/cchipUtils.js"></script>
	    <script type="text/javascript">
		    function setImageArg( urlString ) {
		        document.getElementById("myimg").src = urlString;
		    }
		    function cchipPrintLoop() {
		    	cchip.modifyAndPrintDom( setImageArg, 
    				["files/icon_pdfchip_l_white.png"
		        	,"files/icon_pdfchip_s.png"
		        	,"files/icon_pdfchip.png"
		        	,"files/icon_pdfchip_m.png"
		        	,"files/icon_pdfchip_s_white.png"
		        	,"files/icon_pdfchip_l_white.png"
		        	,"files/icon_pdfchip_m_white.png"
		        	,"files/icon_pdfchip_l.png"] );
			}
		</script>
	</head>
	<body >
		<img id="myimg" style="width:100mm" src="files/image.jpg">
	</body>
</html>

cchip.modifyAndPrintDom takes the name of a function that modifies the DOM as it's first parameter and an array of objects as it's second parameter. The array of objects should contain all objects that are to be feeded into the modifying function for modifying the DOM. The modifying function, in this example "setImageArg", has to have a parameter as placeholder for the new content. The function will be called for each item in the array with the respective item as parameter.

The main purpose of cchip.modifyAndPrintDom is to make sure that the DOM is fully updated with any modifications before it creates a PDF output from the current state of the DOM.