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/dist/meadco-scriptxservicesUI.min.js"
data-meadco-license="3cfd70e2-f38f-4ab2-95f4-4ce4c1e39497"
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:
<!--
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
-->
<script src="//cdn.jsdelivr.net/npm/meadco-scriptxjs@1/dist/meadco-scriptx.min.js"></script>
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/dist/meadco-scriptxservicesUI.min.js"
data-meadco-license="3cfd70e2-f38f-4ab2-95f4-4ce4c1e39497"
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.ScriptX.InitAsync()
.then(function () {
// page script goes here.
})
.catch(function (e) {
reportError("Unable to intialise ScriptX: " + 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/dist/meadco-scriptxservicesUI.min.js"
data-meadco-license="3cfd70e2-f38f-4ab2-95f4-4ce4c1e39497"
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() {
// WARNING: use of .enhancedFormatting requires a license with Enhanced Formatting enabled.
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>";
// Remove the above two lines if testing with a license without Enhanced Formatting enabled.
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.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)
});
});
</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.