From d777d8d2a30575510b5039ae74c805f2eda30a4d Mon Sep 17 00:00:00 2001 From: Johan Lindell Date: Sat, 6 Aug 2016 12:03:35 +0200 Subject: [PATCH] Added better error handling which fixed #91 --- src/JsBarcode.js | 39 +++++++++++++++++---------------- src/exceptions/ErrorHandler.js | 39 +++++++++++++++++++++++++++++++++ src/exceptions/exceptions.js | 29 ++++++++++++++++++++++++ src/help/getRenderProperties.js | 6 +++-- 4 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 src/exceptions/ErrorHandler.js create mode 100644 src/exceptions/exceptions.js diff --git a/src/JsBarcode.js b/src/JsBarcode.js index 9d325534..1a957262 100644 --- a/src/JsBarcode.js +++ b/src/JsBarcode.js @@ -7,6 +7,10 @@ import linearizeEncodings from './help/linearizeEncodings.js'; import fixOptions from './help/fixOptions.js'; import getRenderProperties from './help/getRenderProperties.js'; +// Exceptions +import ErrorHandler from './exceptions/ErrorHandler.js'; +import {InvalidInputException} from './exceptions/exceptions.js'; + // Default values import defaults from './defaults/defaults.js'; @@ -27,6 +31,7 @@ let JsBarcode = function(element, text, options){ api._renderProperties = getRenderProperties(element); api._encodings = []; api._options = defaults; + api._errorHandler = new ErrorHandler(api); // If text is set, use the simple syntax (render the barcode directly) if(typeof text !== "undefined"){ @@ -36,9 +41,7 @@ let JsBarcode = function(element, text, options){ options.format = autoSelectBarcode(); } - api.options(options); - api[options.format](text, options); - api.render(); + api.options(options)[options.format](text, options).render(); } return api; @@ -59,14 +62,17 @@ function registerBarcode(barcodes, name){ API.prototype[name] = API.prototype[name.toUpperCase()] = API.prototype[name.toLowerCase()] = - function(text, options){ - var newOptions = merge(this._options, options); - var Encoder = barcodes[name]; - var encoded = encode(text, Encoder, newOptions); - this._encodings.push(encoded); - - return this; - }; + function(text, options){ + var api = this; + return api._errorHandler.wrapBarcodeCall(function(){ + var newOptions = merge(api._options, options); + var Encoder = barcodes[name]; + var encoded = encode(text, Encoder, newOptions); + api._encodings.push(encoded); + + return api; + }); + }; } // encode() handles the Encoder call and builds the binary string to be rendered @@ -79,12 +85,7 @@ function encode(text, Encoder, options){ // If the input is not valid for the encoder, throw error. // If the valid callback option is set, call it instead of throwing error if(!encoder.valid()){ - if(options.valid === defaults.valid){ - throw new Error('"' + text + '" is not a valid input.'); - } - else{ - options.valid(false); - } + throw new InvalidInputException(encoder.constructor.name, text); } // Make a request for the binary data (and other infromation) that should be rendered @@ -164,11 +165,11 @@ API.prototype.render = function(){ render(this._renderProperties, this._encodings, this._options); } - this._options.valid(true); - return this; }; +API.prototype._defaults = defaults; + // Prepares the encodings and calls the renderer function render(renderProperties, encodings, options){ encodings = linearizeEncodings(encodings); diff --git a/src/exceptions/ErrorHandler.js b/src/exceptions/ErrorHandler.js new file mode 100644 index 00000000..1a684faf --- /dev/null +++ b/src/exceptions/ErrorHandler.js @@ -0,0 +1,39 @@ +/*eslint no-console: 0 */ + +class ErrorHandler{ + constructor(api){ + this.api = api; + } + + handleCatch(e){ + // If babel supported extending of Error in a correct way instanceof would be used here + if(e.name === "InvalidInputException"){ + if(this.api._options.valid !== this.api._defaults.valid){ + this.api._options.valid(false); + } + else{ + throw e.message; + } + } + else{ + throw e; + } + + this.api.render = function(){}; + } + + wrapBarcodeCall(func){ + try{ + var result = func(...arguments); + this.api._options.valid(true); + return result; + } + catch(e){ + this.handleCatch(e); + + return this.api; + } + } +} + +export default ErrorHandler; diff --git a/src/exceptions/exceptions.js b/src/exceptions/exceptions.js new file mode 100644 index 00000000..4835435b --- /dev/null +++ b/src/exceptions/exceptions.js @@ -0,0 +1,29 @@ +class InvalidInputException extends Error{ + constructor(symbology, input) { + super(); + this.name = "InvalidInputException"; + + this.symbology = symbology; + this.input = input; + + this.message = '"' + this.input + '" is not a valid input for ' + this.symbology; + } +} + +class InvalidElementException extends Error{ + constructor() { + super(); + this.name = "InvalidElementException"; + this.message = "Not supported type to render on"; + } +} + +class NoElementException extends Error{ + constructor() { + super(); + this.name = "NoElementException"; + this.message = "No element to render on."; + } +} + +export {InvalidInputException, InvalidElementException, NoElementException}; diff --git a/src/help/getRenderProperties.js b/src/help/getRenderProperties.js index 1a386b89..d18d971d 100644 --- a/src/help/getRenderProperties.js +++ b/src/help/getRenderProperties.js @@ -5,6 +5,8 @@ import getOptionsFromElement from "./getOptionsFromElement.js"; import {getRendererClass} from "../renderers"; +import {InvalidElementException, NoElementException} from "../exceptions/exceptions.js"; + // Takes an element and returns an object with information about how // it should be rendered // This could also return an array with these objects @@ -57,7 +59,7 @@ function getRenderProperties(element){ }; } else{ - throw new Error("Not supported type to render on."); + throw new InvalidElementException(); } } @@ -65,7 +67,7 @@ function getRenderProperties(element){ function querySelectedRenderProperties(string){ var selector = document.querySelectorAll(string); if(selector.length === 0){ - throw new Error("No element found"); + throw new NoElementException(); } else{ let returnArray = [];