Preparing for advanced uses

This walk-through illustrates taking a classic document that has a controlled print experience and works only in Internet Explorer and making it work with ScriptX.Services in any browser on any platform using the minimum amount of development effort and making as few changes as possible (though more changes might be desirable).

Previously : Stage 5 - Prompted printing

Background

If the additions made to provide an on document UI are excluded, a few lines of code have been added to achieve use from anywhere:

<!-- Add.on to scriptx.services compatibility -->
<script src="//cdn.jsdelivr.net/npm/scriptxprint-html@1.6.2/dist/meadco-scriptxservicesUI.min.js"
    data-meadco-license="370000ed-d40c-43d4-b3d3-f2e7d2eff47d"
    data-meadco-server="http://127.0.0.1:41191"
	data-meadco-license-path="warehouse"
	data-meadco-license-revision="0"
	data-meadco-syncinit="true"
>
</script>

The addition of prompted printing and page setup dialogs has necessitated using Bootstrap or writing own code. Even so the changes to the document HTML is very small and although this walkthrough illustrates use of few of the ScriptX properties and methods these simple code updates do apply to a significant number of scenarious and might well be sufficient for most needs.

What is lacking however is support for asynchronous working, some deeper error checking and in particular the ubiquitous function WaitForSpoolingComplete().

ScriptX.Addon provides asynchronous working - i.e. keeping the browser responsive - while providing for synchronous coding - i.e. execution of javascript “pauses” while a ScriptX.Addon function executes. This includes dialogs. So, for example this code can be written:

if ( factory.printing.PageSetup() ) {
    factory.printing.Print(false);
    factory.printing.WaitForSpoolingComplete();
    self.close();
}

In the above, the Page Setup dialog does not return until the dialog closes, the Print API returns immediately, though printing continues asynchronously and WaitForSpoolingComplete() does not return until that asynchronous printing is complete.

Similarly, when ScriptX.Addon self initialises it does so in a way that does not make the browser unresponsive. All properties are available when on page script runs.

This makes for very convenient coding.

This presents a significant problem to implementimg a library emulating the API of ScriptX.Addon for ScriptX.Services as calls must be made to a server service and dialogs etc are implemented in javascript. Service calls can be made synchronous but this has the effect of making the browser unresponsive and would be unacceptable during, as an example, a page print which may take 30 seconds or more. Note that download and caching a license can take a significant time during which the browser would be unresponsive.

Modern javascript provides for async and await. But, using such constructs is diffucult with older browsers where support would require the use of transpiler tools leading to significantly increased effort to take current code and enable it to work with ScriptX.Services.

Noting that :

  • in ScriptX.Addon the print process itself is asynchronous and remains so in ScriptX.Services,
  • some calls to ScriptX.Services are very quick, especially when communicating with ScriptX.Services for Windows PC and
  • code using promises can be supported on browsers from IE 11 onwards

then a compromise can be reached that provides for asynchronous working where it matters and yet requires a reasonably limited set of coding changes, especially if  MeadCoScriptXJS Library is already in use.

MeadCoScriptXJS Library

The library has been available for many years and is widely used by developers working with ScriptX.Addon.

