From 9bb647e27577f78c281a950bb27f9fd3eebb5a07 Mon Sep 17 00:00:00 2001 From: David Hudson Date: Sun, 4 Sep 2016 19:19:14 +0900 Subject: [PATCH] [Testing] Add better dependency injection and error handling --- platform/features/plot/bundle.js | 13 ++- platform/features/plot/src/PlotController.js | 6 +- .../plot/src/services/ExportImageService.js | 93 +++++++++++-------- 3 files changed, 68 insertions(+), 44 deletions(-) diff --git a/platform/features/plot/bundle.js b/platform/features/plot/bundle.js index bec42694b3..874f8fa240 100644 --- a/platform/features/plot/bundle.js +++ b/platform/features/plot/bundle.js @@ -92,7 +92,13 @@ define([ { "key": "ExportImageService", "implementation": ExportImageService, - "depends": [] + "depends": [ + "$q", + "$timeout", + "$log", + "EXPORT_IMAGE_TIMEOUT" + ] + } ], "constants": [ @@ -101,6 +107,11 @@ define([ "value": 900000, "priority": "fallback", "comment": "Fifteen minutes." + }, + { + "key": "EXPORT_IMAGE_TIMEOUT", + "value": 500, + "priority": "fallback" } ], "policies": [ diff --git a/platform/features/plot/src/PlotController.js b/platform/features/plot/src/PlotController.js index 074e17f9b6..97e848f66a 100644 --- a/platform/features/plot/src/PlotController.js +++ b/platform/features/plot/src/PlotController.js @@ -374,7 +374,7 @@ define( PlotController.prototype.exportPDF = function () { var self = this; self.hideExportButtons = true; - self.ExportImageService.exportPDF(self.$element[0], "plot.pdf", function () { + self.ExportImageService.exportPDF(self.$element[0], "plot.pdf").finally(function () { self.hideExportButtons = false; }); }; @@ -385,7 +385,7 @@ define( PlotController.prototype.exportPNG = function () { var self = this; self.hideExportButtons = true; - self.ExportImageService.exportPNG(self.$element[0], "plot.png", function () { + self.ExportImageService.exportPNG(self.$element[0], "plot.png").finally(function () { self.hideExportButtons = false; }); }; @@ -396,7 +396,7 @@ define( PlotController.prototype.exportJPG = function () { var self = this; self.hideExportButtons = true; - self.ExportImageService.exportJPG(self.$element[0], "plot.jpg", function () { + self.ExportImageService.exportJPG(self.$element[0], "plot.jpg").finally(function () { self.hideExportButtons = false; }); }; diff --git a/platform/features/plot/src/services/ExportImageService.js b/platform/features/plot/src/services/ExportImageService.js index 633635a2c6..611330c2d9 100644 --- a/platform/features/plot/src/services/ExportImageService.js +++ b/platform/features/plot/src/services/ExportImageService.js @@ -29,75 +29,88 @@ define( "jsPDF", "saveAs" ], - function (html2canvas, JsPdf, saveAs) { + function ( + html2canvas, + JsPdf, + saveAs + ) { + var self = this; /** * The export image service will export any HTML node to * PDF, JPG, or PNG. * @constructor */ - function ExportImageService() { + function ExportImageService($q, $timeout, $log, EXPORT_IMAGE_TIMEOUT) { + self.$q = $q; + self.$timeout = $timeout; + self.$log = $log; + self.EXPORT_IMAGE_TIMEOUT = EXPORT_IMAGE_TIMEOUT; } /** * Renders an HTML element into a base64 encoded image * as a BLOB, PNG, or JPG. * @param {node} element that will be converted to an image - * @param {function} callback for passing the resulting image * @param {string} type of image to convert the element to - * @returns {string} the color, in #RRGGBB form + * @returns {promise} */ - function renderElement(element, callback, type) { - type = type || "jpeg"; + function renderElement(element, type) { + var defer = self.$q.defer(), + renderTimeout; - html2canvas(element, { - onrendered: function (canvas) { - switch (type.toLowerCase()) { - case "blob": - canvas.toBlob(callback); - break; + renderTimeout = self.$timeout(function() { + defer.reject("html2canvas timed out"); + }, self.EXPORT_IMAGE_TIMEOUT); - case "png": - callback(canvas.toDataURL("image/png", 1.0)); - break; + try { + html2canvas(element, { + onrendered: function (canvas) { + switch (type.toLowerCase()) { + case "blob": + canvas.toBlob(defer.resolve); + break; - default: - case "jpg": - case "jpeg": - callback(canvas.toDataURL("image/jpeg", 1.0)); - break; + case "png": + defer.resolve(canvas.toDataURL("image/png", 1.0)); + break; + + default: + case "jpg": + case "jpeg": + defer.resolve(canvas.toDataURL("image/jpeg", 1.0)); + break; + } } - } - }); + }); + } catch(e) { + self.$log.warn("html2canvas failed with error: " + e); + defer.reject(e); + } + + defer.promise.finally(renderTimeout.cancel); + + return defer.promise; } - ExportImageService.prototype.exportPDF = function (element, filename, callback) { - callback = typeof callback === "function" ? callback : function () {}; - - renderElement(element, function (img) { + ExportImageService.prototype.exportPDF = function (element, filename) { + return renderElement(element, "jpeg").then(function (img) { var pdf = new JsPdf("l", "px", [element.offsetHeight, element.offsetWidth]); pdf.addImage(img, "JPEG", 0, 0, element.offsetWidth, element.offsetHeight); pdf.save(filename); - callback(); - }, "jpeg"); + }); }; - ExportImageService.prototype.exportJPG = function (element, filename, callback) { - callback = typeof callback === "function" ? callback : function () {}; - - renderElement(element, function (img) { + ExportImageService.prototype.exportJPG = function (element, filename) { + return renderElement(element, "blob").then(function (img) { saveAs(img, filename); - callback(); - }, "blob"); + }); }; - ExportImageService.prototype.exportPNG = function (element, filename, callback) { - callback = typeof callback === "function" ? callback : function () {}; - - renderElement(element, function (img) { + ExportImageService.prototype.exportPNG = function (element, filename) { + return renderElement(element, "blob").then(function (img) { saveAs(img, filename); - callback(); - }, "blob"); + }); }; return ExportImageService;