- Introducing Online Image Processor
- Complementing the File API
- Handling Errors
- Conclusion
Handling Errors
HTML5 applications must adapt to error situations that arise so that users aren't left guessing as to why they aren't working as expected (or are not responding). If you fail to make your application robust, frustrated users will probably stop using it and broadcast its failure to others.
One error situation that often confuses users is why a browser such as Firefox sometimes displays a dialog box containing text such as "warning: unresponsive script (not responding)" when the user is trying to load a web page.
JavaScript applications are single-threaded and rely on Image, FileReader, and other types to perform asynchronous operations on their behalf. Browsers such as Firefox monitor this thread. If they detect unresponsiveness (perhaps the thread is performing a lengthy calculation that's taking too long to complete), the browser presents the aforementioned dialog box.
Although users are unlikely to encounter the "warning: unresponsive script (not responding)" dialog box when running any of the HTML5 applications presented in this series, they'll probably wonder why OIP (when run on Chrome or Firefox) doesn't do anything when they try to load a non-image file (perhaps a text file). Instead, OIP displays a black canvas and lets the user select an image-processing operation.
To guard against this situation, two changes need to be made to OIP. First, the Chrome/Firefox version of OIP must at least display a dialog box stating that the image could not be loaded and that the user should try again. This isn't necessary with the Safari/Opera version, whose OIP_uf.php script verifies that a GIF/JPEG file has been uploaded and outputs an error message if any other filetype is detected.
My second version of OIP (see the article's code file) appends the following code fragment to OIP.js's loadImage(files) function, to make the user aware that the image could not be loaded via a simple dialog box. The user is not left staring at a black canvas and wondering what happened to the file:
image.onerror = function() { alert("Invalid image file, or otherwise unable to load image file."); }
This code fragment takes advantage of the fact that JavaScript's Image type provides onerror and onabort properties to which anonymous functions can be assigned. These functions are invoked whenever an error arises or when an image-loading operation is aborted (most likely as the result of some user interaction with the browser), respectively.
The code fragment simply assigns an anonymous function to image's onerror property, and this function acts as an error handler. I haven't assigned an anonymous function to image's onabort property for brevity, and leave doing so an exercise. Its implementation should be just as trivial as the implementation of the onerror handler function.
The second change that I need to make to OIP is to disable the image processing dropdown listbox and (for Firefox) the Save button when no image has been loaded. After the application successfully loads an image, these HTML controls should be enabled. This task can be accomplished by assigning true or false to a control's disabled attribute.
To accomplish this task, I made the following changes to OIP.html:
// Add the disabled=true attribute to the <select> tag, as follows: document.write("<select id='processor_list' "+ "onchange='process()' disabled=true>"); // Add the id='save' attribute and the disabled=true attribute to the <input> tag, as follows: document.write(" <input type='submit' value='save' id='save'"+ "onclick='saveToFile()' disabled=true>");
I also appended the following code fragment to the anonymous function assigned to image.onload in OIP.js's loadImage(files) function:
if (getFirefoxVersion() != null || getChromeVersion() != null) document.getElementById("processor_list").disabled = false; if (getFirefoxVersion() != null) document.getElementById("save").disabled = false;
The first line enables the dropdown listbox control identified as processor_list when the current browser is Firefox or Chrome because this control is initially disabled when OIP runs under these browsers. The second line enables the submit button identified as save when the current browser is Firefox because this control is initially disabled when OIP runs under this browser.
An error situation that often confuses developers is a security exception being thrown instead of a canvas's content being returned when the canvas context's getImageData(x, y, width, height) method is called. The security exception is thrown to prevent this method from violating JavaScript's same origin policy.
This security issue has been discussed at length in various blogs. For example, Aaron Train brings up this item in his “HTML5 Canvas/getImageData and the Nefarious” blog post. I've found this post's responses enlightening.
Furthermore, this security issue is why you cannot run OIP from the local host and attempt to load an image file from the local filesystemGoogle takes security very seriously. Check out Thomas Claburn's “Google's Chrome Team Mulls Local File Restrictions” article for more information.