While not mandatory, the library provides the following advantages

  • Useful 'wrapper' functions to common tasks.
  • Hides differences between ScriptX.Add-on and ScriptX.Services by providing promise based implementations of asynchronous APIs (e.g. the PageSetup() dialog and WaitForSpoolingComplete().
  • Improved error handling and reporting especially for code making use of a ScriptX license (which is always the case for ScriptX.Services).
To use the libary:





Enabling async

To enable asynchronous initialisation of ScriptX.Services emulation of ScriptX.Add-on, simply change the syncinit parameter to false:

<!-- Add.on to scriptx.services compatibility -->
<script src="//cdn.jsdelivr.net/npm/scriptxprint-html@1.6.2/dist/meadco-scriptxservicesUI.min.js"
    data-meadco-license="370000ed-d40c-43d4-b3d3-f2e7d2eff47d"
    data-meadco-server="http://127.0.0.1:41191"
    data-meadco-license-path="warehouse"
	data-meadco-license-revision="0"
	data-meadco-syncinit="false"
>
</script>
Page initialisation

Now that initialisation is asynchronous, page script should not run until the initialisation is complete. This block of code needs to be wrapped around the current code:

MeadCo.Licensing.IsLicensedAsync()
	.then(function (l) {
		MeadCo.ScriptX.InitAsync()
            .then(function () {

                // page script goes here.

            })
            .catch(function (e) {
						reportError("Unable to intialise ScriptX: " + e)
					});
			})
	.catch(function (e) {
		reportError("Unable to use ScriptX License: " + e)
	});
Update current calls

In MeadCoScriptXJS MeadCo.ScriptX.Printing is the same as factory.printing and so this:

factory.printing.header = "My page header";

Can be changed to this:

MeadCo.ScriptX.Printing.header = "My page header";

Making changes such as the above is optional.

The MeadCo.ScriptX object implements a number of helper methods that enable the same script code to work with both ScriptX.Addon and ScriptX.Services by introducing the use of promises()

For example, the issue with dialogs can be resolved:

MeadCo.ScriptX.PageSetup2().then(function() {
    console.log("Page setup changed by user");
});

The complete code is now:

<!-- For async, a promise library is required for IE 11.
    We use and test with promise-polyfill.
    see https://github.com/taylorhakes/promise-polyfill
-->
<script> src="//cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>

<!-- Helper library to obscure differences between .Addon and .Services
    see https://github.com/MeadCo/MeadCoScriptXJS
-->
<!-- Use of this code is indicated by use of MeadCo.ScriptX and MeadCo.ScriptX.Printing prefixes -->
<!-- Please note that the library must be initialised - it does not auto initialise -->
<script src="//cdn.jsdelivr.net/npm/meadco-scriptxjs@1/dist/meadco-scriptx.min.js"></script>

<!-- javscript Add.on to Scriptx.Services compatibility -->
<!-- Connect to ScriptX.Services for Windows PC -->
<!-- Use the same evaluation GUID - it is subject to change -->
<script src="//cdn.jsdelivr.net/npm/scriptxprint-html@1.6.2/dist/meadco-scriptxservicesUI.min.js"
        data-meadco-license="370000ed-d40c-43d4-b3d3-f2e7d2eff47d"
        data-meadco-server="http://127.0.0.1:41191"
        data-meadco-license-path="warehouse"
        data-meadco-license-revision="0"
        data-meadco-syncinit="false">
</script>

<!-- leave current script as is, it will work .. to minimise effort -->
<script>
function initView() {
    factory.printing.enhancedFormatting.allPagesHeader =
        "<div><center><img src='http://services.meadroid.com/images/sx-header.png'></center></div>";
    factory.printing.enhancedFormatting.allPagesFooter =
        "<div><center><img src='http://services.meadroid.com/images/sx-footer-final.png'></center></div>";
    factory.printing.SetMarginMeasure(2) // set inches
    factory.printing.header = ""
    factory.printing.footer = ""
    factory.printing.leftMargin = 0.75
    factory.printing.topMargin = 1.5
    factory.printing.rightMargin = 0.75
    factory.printing.bottomMargin = 1.5
}
</script>

<!-- enable detailed logging -->
<script type="text/javascript">
console.log("Page script starting");
// If ScriptX.Services client libraries have been loaded enable some more verbose logging for debugging purposes
if (typeof MeadCo === "object") {
    console.log("enable verbose logging in ScriptX.Services");
    MeadCo.logEnabled = true;
}

// If ScriptX.Services client libraries have been loaded then overload the error report functions
// to use the error reporting code for this application (for demonstration, we use simple javascript alert).
if (typeof MeadCo === "object" && typeof MeadCo.ScriptX === "object" && typeof MeadCo.ScriptX.Print === "object") {
    // overload cloud print library report error
    MeadCo.ScriptX.Print.reportServerError = function (errorTxt) {
        console.error(errorTxt);
        alert("ScriptX.Services error\n\n" + errorTxt);
    }

    MeadCo.ScriptX.Print.reportFeatureNotImplemented = function (featureDescription) {
        var msg = "Sorry " + featureDescription +
            " is not available yet with ScriptX.Services."

        console.warn(msg);
        alert(msg);
    }
}
</script>

<!-- new UI script -->
<script type="text/javascript">
$(window).on("load", function () {
    console.log("Start view");
    MeadCo.Licensing.IsLicensedAsync()
        .then(function (l) {
            MeadCo.ScriptX.InitAsync()
                .then(function () {
                    initView();
                    $("#btn-print").click(function () {
                        factory.printing.Print(true);
                    });

                    $("#btn-preview").click(function () {
                        factory.printing.Preview();
                    });

                    $("#btn-setup").click(function () {
                        MeadCo.ScriptX.PageSetup2().then(function () {
                            console.log("Page setup changed by user");
                        });
                    });
                })
                .catch(function (e) {
                    reportError("Unable to initialise ScriptX: " + e)
                });
        })
        .catch(function (e) {
            reportError("Unable to use ScriptX License: " + e)
        });
});
</script>

Open your browser (any browser) and go to the address  https://scriptxprintsamples.meadroid.com/ThenToNow/now-stage6

Note that there are no warnings to the console about deprecated synchronous AJAX calls.

Next up: Stage 7 - WaitForSpoolingComplete().