UNPKG

react-fabricjs

Version:
86 lines (72 loc) 1.1 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("react")); else if(typeof define === 'function' && define.amd) define(["react"], factory); else if(typeof exports === 'object') exports["react-fabricjs"] = factory(require("react")); else root["react-fabricjs"] = factory(root["React"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_2__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ((function(modules) { // Check all modules for deduplicated modules for(var i in modules) { if(Object.prototype.hasOwnProperty.call(modules, i)) { switch(typeof modules[i]) { case "function": break; case "object": // Module can be created from a template modules[i] = (function(_m) { var args = _m.slice(1), fn = modules[_m[0]]; return function (a,b,c) { fn.apply(this, [a,b,c].concat(args)); }; }(modules[i])); break; default: // Module is a copy of another module modules[i] = modules[modules[i]]; break; } } } return modules; }([ /* 0 */ /***/ function(module, exports, __webpack_require__) { eval("'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n\tvalue: true\n});\nexports.color = exports.imageFilter = exports.Itext = exports.Text = exports.Image = exports.Triangle = exports.Rect = exports.Polyline = exports.Polygon = exports.PathGroup = exports.Path = exports.Line = exports.Ellipse = exports.Circle = exports.Canvas = exports.StaticCanvas = undefined;\n\nvar _StaticCanvas2 = __webpack_require__(14);\n\nvar _StaticCanvas3 = _interopRequireDefault(_StaticCanvas2);\n\nvar _Canvas2 = __webpack_require__(25);\n\nvar _Canvas3 = _interopRequireDefault(_Canvas2);\n\nvar _Circle2 = __webpack_require__(31);\n\nvar _Circle3 = _interopRequireDefault(_Circle2);\n\nvar _Ellipse2 = __webpack_require__(32);\n\nvar _Ellipse3 = _interopRequireDefault(_Ellipse2);\n\nvar _Line2 = __webpack_require__(33);\n\nvar _Line3 = _interopRequireDefault(_Line2);\n\nvar _Path2 = __webpack_require__(17);\n\nvar _Path3 = _interopRequireDefault(_Path2);\n\nvar _PathGroup2 = __webpack_require__(34);\n\nvar _PathGroup3 = _interopRequireDefault(_PathGroup2);\n\nvar _Polygon2 = __webpack_require__(35);\n\nvar _Polygon3 = _interopRequireDefault(_Polygon2);\n\nvar _Polyline2 = __webpack_require__(36);\n\nvar _Polyline3 = _interopRequireDefault(_Polyline2);\n\nvar _Rect2 = __webpack_require__(37);\n\nvar _Rect3 = _interopRequireDefault(_Rect2);\n\nvar _Triangle2 = __webpack_require__(38);\n\nvar _Triangle3 = _interopRequireDefault(_Triangle2);\n\nvar _Image2 = __webpack_require__(28);\n\nvar _Image3 = _interopRequireDefault(_Image2);\n\nvar _Text2 = __webpack_require__(15);\n\nvar _Text3 = _interopRequireDefault(_Text2);\n\nvar _IText = __webpack_require__(27);\n\nvar _IText2 = _interopRequireDefault(_IText);\n\nvar _ImageFilters = __webpack_require__(29);\n\nvar _ImageFilters2 = _interopRequireDefault(_ImageFilters);\n\nvar _Color = __webpack_require__(26);\n\nvar _Color2 = _interopRequireDefault(_Color);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// Main Bundle\nexports.default = {\n\tStaticCanvas: _StaticCanvas3.default,\n\tCanvas: _Canvas3.default,\n\n\tCircle: _Circle3.default,\n\tEllipse: _Ellipse3.default,\n\tLine: _Line3.default,\n\tPath: _Path3.default,\n\tPathGroup: _PathGroup3.default,\n\tPolygon: _Polygon3.default,\n\tPolyline: _Polyline3.default,\n\tRect: _Rect3.default,\n\tTriangle: _Triangle3.default,\n\n\tImage: _Image3.default,\n\tText: _Text3.default,\n\tItext: _IText2.default,\n\n\timageFilter: _ImageFilters2.default,\n\tcolor: _Color2.default\n};\n\n// Canvas\n\nvar StaticCanvas = exports.StaticCanvas = _StaticCanvas3.default;\nvar Canvas = exports.Canvas = _Canvas3.default;\n\n// Shape\nvar Circle = exports.Circle = _Circle3.default;\nvar Ellipse = exports.Ellipse = _Ellipse3.default;\nvar Line = exports.Line = _Line3.default;\nvar Path = exports.Path = _Path3.default;\nvar PathGroup = exports.PathGroup = _PathGroup3.default;\nvar Polygon = exports.Polygon = _Polygon3.default;\nvar Polyline = exports.Polyline = _Polyline3.default;\nvar Rect = exports.Rect = _Rect3.default;\nvar Triangle = exports.Triangle = _Triangle3.default;\n\nvar Image = exports.Image = _Image3.default;\nvar Text = exports.Text = _Text3.default;\nvar Itext = exports.Itext = _IText2.default;\n\n// utils\nvar imageFilter = exports.imageFilter = _ImageFilters2.default;\nvar color = exports.color = _Color2.default;\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/react-fabric.js\n ** module id = 0\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./src/react-fabric.js?"); /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { eval("/* WEBPACK VAR INJECTION */(function(Buffer, process) {/* build: `node build.js modules=ALL exclude=json,gestures minifier=uglifyjs` */\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: \"1.6.0-rc.1\" };\nif (true) {\n exports.fabric = fabric;\n}\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n fabric.document = document;\n fabric.window = window;\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n window.fabric = fabric;\n}\nelse {\n // assume we're running under node.js when document/window are not present\n fabric.document = __webpack_require__(60)\n .jsdom(\"<!DOCTYPE html><html><head></head><body></body></html>\");\n\n if (fabric.document.createWindow) {\n fabric.window = fabric.document.createWindow();\n } else {\n fabric.window = fabric.document.parentWindow;\n }\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\nfabric.isTouchSupported = \"ontouchstart\" in fabric.document.documentElement;\n\n/**\n * True when in environment that's probably Node.js\n * @type boolean\n */\nfabric.isLikelyNode = typeof Buffer !== 'undefined' &&\n typeof window === 'undefined';\n\n/* _FROM_SVG_START_ */\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\nfabric.SHARED_ATTRIBUTES = [\n \"display\",\n \"transform\",\n \"fill\", \"fill-opacity\", \"fill-rule\",\n \"opacity\",\n \"stroke\", \"stroke-dasharray\", \"stroke-linecap\",\n \"stroke-linejoin\", \"stroke-miterlimit\",\n \"stroke-opacity\", \"stroke-width\",\n \"id\"\n];\n/* _FROM_SVG_END_ */\n\n/**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\nfabric.DPI = 96;\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:e[-+]?\\\\d+)?)';\n\n\n/**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\nfabric.devicePixelRatio = fabric.window.devicePixelRatio ||\n fabric.window.webkitDevicePixelRatio ||\n fabric.window.mozDevicePixelRatio ||\n 1;\n\n\n(function() {\n\n /**\n * @private\n * @param {String} eventName\n * @param {Function} handler\n */\n function _removeEventListener(eventName, handler) {\n if (!this.__eventListeners[eventName]) {\n return;\n }\n\n if (handler) {\n fabric.util.removeFromArray(this.__eventListeners[eventName], handler);\n }\n else {\n this.__eventListeners[eventName].length = 0;\n }\n }\n\n /**\n * Observes specified event\n * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)\n * @memberOf fabric.Observable\n * @alias on\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n * @return {Self} thisArg\n * @chainable\n */\n function observe(eventName, handler) {\n if (!this.__eventListeners) {\n this.__eventListeners = { };\n }\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n this.on(prop, eventName[prop]);\n }\n }\n else {\n if (!this.__eventListeners[eventName]) {\n this.__eventListeners[eventName] = [ ];\n }\n this.__eventListeners[eventName].push(handler);\n }\n return this;\n }\n\n /**\n * Stops event observing for a particular event handler. Calling this method\n * without arguments removes all handlers for all events\n * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)\n * @memberOf fabric.Observable\n * @alias off\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function to be deleted from EventListeners\n * @return {Self} thisArg\n * @chainable\n */\n function stopObserving(eventName, handler) {\n if (!this.__eventListeners) {\n return;\n }\n\n // remove all key/value pairs (event name -> event handler)\n if (arguments.length === 0) {\n this.__eventListeners = { };\n }\n // one object with key/value pairs was passed\n else if (arguments.length === 1 && typeof arguments[0] === 'object') {\n for (var prop in eventName) {\n _removeEventListener.call(this, prop, eventName[prop]);\n }\n }\n else {\n _removeEventListener.call(this, eventName, handler);\n }\n return this;\n }\n\n /**\n * Fires event with an optional options object\n * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)\n * @memberOf fabric.Observable\n * @alias trigger\n * @param {String} eventName Event name to fire\n * @param {Object} [options] Options object\n * @return {Self} thisArg\n * @chainable\n */\n function fire(eventName, options) {\n if (!this.__eventListeners) {\n return;\n }\n\n var listenersForEvent = this.__eventListeners[eventName];\n if (!listenersForEvent) {\n return;\n }\n\n for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n // avoiding try/catch for perf. reasons\n listenersForEvent[i].call(this, options || { });\n }\n return this;\n }\n\n /**\n * @namespace fabric.Observable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events}\n * @see {@link http://fabricjs.com/events/|Events demo}\n */\n fabric.Observable = {\n observe: observe,\n stopObserving: stopObserving,\n fire: fire,\n\n on: observe,\n off: stopObserving,\n trigger: fire\n };\n})();\n\n\n/**\n * @namespace fabric.Collection\n */\nfabric.Collection = {\n\n /**\n * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * Objects should be instances of (or inherit from) fabric.Object\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n */\n add: function () {\n this._objects.push.apply(this._objects, arguments);\n for (var i = 0, length = arguments.length; i < length; i++) {\n this._onObjectAdded(arguments[i]);\n }\n this.renderOnAddRemove && this.renderAll();\n return this;\n },\n\n /**\n * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\n * An object should be an instance of (or inherit from) fabric.Object\n * @param {Object} object Object to insert\n * @param {Number} index Index to insert object at\n * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\n * @return {Self} thisArg\n * @chainable\n */\n insertAt: function (object, index, nonSplicing) {\n var objects = this.getObjects();\n if (nonSplicing) {\n objects[index] = object;\n }\n else {\n objects.splice(index, 0, object);\n }\n this._onObjectAdded(object);\n this.renderOnAddRemove && this.renderAll();\n return this;\n },\n\n /**\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n * @chainable\n */\n remove: function() {\n var objects = this.getObjects(),\n index;\n\n for (var i = 0, length = arguments.length; i < length; i++) {\n index = objects.indexOf(arguments[i]);\n\n // only call onObjectRemoved if an object was actually removed\n if (index !== -1) {\n objects.splice(index, 1);\n this._onObjectRemoved(arguments[i]);\n }\n }\n\n this.renderOnAddRemove && this.renderAll();\n return this;\n },\n\n /**\n * Executes given function for each object in this group\n * @param {Function} callback\n * Callback invoked with current object as first argument,\n * index - as second and an array of all objects - as third.\n * Iteration happens in reverse order (for performance reasons).\n * Callback is invoked in a context of Global Object (e.g. `window`)\n * when no `context` argument is given\n *\n * @param {Object} context Context (aka thisObject)\n * @return {Self} thisArg\n */\n forEachObject: function(callback, context) {\n var objects = this.getObjects(),\n i = objects.length;\n while (i--) {\n callback.call(context, objects[i], i, objects);\n }\n return this;\n },\n\n /**\n * Returns an array of children objects of this instance\n * Type parameter introduced in 1.3.10\n * @param {String} [type] When specified, only objects of this type are returned\n * @return {Array}\n */\n getObjects: function(type) {\n if (typeof type === 'undefined') {\n return this._objects;\n }\n return this._objects.filter(function(o) {\n return o.type === type;\n });\n },\n\n /**\n * Returns object at specified index\n * @param {Number} index\n * @return {Self} thisArg\n */\n item: function (index) {\n return this.getObjects()[index];\n },\n\n /**\n * Returns true if collection contains no objects\n * @return {Boolean} true if collection is empty\n */\n isEmpty: function () {\n return this.getObjects().length === 0;\n },\n\n /**\n * Returns a size of a collection (i.e: length of an array containing its objects)\n * @return {Number} Collection size\n */\n size: function() {\n return this.getObjects().length;\n },\n\n /**\n * Returns true if collection contains an object\n * @param {Object} object Object to check against\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function(object) {\n return this.getObjects().indexOf(object) > -1;\n },\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity: function () {\n return this.getObjects().reduce(function (memo, current) {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\n};\n\n\n(function(global) {\n\n var sqrt = Math.sqrt,\n atan2 = Math.atan2,\n PiBy180 = Math.PI / 180;\n\n /**\n * @namespace fabric.util\n */\n fabric.util = {\n\n /**\n * Removes value from an array.\n * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n * @static\n * @memberOf fabric.util\n * @param {Array} array\n * @param {Any} value\n * @return {Array} original array\n */\n removeFromArray: function(array, value) {\n var idx = array.indexOf(value);\n if (idx !== -1) {\n array.splice(idx, 1);\n }\n return array;\n },\n\n /**\n * Returns random number between 2 specified ones.\n * @static\n * @memberOf fabric.util\n * @param {Number} min lower limit\n * @param {Number} max upper limit\n * @return {Number} random value (between min and max)\n */\n getRandomInt: function(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n },\n\n /**\n * Transforms degrees to radians.\n * @static\n * @memberOf fabric.util\n * @param {Number} degrees value in degrees\n * @return {Number} value in radians\n */\n degreesToRadians: function(degrees) {\n return degrees * PiBy180;\n },\n\n /**\n * Transforms radians to degrees.\n * @static\n * @memberOf fabric.util\n * @param {Number} radians value in radians\n * @return {Number} value in degrees\n */\n radiansToDegrees: function(radians) {\n return radians / PiBy180;\n },\n\n /**\n * Rotates `point` around `origin` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} point The point to rotate\n * @param {fabric.Point} origin The origin of the rotation\n * @param {Number} radians The radians of the angle for the rotation\n * @return {fabric.Point} The new rotated point\n */\n rotatePoint: function(point, origin, radians) {\n point.subtractEquals(origin);\n var sin = Math.sin(radians),\n cos = Math.cos(radians),\n rx = point.x * cos - point.y * sin,\n ry = point.x * sin + point.y * cos;\n return new fabric.Point(rx, ry).addEquals(origin);\n },\n\n /**\n * Apply transform t to point p\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {fabric.Point} The transformed point\n */\n transformPoint: function(p, t, ignoreOffset) {\n if (ignoreOffset) {\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y,\n t[1] * p.x + t[3] * p.y\n );\n }\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y + t[4],\n t[1] * p.x + t[3] * p.y + t[5]\n );\n },\n\n /**\n * Invert transformation t\n * @static\n * @memberOf fabric.util\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\n invertTransform: function(t) {\n var a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\n o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);\n r[4] = -o.x;\n r[5] = -o.y;\n return r;\n },\n\n /**\n * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n * @static\n * @memberOf fabric.util\n * @param {Number|String} number number to operate on\n * @param {Number} fractionDigits number of fraction digits to \"leave\"\n * @return {Number}\n */\n toFixed: function(number, fractionDigits) {\n return parseFloat(Number(number).toFixed(fractionDigits));\n },\n\n /**\n * Converts from attribute value to pixel value if applicable.\n * Returns converted pixels or original value not converted.\n * @param {Number|String} value number to operate on\n * @return {Number|String}\n */\n parseUnit: function(value, fontSize) {\n var unit = /\\D{0,2}$/.exec(value),\n number = parseFloat(value);\n if (!fontSize) {\n fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n }\n switch (unit[0]) {\n case 'mm':\n return number * fabric.DPI / 25.4;\n\n case 'cm':\n return number * fabric.DPI / 2.54;\n\n case 'in':\n return number * fabric.DPI;\n\n case 'pt':\n return number * fabric.DPI / 72; // or * 4 / 3\n\n case 'pc':\n return number * fabric.DPI / 72 * 12; // or * 16\n\n case 'em':\n return number * fontSize;\n\n default:\n return number;\n }\n },\n\n /**\n * Function which always returns `false`.\n * @static\n * @memberOf fabric.util\n * @return {Boolean}\n */\n falseFunction: function() {\n return false;\n },\n\n /**\n * Returns klass \"Class\" object of given namespace\n * @memberOf fabric.util\n * @param {String} type Type of object (eg. 'circle')\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @return {Object} klass \"Class\"\n */\n getKlass: function(type, namespace) {\n // capitalize first letter only\n type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\n return fabric.util.resolveNamespace(namespace)[type];\n },\n\n /**\n * Returns object of given namespace\n * @memberOf fabric.util\n * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n * @return {Object} Object for given namespace (default fabric)\n */\n resolveNamespace: function(namespace) {\n if (!namespace) {\n return fabric;\n }\n\n var parts = namespace.split('.'),\n len = parts.length,\n obj = global || fabric.window;\n\n for (var i = 0; i < len; ++i) {\n obj = obj[parts[i]];\n }\n\n return obj;\n },\n\n /**\n * Loads image element from given url and passes it to a callback\n * @memberOf fabric.util\n * @param {String} url URL representing an image\n * @param {Function} callback Callback; invoked with loaded image\n * @param {Any} [context] Context to invoke callback in\n * @param {Object} [crossOrigin] crossOrigin value to set image element to\n */\n loadImage: function(url, callback, context, crossOrigin) {\n if (!url) {\n callback && callback.call(context, url);\n return;\n }\n\n var img = fabric.util.createImage();\n\n /** @ignore */\n img.onload = function () {\n callback && callback.call(context, img);\n img = img.onload = img.onerror = null;\n };\n\n /** @ignore */\n img.onerror = function() {\n fabric.log('Error loading ' + img.src);\n callback && callback.call(context, null, true);\n img = img.onload = img.onerror = null;\n };\n\n // data-urls appear to be buggy with crossOrigin\n // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\n // see https://code.google.com/p/chromium/issues/detail?id=315152\n // https://bugzilla.mozilla.org/show_bug.cgi?id=935069\n if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') {\n img.crossOrigin = crossOrigin;\n }\n\n img.src = url;\n },\n\n /**\n * Creates corresponding fabric instances from their object representations\n * @static\n * @memberOf fabric.util\n * @param {Array} objects Objects to enliven\n * @param {Function} callback Callback to invoke when all objects are created\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @param {Function} reviver Method for further parsing of object elements,\n * called after each fabric object created.\n */\n enlivenObjects: function(objects, callback, namespace, reviver) {\n objects = objects || [ ];\n\n function onLoaded() {\n if (++numLoadedObjects === numTotalObjects) {\n callback && callback(enlivenedObjects);\n }\n }\n\n var enlivenedObjects = [ ],\n numLoadedObjects = 0,\n numTotalObjects = objects.length;\n\n if (!numTotalObjects) {\n callback && callback(enlivenedObjects);\n return;\n }\n\n objects.forEach(function (o, index) {\n // if sparse array\n if (!o || !o.type) {\n onLoaded();\n return;\n }\n var klass = fabric.util.getKlass(o.type, namespace);\n if (klass.async) {\n klass.fromObject(o, function (obj, error) {\n if (!error) {\n enlivenedObjects[index] = obj;\n reviver && reviver(o, enlivenedObjects[index]);\n }\n onLoaded();\n });\n }\n else {\n enlivenedObjects[index] = klass.fromObject(o);\n reviver && reviver(o, enlivenedObjects[index]);\n onLoaded();\n }\n });\n },\n\n /**\n * Groups SVG elements (usually those retrieved from SVG document)\n * @static\n * @memberOf fabric.util\n * @param {Array} elements SVG elements to group\n * @param {Object} [options] Options object\n * @return {fabric.Object|fabric.PathGroup}\n */\n groupSVGElements: function(elements, options, path) {\n var object;\n\n object = new fabric.PathGroup(elements, options);\n\n if (typeof path !== 'undefined') {\n object.setSourcePath(path);\n }\n return object;\n },\n\n /**\n * Populates an object with properties of another object\n * @static\n * @memberOf fabric.util\n * @param {Object} source Source object\n * @param {Object} destination Destination object\n * @return {Array} properties Propertie names to include\n */\n populateWithProperties: function(source, destination, properties) {\n if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\n for (var i = 0, len = properties.length; i < len; i++) {\n if (properties[i] in source) {\n destination[properties[i]] = source[properties[i]];\n }\n }\n }\n },\n\n /**\n * Draws a dashed line between two points\n *\n * This method is used to draw dashed line around selection area.\n * See <a href=\"http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas\">dotted stroke in canvas</a>\n *\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x start x coordinate\n * @param {Number} y start y coordinate\n * @param {Number} x2 end x coordinate\n * @param {Number} y2 end y coordinate\n * @param {Array} da dash array pattern\n */\n drawDashedLine: function(ctx, x, y, x2, y2, da) {\n var dx = x2 - x,\n dy = y2 - y,\n len = sqrt(dx * dx + dy * dy),\n rot = atan2(dy, dx),\n dc = da.length,\n di = 0,\n draw = true;\n\n ctx.save();\n ctx.translate(x, y);\n ctx.moveTo(0, 0);\n ctx.rotate(rot);\n\n x = 0;\n while (len > x) {\n x += da[di++ % dc];\n if (x > len) {\n x = len;\n }\n ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n draw = !draw;\n }\n\n ctx.restore();\n },\n\n /**\n * Creates canvas element and initializes it via excanvas if necessary\n * @static\n * @memberOf fabric.util\n * @param {CanvasElement} [canvasEl] optional canvas element to initialize;\n * when not given, element is created implicitly\n * @return {CanvasElement} initialized canvas element\n */\n createCanvasElement: function(canvasEl) {\n canvasEl || (canvasEl = fabric.document.createElement('canvas'));\n //jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {\n G_vmlCanvasManager.initElement(canvasEl);\n }\n //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n return canvasEl;\n },\n\n /**\n * Creates image element (works on client and node)\n * @static\n * @memberOf fabric.util\n * @return {HTMLImageElement} HTML image element\n */\n createImage: function() {\n return fabric.isLikelyNode\n ? new (__webpack_require__(13).Image)()\n : fabric.document.createElement('img');\n },\n\n /**\n * Creates accessors (getXXX, setXXX) for a \"class\", based on \"stateProperties\" array\n * @static\n * @memberOf fabric.util\n * @param {Object} klass \"Class\" to create accessors for\n */\n createAccessors: function(klass) {\n var proto = klass.prototype;\n\n for (var i = proto.stateProperties.length; i--; ) {\n\n var propName = proto.stateProperties[i],\n capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1),\n setterName = 'set' + capitalizedPropName,\n getterName = 'get' + capitalizedPropName;\n\n // using `new Function` for better introspection\n if (!proto[getterName]) {\n proto[getterName] = (function(property) {\n return new Function('return this.get(\"' + property + '\")');\n })(propName);\n }\n if (!proto[setterName]) {\n proto[setterName] = (function(property) {\n return new Function('value', 'return this.set(\"' + property + '\", value)');\n })(propName);\n }\n }\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} receiver Object implementing `clipTo` method\n * @param {CanvasRenderingContext2D} ctx Context to clip\n */\n clipContext: function(receiver, ctx) {\n ctx.save();\n ctx.beginPath();\n receiver.clipTo(ctx);\n ctx.clip();\n },\n\n /**\n * Multiply matrix A by matrix B to nest transformations\n * @static\n * @memberOf fabric.util\n * @param {Array} a First transformMatrix\n * @param {Array} b Second transformMatrix\n * @return {Array} The product of the two transform matrices\n */\n multiplyTransformMatrices: function(a, b) {\n // Matrix multiply a * b\n return [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n a[0] * b[4] + a[2] * b[5] + a[4],\n a[1] * b[4] + a[3] * b[5] + a[5]\n ];\n },\n\n /**\n * Returns string representation of function body\n * @param {Function} fn Function to get body of\n * @return {String} Function body\n */\n getFunctionBody: function(fn) {\n return (String(fn).match(/function[^{]*\\{([\\s\\S]*)\\}/) || {})[1];\n },\n\n /**\n * Returns true if context has transparent pixel\n * at specified location (taking tolerance into account)\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x x coordinate\n * @param {Number} y y coordinate\n * @param {Number} tolerance Tolerance\n */\n isTransparent: function(ctx, x, y, tolerance) {\n\n // If tolerance is > 0 adjust start coords to take into account.\n // If moves off Canvas fix to 0\n if (tolerance > 0) {\n if (x > tolerance) {\n x -= tolerance;\n }\n else {\n x = 0;\n }\n if (y > tolerance) {\n y -= tolerance;\n }\n else {\n y = 0;\n }\n }\n\n var _isTransparent = true,\n imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1);\n\n // Split image data - for tolerance > 1, pixelDataSize = 4;\n for (var i = 3, l = imageData.data.length; i < l; i += 4) {\n var temp = imageData.data[i];\n _isTransparent = temp <= 0;\n if (_isTransparent === false) {\n break; // Stop if colour found\n }\n }\n\n imageData = null;\n\n return _isTransparent;\n }\n };\n\n})( true ? exports : this);\n\n\n(function() {\n\n var arcToSegmentsCache = { },\n segmentToBezierCache = { },\n boundsOfCurveCache = { },\n _join = Array.prototype.join;\n\n /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\n * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\n * http://mozilla.org/MPL/2.0/\n */\n function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\n var argsString = _join.call(arguments);\n if (arcToSegmentsCache[argsString]) {\n return arcToSegmentsCache[argsString];\n }\n\n var PI = Math.PI, th = rotateX * PI / 180,\n sinTh = Math.sin(th),\n cosTh = Math.cos(th),\n fromX = 0, fromY = 0;\n\n rx = Math.abs(rx);\n ry = Math.abs(ry);\n\n var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\n py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\n rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,\n pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\n root = 0;\n\n if (pl < 0) {\n var s = Math.sqrt(1 - pl/(rx2 * ry2));\n rx *= s;\n ry *= s;\n }\n else {\n root = (large === sweep ? -1.0 : 1.0) *\n Math.sqrt( pl /(rx2 * py2 + ry2 * px2));\n }\n\n var cx = root * rx * py / ry,\n cy = -root * ry * px / rx,\n cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\n cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\n mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\n dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\n\n if (sweep === 0 && dtheta > 0) {\n dtheta -= 2 * PI;\n }\n else if (sweep === 1 && dtheta < 0) {\n dtheta += 2 * PI;\n }\n\n // Convert into cubic bezier segments <= 90deg\n var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\n result = [], mDelta = dtheta / segments,\n mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\n th3 = mTheta + mDelta;\n\n for (var i = 0; i < segments; i++) {\n result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\n fromX = result[i][4];\n fromY = result[i][5];\n mTheta = th3;\n th3 += mDelta;\n }\n arcToSegmentsCache[argsString] = result;\n return result;\n }\n\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n var argsString2 = _join.call(arguments);\n if (segmentToBezierCache[argsString2]) {\n return segmentToBezierCache[argsString2];\n }\n\n var costh2 = Math.cos(th2),\n sinth2 = Math.sin(th2),\n costh3 = Math.cos(th3),\n sinth3 = Math.sin(th3),\n toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\n toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\n cp1X = fromX + mT * ( - cosTh * rx * sinth2 - sinTh * ry * costh2),\n cp1Y = fromY + mT * ( - sinTh * rx * sinth2 + cosTh * ry * costh2),\n cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),\n cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);\n\n segmentToBezierCache[argsString2] = [\n cp1X, cp1Y,\n cp2X, cp2Y,\n toX, toY\n ];\n return segmentToBezierCache[argsString2];\n }\n\n /*\n * Private\n */\n function calcVectorAngle(ux, uy, vx, vy) {\n var ta = Math.atan2(uy, ux),\n tb = Math.atan2(vy, vx);\n if (tb >= ta) {\n return tb - ta;\n }\n else {\n return 2 * Math.PI - (ta - tb);\n }\n }\n\n /**\n * Draws arc\n * @param {CanvasRenderingContext2D} ctx\n * @param {Number} fx\n * @param {Number} fy\n * @param {Array} coords\n */\n fabric.util.drawArc = function(ctx, fx, fy, coords) {\n var rx = coords[0],\n ry = coords[1],\n rot = coords[2],\n large = coords[3],\n sweep = coords[4],\n tx = coords[5],\n ty = coords[6],\n segs = [[ ], [ ], [ ], [ ]],\n segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (var i = 0, len = segsNorm.length; i < len; i++) {\n segs[i][0] = segsNorm[i][0] + fx;\n segs[i][1] = segsNorm[i][1] + fy;\n segs[i][2] = segsNorm[i][2] + fx;\n segs[i][3] = segsNorm[i][3] + fy;\n segs[i][4] = segsNorm[i][4] + fx;\n segs[i][5] = segsNorm[i][5] + fy;\n ctx.bezierCurveTo.apply(ctx, segs[i]);\n }\n };\n\n /**\n * Calculate bounding box of a elliptic-arc\n * @param {Number} fx start point of arc\n * @param {Number} fy\n * @param {Number} rx horizontal radius\n * @param {Number} ry vertical radius\n * @param {Number} rot angle of horizontal axe\n * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n * @param {Number} tx end point of arc\n * @param {Number} ty\n */\n fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n\n var fromX = 0, fromY = 0, bound = [ ], bounds = [ ],\n segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot),\n boundCopy = [[ ], [ ]];\n\n for (var i = 0, len = segs.length; i < len; i++) {\n bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]);\n boundCopy[0].x = bound[0].x + fx;\n boundCopy[0].y = bound[0].y + fy;\n boundCopy[1].x = bound[1].x + fx;\n boundCopy[1].y = bound[1].y + fy;\n bounds.push(boundCopy[0]);\n bounds.push(boundCopy[1]);\n fromX = segs[i][4];\n fromY = segs[i][5];\n }\n return bounds;\n };\n\n /**\n * Calculate bounding box of a beziercurve\n * @param {Number} x0 starting point\n * @param {Number} y0\n * @param {Number} x1 first control point\n * @param {Number} y1\n * @param {Number} x2 secondo control point\n * @param {Number} y2\n * @param {Number} x3 end of beizer\n * @param {Number} y3\n */\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n var argsString = _join.call(arguments);\n if (boundsOfCurveCache[argsString]) {\n return boundsOfCurveCache[argsString];\n }\n\n var sqrt = Math.sqrt,\n min = Math.min, max = Math.max,\n abs = Math.abs, tvalues = [ ],\n bounds = [[ ], [ ]],\n a, b, c, t, t1, t2, b2ac, sqrtb2ac;\n\n b = 6 * x0 - 12 * x1 + 6 * x2;\n a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n c = 3 * x1 - 3 * x0;\n\n for (var i = 0; i < 2; ++i) {\n if (i > 0) {\n b = 6 * y0 - 12 * y1 + 6 * y2;\n a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n c = 3 * y1 - 3 * y0;\n }\n\n if (abs(a) < 1e-12) {\n if (abs(b) < 1e-12) {\n continue;\n }\n t = -c / b;\n if (0 < t && t < 1) {\n tvalues.push(t);\n }\n continue;\n }\n b2ac = b * b - 4 * c * a;\n if (b2ac < 0) {\n continue;\n }\n sqrtb2ac = sqrt(b2ac);\n t1 = (-b + sqrtb2ac) / (2 * a);\n if (0 < t1 && t1 < 1) {\n tvalues.push(t1);\n }\n t2 = (-b - sqrtb2ac) / (2 * a);\n if (0 < t2 && t2 < 1) {\n tvalues.push(t2);\n }\n }\n\n var x, y, j = tvalues.length, jlen = j, mt;\n while (j--) {\n t = tvalues[j];\n mt = 1 - t;\n x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\n bounds[0][j] = x;\n\n y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\n bounds[1][j] = y;\n }\n\n bounds[0][jlen] = x0;\n bounds[1][jlen] = y0;\n bounds[0][jlen + 1] = x3;\n bounds[1][jlen + 1] = y3;\n var result = [\n {\n x: min.apply(null, bounds[0]),\n y: min.apply(null, bounds[1])\n },\n {\n x: max.apply(null, bounds[0]),\n y: max.apply(null, bounds[1])\n }\n ];\n boundsOfCurveCache[argsString] = result;\n return result;\n }\n\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice;\n\n /* _ES5_COMPAT_START_ */\n\n if (!Array.prototype.indexOf) {\n /**\n * Finds index of an element in an array\n * @param {Any} searchElement\n * @param {Number} [fromIndex]\n * @return {Number}\n */\n Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\n if (this === void 0 || this === null) {\n throw new TypeError();\n }\n var t = Object(this), len = t.length >>> 0;\n if (len === 0) {\n return -1;\n }\n var n = 0;\n if (arguments.length > 0) {\n n = Number(arguments[1]);\n if (n !== n) { // shortcut for verifying if it's NaN\n n = 0;\n }\n else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n }\n if (n >= len) {\n return -1;\n }\n var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n for (; k < len; k++) {\n if (k in t && t[k] === searchElement) {\n return k;\n }\n }\n return -1;\n };\n }\n\n if (!Array.prototype.forEach) {\n /**\n * Iterates an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.forEach = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n fn.call(context, this[i], i, this);\n }\n }\n };\n }\n\n if (!Array.prototype.map) {\n /**\n * Returns a result of iterating over an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.map = function(fn, context) {\n var result = [ ];\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n result[i] = fn.call(context, this[i], i, this);\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.every) {\n /**\n * Returns true if a callback returns truthy value for all elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.every = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && !fn.call(context, this[i], i, this)) {\n return false;\n }\n }\n return true;\n };\n }\n\n if (!Array.prototype.some) {\n /**\n * Returns true if a callback returns truthy value for at least one element in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.some = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && fn.call(context, this[i], i, this)) {\n return true;\n }\n }\n return false;\n };\n }\n\n if (!Array.prototype.filter) {\n /**\n * Returns the result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.filter = function(fn, context) {\n var result = [ ], val;\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n val = this[i]; // in case fn mutates this\n if (fn.call(context, val, i, this)) {\n result.push(val);\n }\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.reduce) {\n /**\n * Returns \"folded\" (reduced) result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [initial] Object to use as the first argument to the first call of the callback\n * @return {Any}\n */\n Array.prototype.reduce = function(fn /*, initial*/) {\n var len = this.length >>> 0,\n i = 0,\n rv;\n\n if (arguments.length > 1) {\n rv = arguments[1];\n }\n else {\n do {\n if (i in this) {\n rv = this[i++];\n break;\n }\n // if array contains no values, no initial value to return\n if (++i >= len) {\n throw new TypeError();\n }\n }\n while (true);\n }\n for (; i < len; i++) {\n if (i in this) {\n rv = fn.call(null, rv, this[i], i, this);\n }\n }\n return rv;\n };\n }\n\n /* _ES5_COMPAT_END_ */\n\n /**\n * Invokes method on all items in a given array\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} method Name of a method to invoke\n * @return {Array}\n */\n function invoke(array, method) {\n var args = slice.call(arguments, 2), result = [ ];\n for (var i = 0, len = array.length; i < len; i++) {\n result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\n }\n return result;\n }\n\n /**\n * Finds maximum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {Any}\n */\n function max(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 >= value2;\n });\n }\n\n /**\n * Finds minimum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {Any}\n */\n function min(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 < value2;\n });\n }\n\n /**\n * @private\n */\n function find(array, byProperty, condition) {\n if (!array || array.length === 0) {\n return;\n }\n\n var i = array.length - 1,\n result = byProperty ? array[i][byProperty] : array[i];\n if (byProperty) {\n while (i--) {\n if (condition(array[i][byProperty], result)) {\n result = array[i][byProperty];\n }\n }\n }\n else {\n while (i--) {\n if (condition(array[i], result)) {\n result = array[i];\n }\n }\n }\n return result;\n }\n\n /**\n * @namespace fabric.util.array\n */\n fabric.util.array = {\n invoke: invoke,\n min: min,\n max: max\n };\n\n})();\n\n\n(function() {\n\n /**\n * Copies all enumerable properties of one object to another\n * @memberOf fabric.util.object\n * @param {Object} destination Where to copy to\n * @param {Object} source Where to copy from\n * @return {Object}\n */\n function extend(destination, source) {\n // JScript DontEnum bug is not taken care of\n for (var property in source) {\n destination[property] = source[property];\n }\n return destination;\n }\n\n /**\n * Creates an empty object and copies all enumerable properties of another object to it\n * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @return {Object}\n */\n function clone(object) {\n return extend({ }, object);\n }\n\n /** @namespace fabric.util.object */\n fabric.util.object = {\n extend: extend,\n clone: clone\n };\n\n})();\n\n\n(function() {\n\n /* _ES5_COMPAT_START_ */\n if (!String.prototype.trim) {\n /**\n * Trims a string (removing whitespace from the beginning and the end)\n * @function external:String#trim\n * @see <a href=\"https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim\">String#trim on MDN</a>\n */\n String.prototype.trim = function () {\n // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now\n return this.replace(/^[\\s\\xA0]+/, '').replace(/[\\s\\xA0]+$/, '');\n };\n }\n /* _ES5_COMPAT_END_ */\n\n /**\n * Camelizes a string\n * @memberOf fabric.util.string\n * @param {String} string String to camelize\n * @return {String} Camelized version of a string\n */\n function camelize(string) {\n return string.replace(/-+(.)?/g, function(match, character) {\n return character ? character.toUpperCase() : '';\n });\n