/*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
(self["webpackChunkkd_login"] = self["webpackChunkkd_login"] || []).push([[794],{

/***/ "../../node_modules/siriwave/dist/siriwave.umd.js":
/*!********************************************************!*\
  !*** ../../node_modules/siriwave/dist/siriwave.umd.js ***!
  \********************************************************/
/***/ (function(module) {

eval("(function (global, factory) {\n   true ? module.exports = factory() :\n  0;\n}(this, (function () { 'use strict';\n\n  function _classCallCheck(instance, Constructor) {\n    if (!(instance instanceof Constructor)) {\n      throw new TypeError(\"Cannot call a class as a function\");\n    }\n  }\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _unsupportedIterableToArray(o, minLen) {\n    if (!o) return;\n    if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);\n    var n = Object.prototype.toString.call(o).slice(8, -1);\n    if (n === \"Object\" && o.constructor) n = o.constructor.name;\n    if (n === \"Map\" || n === \"Set\") return Array.from(o);\n    if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);\n  }\n\n  function _arrayLikeToArray(arr, len) {\n    if (len == null || len > arr.length) len = arr.length;\n\n    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];\n\n    return arr2;\n  }\n\n  function _createForOfIteratorHelper(o) {\n    if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) {\n      if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) {\n        var i = 0;\n\n        var F = function () {};\n\n        return {\n          s: F,\n          n: function () {\n            if (i >= o.length) return {\n              done: true\n            };\n            return {\n              done: false,\n              value: o[i++]\n            };\n          },\n          e: function (e) {\n            throw e;\n          },\n          f: F\n        };\n      }\n\n      throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n    }\n\n    var it,\n        normalCompletion = true,\n        didErr = false,\n        err;\n    return {\n      s: function () {\n        it = o[Symbol.iterator]();\n      },\n      n: function () {\n        var step = it.next();\n        normalCompletion = step.done;\n        return step;\n      },\n      e: function (e) {\n        didErr = true;\n        err = e;\n      },\n      f: function () {\n        try {\n          if (!normalCompletion && it.return != null) it.return();\n        } finally {\n          if (didErr) throw err;\n        }\n      }\n    };\n  }\n\n  function lerp(v0, v1, t) {\n      return v0*(1-t)+v1*t\n  }\n  var lerp_1 = lerp;\n\n  var Curve = /*#__PURE__*/function () {\n    function Curve(opt) {\n      _classCallCheck(this, Curve);\n\n      this.ctrl = opt.ctrl;\n      this.definition = opt.definition;\n      this.ATT_FACTOR = 4;\n      this.GRAPH_X = 2;\n      this.AMPLITUDE_FACTOR = 0.6;\n    }\n\n    _createClass(Curve, [{\n      key: \"globalAttFn\",\n      value: function globalAttFn(x) {\n        return Math.pow(this.ATT_FACTOR / (this.ATT_FACTOR + Math.pow(x, this.ATT_FACTOR)), this.ATT_FACTOR);\n      }\n    }, {\n      key: \"_xpos\",\n      value: function _xpos(i) {\n        return this.ctrl.width * ((i + this.GRAPH_X) / (this.GRAPH_X * 2));\n      }\n    }, {\n      key: \"_ypos\",\n      value: function _ypos(i) {\n        return this.AMPLITUDE_FACTOR * (this.globalAttFn(i) * (this.ctrl.heightMax * this.ctrl.amplitude) * (1 / this.definition.attenuation) * Math.sin(this.ctrl.opt.frequency * i - this.ctrl.phase));\n      }\n    }, {\n      key: \"draw\",\n      value: function draw() {\n        var ctx = this.ctrl.ctx;\n        ctx.moveTo(0, 0);\n        ctx.beginPath();\n        var color = this.ctrl.color.replace(/rgb\\(/g, \"\").replace(/\\)/g, \"\");\n        ctx.strokeStyle = \"rgba(\".concat(color, \",\").concat(this.definition.opacity, \")\");\n        ctx.lineWidth = this.definition.lineWidth; // Cycle the graph from -X to +X every PX_DEPTH and draw the line\n\n        for (var i = -this.GRAPH_X; i <= this.GRAPH_X; i += this.ctrl.opt.pixelDepth) {\n          ctx.lineTo(this._xpos(i), this.ctrl.heightMax + this._ypos(i));\n        }\n\n        ctx.stroke();\n      }\n    }], [{\n      key: \"getDefinition\",\n      value: function getDefinition() {\n        return [{\n          attenuation: -2,\n          lineWidth: 1,\n          opacity: 0.1\n        }, {\n          attenuation: -6,\n          lineWidth: 1,\n          opacity: 0.2\n        }, {\n          attenuation: 4,\n          lineWidth: 1,\n          opacity: 0.4\n        }, {\n          attenuation: 2,\n          lineWidth: 1,\n          opacity: 0.6\n        }, {\n          attenuation: 1,\n          lineWidth: 1.5,\n          opacity: 1\n        }];\n      }\n    }]);\n\n    return Curve;\n  }();\n\n  var iOS9Curve = /*#__PURE__*/function () {\n    function iOS9Curve() {\n      var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n      _classCallCheck(this, iOS9Curve);\n\n      this.ctrl = opt.ctrl;\n      this.definition = opt.definition;\n      this.GRAPH_X = 25;\n      this.AMPLITUDE_FACTOR = 0.8;\n      this.SPEED_FACTOR = 1;\n      this.DEAD_PX = 2;\n      this.ATT_FACTOR = 4;\n      this.DESPAWN_FACTOR = 0.02;\n      this.NOOFCURVES_RANGES = [2, 5];\n      this.AMPLITUDE_RANGES = [0.3, 1];\n      this.OFFSET_RANGES = [-3, 3];\n      this.WIDTH_RANGES = [1, 3];\n      this.SPEED_RANGES = [0.5, 1];\n      this.DESPAWN_TIMEOUT_RANGES = [500, 2000];\n      this.respawn();\n    }\n\n    _createClass(iOS9Curve, [{\n      key: \"getRandomRange\",\n      value: function getRandomRange(e) {\n        return e[0] + Math.random() * (e[1] - e[0]);\n      }\n    }, {\n      key: \"respawnSingle\",\n      value: function respawnSingle(ci) {\n        this.phases[ci] = 0;\n        this.amplitudes[ci] = 0;\n        this.despawnTimeouts[ci] = this.getRandomRange(this.DESPAWN_TIMEOUT_RANGES);\n        this.offsets[ci] = this.getRandomRange(this.OFFSET_RANGES);\n        this.speeds[ci] = this.getRandomRange(this.SPEED_RANGES);\n        this.finalAmplitudes[ci] = this.getRandomRange(this.AMPLITUDE_RANGES);\n        this.widths[ci] = this.getRandomRange(this.WIDTH_RANGES);\n        this.verses[ci] = this.getRandomRange([-1, 1]);\n      }\n    }, {\n      key: \"respawn\",\n      value: function respawn() {\n        this.spawnAt = Date.now();\n        this.noOfCurves = Math.floor(this.getRandomRange(this.NOOFCURVES_RANGES));\n        this.phases = new Array(this.noOfCurves);\n        this.offsets = new Array(this.noOfCurves);\n        this.speeds = new Array(this.noOfCurves);\n        this.finalAmplitudes = new Array(this.noOfCurves);\n        this.widths = new Array(this.noOfCurves);\n        this.amplitudes = new Array(this.noOfCurves);\n        this.despawnTimeouts = new Array(this.noOfCurves);\n        this.verses = new Array(this.noOfCurves);\n\n        for (var ci = 0; ci < this.noOfCurves; ci++) {\n          this.respawnSingle(ci);\n        }\n      }\n    }, {\n      key: \"globalAttFn\",\n      value: function globalAttFn(x) {\n        return Math.pow(this.ATT_FACTOR / (this.ATT_FACTOR + Math.pow(x, 2)), this.ATT_FACTOR);\n      }\n    }, {\n      key: \"sin\",\n      value: function sin(x, phase) {\n        return Math.sin(x - phase);\n      }\n    }, {\n      key: \"_grad\",\n      value: function _grad(x, a, b) {\n        if (x > a && x < b) return 1;\n        return 1;\n      }\n    }, {\n      key: \"yRelativePos\",\n      value: function yRelativePos(i) {\n        var y = 0;\n\n        for (var ci = 0; ci < this.noOfCurves; ci++) {\n          // Generate a static T so that each curve is distant from each oterh\n          var t = 4 * (-1 + ci / (this.noOfCurves - 1) * 2); // but add a dynamic offset\n\n          t += this.offsets[ci];\n          var k = 1 / this.widths[ci];\n          var x = i * k - t;\n          y += Math.abs(this.amplitudes[ci] * this.sin(this.verses[ci] * x, this.phases[ci]) * this.globalAttFn(x));\n        } // Divide for NoOfCurves so that y <= 1\n\n\n        return y / this.noOfCurves;\n      }\n    }, {\n      key: \"_ypos\",\n      value: function _ypos(i) {\n        return this.AMPLITUDE_FACTOR * this.ctrl.heightMax * this.ctrl.amplitude * this.yRelativePos(i) * this.globalAttFn(i / this.GRAPH_X * 2);\n      }\n    }, {\n      key: \"_xpos\",\n      value: function _xpos(i) {\n        return this.ctrl.width * ((i + this.GRAPH_X) / (this.GRAPH_X * 2));\n      }\n    }, {\n      key: \"drawSupportLine\",\n      value: function drawSupportLine(ctx) {\n        var coo = [0, this.ctrl.heightMax, this.ctrl.width, 1];\n        var gradient = ctx.createLinearGradient.apply(ctx, coo);\n        gradient.addColorStop(0, \"transparent\");\n        gradient.addColorStop(0.1, \"rgba(255,255,255,.5)\");\n        gradient.addColorStop(1 - 0.1 - 0.1, \"rgba(255,255,255,.5)\");\n        gradient.addColorStop(1, \"transparent\");\n        ctx.fillStyle = gradient;\n        ctx.fillRect.apply(ctx, coo);\n      }\n    }, {\n      key: \"draw\",\n      value: function draw() {\n        var ctx = this.ctrl.ctx;\n        ctx.globalAlpha = 0.7;\n        ctx.globalCompositeOperation = \"lighter\";\n\n        if (this.definition.supportLine) {\n          // Draw the support line\n          return this.drawSupportLine(ctx);\n        }\n\n        for (var ci = 0; ci < this.noOfCurves; ci++) {\n          if (this.spawnAt + this.despawnTimeouts[ci] <= Date.now()) {\n            this.amplitudes[ci] -= this.DESPAWN_FACTOR;\n          } else {\n            this.amplitudes[ci] += this.DESPAWN_FACTOR;\n          }\n\n          this.amplitudes[ci] = Math.min(Math.max(this.amplitudes[ci], 0), this.finalAmplitudes[ci]);\n          this.phases[ci] = (this.phases[ci] + this.ctrl.speed * this.speeds[ci] * this.SPEED_FACTOR) % (2 * Math.PI);\n        }\n\n        var maxY = -Infinity;\n\n        for (var _i = 0, _arr = [1, -1]; _i < _arr.length; _i++) {\n          var sign = _arr[_i];\n          ctx.beginPath();\n\n          for (var i = -this.GRAPH_X; i <= this.GRAPH_X; i += this.ctrl.opt.pixelDepth) {\n            var x = this._xpos(i);\n\n            var y = this._ypos(i);\n\n            ctx.lineTo(x, this.ctrl.heightMax - sign * y);\n            maxY = Math.max(maxY, y);\n          }\n\n          ctx.closePath();\n          ctx.fillStyle = \"rgba(\".concat(this.definition.color, \", 1)\");\n          ctx.strokeStyle = \"rgba(\".concat(this.definition.color, \", 1)\");\n          ctx.fill();\n        }\n\n        if (maxY < this.DEAD_PX && this.prevMaxY > maxY) {\n          this.respawn();\n        }\n\n        this.prevMaxY = maxY;\n        return null;\n      }\n    }], [{\n      key: \"getDefinition\",\n      value: function getDefinition(waveColors) {\n        return Object.assign([{\n          color: \"255,255,255\",\n          supportLine: true\n        }, {\n          // blue\n          color: \"15, 82, 169\"\n        }, {\n          // red\n          color: \"173, 57, 76\"\n        }, {\n          // green\n          color: \"48, 220, 155\"\n        }], waveColors);\n      }\n    }]);\n\n    return iOS9Curve;\n  }();\n\n  var SiriWave = /*#__PURE__*/function () {\n    /**\n     * Build the SiriWave\n     * @param {Object} opt\n     * @param {DOMElement} [opt.container=document.body] The DOM container where the DOM canvas element will be added\n     * @param {String} [opt.style='ios'] The style of the wave: `ios` or `ios9`\n     * @param {Number} [opt.ratio=null] Ratio of the display to use. Calculated by default.\n     * @param {Number} [opt.speed=0.2] The speed of the animation.\n     * @param {Number} [opt.amplitude=1] The amplitude of the complete wave.\n     * @param {Number} [opt.frequency=6] The frequency for the complete wave (how many waves). - Not available in iOS9 Style\n     * @param {String} [opt.color='#fff'] The color of the wave, in hexadecimal form (`#336699`, `#FF0`). - Not available in iOS9 Style\n     * @param {Boolean} [opt.cover=false] The `canvas` covers the entire width or height of the container.\n     * @param {Number} [opt.width=null] Width of the canvas. Calculated by default.\n     * @param {Number} [opt.height=null] Height of the canvas. Calculated by default.\n     * @param {Boolean} [opt.autostart=false] Decide wether start the animation on boot.\n     * @param {Number} [opt.pixelDepth=0.02] Number of step (in pixels) used when drawed on canvas.\n     * @param {Number} [opt.lerpSpeed=0.1] Lerp speed to interpolate properties.\n     */\n    function SiriWave() {\n      var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n      _classCallCheck(this, SiriWave);\n\n      this.container = opt.container || document.body; // In this.opt you could find definitive opt with defaults values\n\n      this.opt = Object.assign({\n        style: \"ios\",\n        ratio: window.devicePixelRatio || 1,\n        speed: 0.2,\n        amplitude: 1,\n        frequency: 6,\n        color: \"#fff\",\n        cover: false,\n        width: window.getComputedStyle(this.container).width.replace(\"px\", \"\"),\n        height: window.getComputedStyle(this.container).height.replace(\"px\", \"\"),\n        autostart: false,\n        pixelDepth: 0.02,\n        lerpSpeed: 0.1\n      }, opt);\n      /**\n       * Phase of the wave (passed to Math.sin function)\n       */\n\n      this.phase = 0;\n      /**\n       * Boolean value indicating the the animation is running\n       */\n\n      this.run = false;\n      /**\n       * Actual speed of the animation. Is not safe to change this value directly, use `setSpeed` instead.\n       */\n\n      this.speed = Number(this.opt.speed);\n      /**\n       * Actual amplitude of the animation. Is not safe to change this value directly, use `setAmplitude` instead.\n       */\n\n      this.amplitude = Number(this.opt.amplitude);\n      /**\n       * Width of the canvas multiplied by pixel ratio\n       */\n\n      this.width = Number(this.opt.ratio * this.opt.width);\n      /**\n       * Height of the canvas multiplied by pixel ratio\n       */\n\n      this.height = Number(this.opt.ratio * this.opt.height);\n      /**\n       * Maximum height for a single wave\n       */\n\n      this.heightMax = Number(this.height / 2) - 6;\n      /**\n       * Color of the wave (used in Classic iOS)\n       */\n\n      this.color = \"rgb(\".concat(this.hex2rgb(this.opt.color), \")\");\n      /**\n       * An object containing controller variables that need to be interpolated\n       * to an another value before to be actually changed\n       */\n\n      this.interpolation = {\n        speed: this.speed,\n        amplitude: this.amplitude\n      };\n      /**\n       * Canvas DOM Element where curves will be drawn\n       */\n\n      this.canvas = document.createElement(\"canvas\");\n      /**\n       * 2D Context from Canvas\n       */\n\n      this.ctx = this.canvas.getContext(\"2d\"); // Set dimensions\n\n      this.canvas.width = this.width;\n      this.canvas.height = this.height; // By covering, we ensure the canvas is in the same size of the parent\n\n      if (this.opt.cover === true) {\n        this.canvas.style.width = this.canvas.style.height = \"100%\";\n      } else {\n        this.canvas.style.width = \"\".concat(this.width / this.opt.ratio, \"px\");\n        this.canvas.style.height = \"\".concat(this.height / this.opt.ratio, \"px\");\n      }\n      /**\n       * Curves objects to animate\n       */\n\n\n      this.curves = []; // Instantiate all curves based on the style\n\n      if (this.opt.style === \"ios9\") {\n        var _iterator = _createForOfIteratorHelper(iOS9Curve.getDefinition(this.opt.waveColors || [])),\n            _step;\n\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var def = _step.value;\n            this.curves.push(new iOS9Curve({\n              ctrl: this,\n              definition: def\n            }));\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      } else {\n        var _iterator2 = _createForOfIteratorHelper(Curve.getDefinition()),\n            _step2;\n\n        try {\n          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n            var _def = _step2.value;\n            this.curves.push(new Curve({\n              ctrl: this,\n              definition: _def\n            }));\n          }\n        } catch (err) {\n          _iterator2.e(err);\n        } finally {\n          _iterator2.f();\n        }\n      } // Attach to the container\n\n\n      this.container.appendChild(this.canvas); // Start the animation\n\n      if (opt.autostart) {\n        this.start();\n      }\n    }\n    /**\n     * Convert an HEX color to RGB\n     * @param {String} hex\n     * @returns RGB value that could be used\n     * @memberof SiriWave\n     */\n\n\n    _createClass(SiriWave, [{\n      key: \"hex2rgb\",\n      value: function hex2rgb(hex) {\n        var shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n        hex = hex.replace(shorthandRegex, function (m, r, g, b) {\n          return r + r + g + g + b + b;\n        });\n        var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n        return result ? \"\".concat(parseInt(result[1], 16).toString(), \",\").concat(parseInt(result[2], 16).toString(), \",\").concat(parseInt(result[3], 16).toString()) : null;\n      }\n      /**\n       * Interpolate a property to the value found in $.interpolation\n       * @param {String} propertyStr\n       * @returns\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"lerp\",\n      value: function lerp(propertyStr) {\n        this[propertyStr] = lerp_1(this[propertyStr], this.interpolation[propertyStr], this.opt.lerpSpeed);\n\n        if (this[propertyStr] - this.interpolation[propertyStr] === 0) {\n          this.interpolation[propertyStr] = null;\n        }\n\n        return this[propertyStr];\n      }\n      /**\n       * Clear the canvas\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"_clear\",\n      value: function _clear() {\n        this.ctx.globalCompositeOperation = \"destination-out\";\n        this.ctx.fillRect(0, 0, this.width, this.height);\n        this.ctx.globalCompositeOperation = \"source-over\";\n      }\n      /**\n       * Draw all curves\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"_draw\",\n      value: function _draw() {\n        var _iterator3 = _createForOfIteratorHelper(this.curves),\n            _step3;\n\n        try {\n          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n            var curve = _step3.value;\n            curve.draw();\n          }\n        } catch (err) {\n          _iterator3.e(err);\n        } finally {\n          _iterator3.f();\n        }\n      }\n      /**\n       * Clear the space, interpolate values, calculate new steps and draws\n       * @returns\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"startDrawCycle\",\n      value: function startDrawCycle() {\n        if (this.run === false) return;\n\n        this._clear(); // Interpolate values\n\n\n        if (this.interpolation.amplitude !== null) this.lerp(\"amplitude\");\n        if (this.interpolation.speed !== null) this.lerp(\"speed\");\n\n        this._draw();\n\n        this.phase = (this.phase + Math.PI / 2 * this.speed) % (2 * Math.PI);\n\n        if (window.requestAnimationFrame) {\n          window.requestAnimationFrame(this.startDrawCycle.bind(this));\n        } else {\n          setTimeout(this.startDrawCycle.bind(this), 20);\n        }\n      }\n      /* API */\n\n      /**\n       * Start the animation\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"start\",\n      value: function start() {\n        this.phase = 0;\n        this.run = true;\n        this.startDrawCycle();\n      }\n      /**\n       * Stop the animation\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"stop\",\n      value: function stop() {\n        this.phase = 0;\n        this.run = false;\n      }\n      /**\n       * Set a new value for a property (interpolated)\n       * @param {String} propertyStr\n       * @param {Number} v\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"set\",\n      value: function set(propertyStr, v) {\n        this.interpolation[propertyStr] = Number(v);\n      }\n      /**\n       * Set a new value for the speed property (interpolated)\n       * @param {Number} v\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"setSpeed\",\n      value: function setSpeed(v) {\n        this.set(\"speed\", v);\n      }\n      /**\n       * Set a new value for the amplitude property (interpolated)\n       * @param {Number} v\n       * @memberof SiriWave\n       */\n\n    }, {\n      key: \"setAmplitude\",\n      value: function setAmplitude(v) {\n        this.set(\"amplitude\", v);\n      }\n    }]);\n\n    return SiriWave;\n  }();\n\n  return SiriWave;\n\n})));\n\n\n//# sourceURL=webpack://kd-login/../../node_modules/siriwave/dist/siriwave.umd.js?");

/***/ }),

/***/ "../../node_modules/webcamjs/webcam.js":
/*!*********************************************!*\
  !*** ../../node_modules/webcamjs/webcam.js ***!
  \*********************************************/
/***/ (function(module, exports, __webpack_require__) {

eval("var __WEBPACK_AMD_DEFINE_RESULT__;// WebcamJS v1.0.26\n// Webcam library for capturing JPEG/PNG images in JavaScript\n// Attempts getUserMedia, falls back to Flash\n// Author: Joseph Huckaby: http://github.com/jhuckaby\n// Based on JPEGCam: http://code.google.com/p/jpegcam/\n// Copyright (c) 2012 - 2019 Joseph Huckaby\n// Licensed under the MIT License\n\n(function(window) {\nvar _userMedia;\n\n// declare error types\n\n// inheritance pattern here:\n// https://stackoverflow.com/questions/783818/how-do-i-create-a-custom-error-in-javascript\nfunction FlashError() {\n\tvar temp = Error.apply(this, arguments);\n\ttemp.name = this.name = \"FlashError\";\n\tthis.stack = temp.stack;\n\tthis.message = temp.message;\n}\n\nfunction WebcamError() {\n\tvar temp = Error.apply(this, arguments);\n\ttemp.name = this.name = \"WebcamError\";\n\tthis.stack = temp.stack;\n\tthis.message = temp.message;\n}\n\nvar IntermediateInheritor = function() {};\nIntermediateInheritor.prototype = Error.prototype;\n\nFlashError.prototype = new IntermediateInheritor();\nWebcamError.prototype = new IntermediateInheritor();\n\nvar Webcam = {\n\tversion: '1.0.26',\n\t\n\t// globals\n\tprotocol: location.protocol.match(/https/i) ? 'https' : 'http',\n\tloaded: false,   // true when webcam movie finishes loading\n\tlive: false,     // true when webcam is initialized and ready to snap\n\tuserMedia: true, // true when getUserMedia is supported natively\n\n\tiOS: /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,\n\n\tparams: {\n\t\twidth: 0,\n\t\theight: 0,\n\t\tdest_width: 0,         // size of captured image\n\t\tdest_height: 0,        // these default to width/height\n\t\timage_format: 'jpeg',  // image format (may be jpeg or png)\n\t\tjpeg_quality: 90,      // jpeg image quality from 0 (worst) to 100 (best)\n\t\tenable_flash: true,    // enable flash fallback,\n\t\tforce_flash: false,    // force flash mode,\n\t\tflip_horiz: false,     // flip image horiz (mirror mode)\n\t\tfps: 30,               // camera frames per second\n\t\tupload_name: 'webcam', // name of file in upload post data\n\t\tconstraints: null,     // custom user media constraints,\n\t\tswfURL: '',            // URI to webcam.swf movie (defaults to the js location)\n\t\tflashNotDetectedText: 'ERROR: No Adobe Flash Player detected.  Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours).',\n\t\tnoInterfaceFoundText: 'No supported webcam interface found.',\n\t\tunfreeze_snap: true,    // Whether to unfreeze the camera after snap (defaults to true)\n\t\tiosPlaceholderText: 'Click here to open camera.',\n\t\tuser_callback: null,    // callback function for snapshot (used if no user_callback parameter given to snap function)\n\t\tuser_canvas: null       // user provided canvas for snapshot (used if no user_canvas parameter given to snap function)\n\t},\n\n\terrors: {\n\t\tFlashError: FlashError,\n\t\tWebcamError: WebcamError\n\t},\n\t\n\thooks: {}, // callback hook functions\n\t\n\tinit: function() {\n\t\t// initialize, check for getUserMedia support\n\t\tvar self = this;\n\t\t\n\t\t// Setup getUserMedia, with polyfill for older browsers\n\t\t// Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia\n\t\tthis.mediaDevices = (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ? \n\t\t\tnavigator.mediaDevices : ((navigator.mozGetUserMedia || navigator.webkitGetUserMedia) ? {\n\t\t\t\tgetUserMedia: function(c) {\n\t\t\t\t\treturn new Promise(function(y, n) {\n\t\t\t\t\t\t(navigator.mozGetUserMedia ||\n\t\t\t\t\t\tnavigator.webkitGetUserMedia).call(navigator, c, y, n);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t} : null);\n\t\t\n\t\twindow.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;\n\t\tthis.userMedia = this.userMedia && !!this.mediaDevices && !!window.URL;\n\t\t\n\t\t// Older versions of firefox (< 21) apparently claim support but user media does not actually work\n\t\tif (navigator.userAgent.match(/Firefox\\D+(\\d+)/)) {\n\t\t\tif (parseInt(RegExp.$1, 10) < 21) this.userMedia = null;\n\t\t}\n\t\t\n\t\t// Make sure media stream is closed when navigating away from page\n\t\tif (this.userMedia) {\n\t\t\twindow.addEventListener( 'beforeunload', function(event) {\n\t\t\t\tself.reset();\n\t\t\t} );\n\t\t}\n\t},\n\t\n\texifOrientation: function(binFile) {\n\t\t// extract orientation information from the image provided by iOS\n\t\t// algorithm based on exif-js\n\t\tvar dataView = new DataView(binFile);\n\t\tif ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {\n\t\t\tconsole.log('Not a valid JPEG file');\n\t\t\treturn 0;\n\t\t}\n\t\tvar offset = 2;\n\t\tvar marker = null;\n\t\twhile (offset < binFile.byteLength) {\n\t\t\t// find 0xFFE1 (225 marker)\n\t\t\tif (dataView.getUint8(offset) != 0xFF) {\n\t\t\t\tconsole.log('Not a valid marker at offset ' + offset + ', found: ' + dataView.getUint8(offset));\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tmarker = dataView.getUint8(offset + 1);\n\t\t\tif (marker == 225) {\n\t\t\t\toffset += 4;\n\t\t\t\tvar str = \"\";\n\t\t\t\tfor (n = 0; n < 4; n++) {\n\t\t\t\t\tstr += String.fromCharCode(dataView.getUint8(offset+n));\n\t\t\t\t}\n\t\t\t\tif (str != 'Exif') {\n\t\t\t\t\tconsole.log('Not valid EXIF data found');\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toffset += 6; // tiffOffset\n\t\t\t\tvar bigEnd = null;\n\n\t\t\t\t// test for TIFF validity and endianness\n\t\t\t\tif (dataView.getUint16(offset) == 0x4949) {\n\t\t\t\t\tbigEnd = false;\n\t\t\t\t} else if (dataView.getUint16(offset) == 0x4D4D) {\n\t\t\t\t\tbigEnd = true;\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"Not valid TIFF data! (no 0x4949 or 0x4D4D)\");\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\tif (dataView.getUint16(offset+2, !bigEnd) != 0x002A) {\n\t\t\t\t\tconsole.log(\"Not valid TIFF data! (no 0x002A)\");\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\tvar firstIFDOffset = dataView.getUint32(offset+4, !bigEnd);\n\t\t\t\tif (firstIFDOffset < 0x00000008) {\n\t\t\t\t\tconsole.log(\"Not valid TIFF data! (First offset less than 8)\", dataView.getUint32(offset+4, !bigEnd));\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\t// extract orientation data\n\t\t\t\tvar dataStart = offset + firstIFDOffset;\n\t\t\t\tvar entries = dataView.getUint16(dataStart, !bigEnd);\n\t\t\t\tfor (var i=0; i<entries; i++) {\n\t\t\t\t\tvar entryOffset = dataStart + i*12 + 2;\n\t\t\t\t\tif (dataView.getUint16(entryOffset, !bigEnd) == 0x0112) {\n\t\t\t\t\t\tvar valueType = dataView.getUint16(entryOffset+2, !bigEnd);\n\t\t\t\t\t\tvar numValues = dataView.getUint32(entryOffset+4, !bigEnd);\n\t\t\t\t\t\tif (valueType != 3 && numValues != 1) {\n\t\t\t\t\t\t\tconsole.log('Invalid EXIF orientation value type ('+valueType+') or count ('+numValues+')');\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar value = dataView.getUint16(entryOffset + 8, !bigEnd);\n\t\t\t\t\t\tif (value < 1 || value > 8) {\n\t\t\t\t\t\t\tconsole.log('Invalid EXIF orientation value ('+value+')');\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toffset += 2+dataView.getUint16(offset+2);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t},\n\t\n\tfixOrientation: function(origObjURL, orientation, targetImg) {\n\t\t// fix image orientation based on exif orientation data\n\t\t// exif orientation information\n\t\t//    http://www.impulseadventure.com/photo/exif-orientation.html\n\t\t//    link source wikipedia (https://en.wikipedia.org/wiki/Exif#cite_note-20)\n\t\tvar img = new Image();\n\t\timg.addEventListener('load', function(event) {\n\t\t\tvar canvas = document.createElement('canvas');\n\t\t\tvar ctx = canvas.getContext('2d');\n\t\t\t\n\t\t\t// switch width height if orientation needed\n\t\t\tif (orientation < 5) {\n\t\t\t\tcanvas.width = img.width;\n\t\t\t\tcanvas.height = img.height;\n\t\t\t} else {\n\t\t\t\tcanvas.width = img.height;\n\t\t\t\tcanvas.height = img.width;\n\t\t\t}\n\n\t\t\t// transform (rotate) image - see link at beginning this method\n\t\t\tswitch (orientation) {\n\t\t\t\tcase 2: ctx.transform(-1, 0, 0, 1, img.width, 0); break;\n\t\t\t\tcase 3: ctx.transform(-1, 0, 0, -1, img.width, img.height); break;\n\t\t\t\tcase 4: ctx.transform(1, 0, 0, -1, 0, img.height); break;\n\t\t\t\tcase 5: ctx.transform(0, 1, 1, 0, 0, 0); break;\n\t\t\t\tcase 6: ctx.transform(0, 1, -1, 0, img.height , 0); break;\n\t\t\t\tcase 7: ctx.transform(0, -1, -1, 0, img.height, img.width); break;\n\t\t\t\tcase 8: ctx.transform(0, -1, 1, 0, 0, img.width); break;\n\t\t\t}\n\n\t\t\tctx.drawImage(img, 0, 0);\n\t\t\t// pass rotated image data to the target image container\n\t\t\ttargetImg.src = canvas.toDataURL();\n\t\t}, false);\n\t\t// start transformation by load event\n\t\timg.src = origObjURL;\n\t},\n\t\n\tattach: function(elem) {\n\t\t// create webcam preview and attach to DOM element\n\t\t// pass in actual DOM reference, ID, or CSS selector\n\t\tif (typeof(elem) == 'string') {\n\t\t\telem = document.getElementById(elem) || document.querySelector(elem);\n\t\t}\n\t\tif (!elem) {\n\t\t\treturn this.dispatch('error', new WebcamError(\"Could not locate DOM element to attach to.\"));\n\t\t}\n\t\tthis.container = elem;\n\t\telem.innerHTML = ''; // start with empty element\n\t\t\n\t\t// insert \"peg\" so we can insert our preview canvas adjacent to it later on\n\t\tvar peg = document.createElement('div');\n\t\telem.appendChild( peg );\n\t\tthis.peg = peg;\n\t\t\n\t\t// set width/height if not already set\n\t\tif (!this.params.width) this.params.width = elem.offsetWidth;\n\t\tif (!this.params.height) this.params.height = elem.offsetHeight;\n\t\t\n\t\t// make sure we have a nonzero width and height at this point\n\t\tif (!this.params.width || !this.params.height) {\n\t\t\treturn this.dispatch('error', new WebcamError(\"No width and/or height for webcam.  Please call set() first, or attach to a visible element.\"));\n\t\t}\n\t\t\n\t\t// set defaults for dest_width / dest_height if not set\n\t\tif (!this.params.dest_width) this.params.dest_width = this.params.width;\n\t\tif (!this.params.dest_height) this.params.dest_height = this.params.height;\n\t\t\n\t\tthis.userMedia = _userMedia === undefined ? this.userMedia : _userMedia;\n\t\t// if force_flash is set, disable userMedia\n\t\tif (this.params.force_flash) {\n\t\t\t_userMedia = this.userMedia;\n\t\t\tthis.userMedia = null;\n\t\t}\n\t\t\n\t\t// check for default fps\n\t\tif (typeof this.params.fps !== \"number\") this.params.fps = 30;\n\n\t\t// adjust scale if dest_width or dest_height is different\n\t\tvar scaleX = this.params.width / this.params.dest_width;\n\t\tvar scaleY = this.params.height / this.params.dest_height;\n\t\t\n\t\tif (this.userMedia) {\n\t\t\t// setup webcam video container\n\t\t\tvar video = document.createElement('video');\n\t\t\tvideo.setAttribute('autoplay', 'autoplay');\n\t\t\tvideo.setAttribute('playsinline', 'playsinline');\n\t\t\tvideo.style.width = '' + this.params.dest_width + 'px';\n\t\t\tvideo.style.height = '' + this.params.dest_height + 'px';\n\t\t\t\n\t\t\tif ((scaleX != 1.0) || (scaleY != 1.0)) {\n\t\t\t\telem.style.overflow = 'hidden';\n\t\t\t\tvideo.style.webkitTransformOrigin = '0px 0px';\n\t\t\t\tvideo.style.mozTransformOrigin = '0px 0px';\n\t\t\t\tvideo.style.msTransformOrigin = '0px 0px';\n\t\t\t\tvideo.style.oTransformOrigin = '0px 0px';\n\t\t\t\tvideo.style.transformOrigin = '0px 0px';\n\t\t\t\tvideo.style.webkitTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\t\tvideo.style.mozTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\t\tvideo.style.msTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\t\tvideo.style.oTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\t\tvideo.style.transform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\t}\n\t\t\t\n\t\t\t// add video element to dom\n\t\t\telem.appendChild( video );\n\t\t\tthis.video = video;\n\t\t\t\n\t\t\t// ask user for access to their camera\n\t\t\tvar self = this;\n\t\t\tthis.mediaDevices.getUserMedia({\n\t\t\t\t\"audio\": false,\n\t\t\t\t\"video\": this.params.constraints || {\n\t\t\t\t\tmandatory: {\n\t\t\t\t\t\tminWidth: this.params.dest_width,\n\t\t\t\t\t\tminHeight: this.params.dest_height\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then( function(stream) {\n\t\t\t\t// got access, attach stream to video\n\t\t\t\tvideo.onloadedmetadata = function(e) {\n\t\t\t\t\tself.stream = stream;\n\t\t\t\t\tself.loaded = true;\n\t\t\t\t\tself.live = true;\n\t\t\t\t\tself.dispatch('load');\n\t\t\t\t\tself.dispatch('live');\n\t\t\t\t\tself.flip();\n\t\t\t\t};\n\t\t\t\t// as window.URL.createObjectURL() is deprecated, adding a check so that it works in Safari.\n\t\t\t\t// older browsers may not have srcObject\n\t\t\t\tif (\"srcObject\" in video) {\n\t\t\t\t  \tvideo.srcObject = stream;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t  \t// using URL.createObjectURL() as fallback for old browsers\n\t\t\t\t  \tvideo.src = window.URL.createObjectURL(stream);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch( function(err) {\n\t\t\t\t// JH 2016-07-31 Instead of dispatching error, now falling back to Flash if userMedia fails (thx @john2014)\n\t\t\t\t// JH 2016-08-07 But only if flash is actually installed -- if not, dispatch error here and now.\n\t\t\t\tif (self.params.enable_flash && self.detectFlash()) {\n\t\t\t\t\tsetTimeout( function() { self.params.force_flash = 1; self.attach(elem); }, 1 );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tself.dispatch('error', err);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\telse if (this.iOS) {\n\t\t\t// prepare HTML elements\n\t\t\tvar div = document.createElement('div');\n\t\t\tdiv.id = this.container.id+'-ios_div';\n\t\t\tdiv.className = 'webcamjs-ios-placeholder';\n\t\t\tdiv.style.width = '' + this.params.width + 'px';\n\t\t\tdiv.style.height = '' + this.params.height + 'px';\n\t\t\tdiv.style.textAlign = 'center';\n\t\t\tdiv.style.display = 'table-cell';\n\t\t\tdiv.style.verticalAlign = 'middle';\n\t\t\tdiv.style.backgroundRepeat = 'no-repeat';\n\t\t\tdiv.style.backgroundSize = 'contain';\n\t\t\tdiv.style.backgroundPosition = 'center';\n\t\t\tvar span = document.createElement('span');\n\t\t\tspan.className = 'webcamjs-ios-text';\n\t\t\tspan.innerHTML = this.params.iosPlaceholderText;\n\t\t\tdiv.appendChild(span);\n\t\t\tvar img = document.createElement('img');\n\t\t\timg.id = this.container.id+'-ios_img';\n\t\t\timg.style.width = '' + this.params.dest_width + 'px';\n\t\t\timg.style.height = '' + this.params.dest_height + 'px';\n\t\t\timg.style.display = 'none';\n\t\t\tdiv.appendChild(img);\n\t\t\tvar input = document.createElement('input');\n\t\t\tinput.id = this.container.id+'-ios_input';\n\t\t\tinput.setAttribute('type', 'file');\n\t\t\tinput.setAttribute('accept', 'image/*');\n\t\t\tinput.setAttribute('capture', 'camera');\n\t\t\t\n\t\t\tvar self = this;\n\t\t\tvar params = this.params;\n\t\t\t// add input listener to load the selected image\n\t\t\tinput.addEventListener('change', function(event) {\n\t\t\t\tif (event.target.files.length > 0 && event.target.files[0].type.indexOf('image/') == 0) {\n\t\t\t\t\tvar objURL = URL.createObjectURL(event.target.files[0]);\n\n\t\t\t\t\t// load image with auto scale and crop\n\t\t\t\t\tvar image = new Image();\n\t\t\t\t\timage.addEventListener('load', function(event) {\n\t\t\t\t\t\tvar canvas = document.createElement('canvas');\n\t\t\t\t\t\tcanvas.width = params.dest_width;\n\t\t\t\t\t\tcanvas.height = params.dest_height;\n\t\t\t\t\t\tvar ctx = canvas.getContext('2d');\n\n\t\t\t\t\t\t// crop and scale image for final size\n\t\t\t\t\t\tratio = Math.min(image.width / params.dest_width, image.height / params.dest_height);\n\t\t\t\t\t\tvar sw = params.dest_width * ratio;\n\t\t\t\t\t\tvar sh = params.dest_height * ratio;\n\t\t\t\t\t\tvar sx = (image.width - sw) / 2;\n\t\t\t\t\t\tvar sy = (image.height - sh) / 2;\n\t\t\t\t\t\tctx.drawImage(image, sx, sy, sw, sh, 0, 0, params.dest_width, params.dest_height);\n\n\t\t\t\t\t\tvar dataURL = canvas.toDataURL();\n\t\t\t\t\t\timg.src = dataURL;\n\t\t\t\t\t\tdiv.style.backgroundImage = \"url('\"+dataURL+\"')\";\n\t\t\t\t\t}, false);\n\t\t\t\t\t\n\t\t\t\t\t// read EXIF data\n\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\tfileReader.addEventListener('load', function(e) {\n\t\t\t\t\t\tvar orientation = self.exifOrientation(e.target.result);\n\t\t\t\t\t\tif (orientation > 1) {\n\t\t\t\t\t\t\t// image need to rotate (see comments on fixOrientation method for more information)\n\t\t\t\t\t\t\t// transform image and load to image object\n\t\t\t\t\t\t\tself.fixOrientation(objURL, orientation, image);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// load image data to image object\n\t\t\t\t\t\t\timage.src = objURL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, false);\n\t\t\t\t\t\n\t\t\t\t\t// Convert image data to blob format\n\t\t\t\t\tvar http = new XMLHttpRequest();\n\t\t\t\t\thttp.open(\"GET\", objURL, true);\n\t\t\t\t\thttp.responseType = \"blob\";\n\t\t\t\t\thttp.onload = function(e) {\n\t\t\t\t\t\tif (this.status == 200 || this.status === 0) {\n\t\t\t\t\t\t\tfileReader.readAsArrayBuffer(this.response);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\thttp.send();\n\n\t\t\t\t}\n\t\t\t}, false);\n\t\t\tinput.style.display = 'none';\n\t\t\telem.appendChild(input);\n\t\t\t// make div clickable for open camera interface\n\t\t\tdiv.addEventListener('click', function(event) {\n\t\t\t\tif (params.user_callback) {\n\t\t\t\t\t// global user_callback defined - create the snapshot\n\t\t\t\t\tself.snap(params.user_callback, params.user_canvas);\n\t\t\t\t} else {\n\t\t\t\t\t// no global callback definied for snapshot, load image and wait for external snap method call\n\t\t\t\t\tinput.style.display = 'block';\n\t\t\t\t\tinput.focus();\n\t\t\t\t\tinput.click();\n\t\t\t\t\tinput.style.display = 'none';\n\t\t\t\t}\n\t\t\t}, false);\n\t\t\telem.appendChild(div);\n\t\t\tthis.loaded = true;\n\t\t\tthis.live = true;\n\t\t}\n\t\telse if (this.params.enable_flash && this.detectFlash()) {\n\t\t\t// flash fallback\n\t\t\twindow.Webcam = Webcam; // needed for flash-to-js interface\n\t\t\tvar div = document.createElement('div');\n\t\t\tdiv.innerHTML = this.getSWFHTML();\n\t\t\telem.appendChild( div );\n\t\t}\n\t\telse {\n\t\t\tthis.dispatch('error', new WebcamError( this.params.noInterfaceFoundText ));\n\t\t}\n\t\t\n\t\t// setup final crop for live preview\n\t\tif (this.params.crop_width && this.params.crop_height) {\n\t\t\tvar scaled_crop_width = Math.floor( this.params.crop_width * scaleX );\n\t\t\tvar scaled_crop_height = Math.floor( this.params.crop_height * scaleY );\n\t\t\t\n\t\t\telem.style.width = '' + scaled_crop_width + 'px';\n\t\t\telem.style.height = '' + scaled_crop_height + 'px';\n\t\t\telem.style.overflow = 'hidden';\n\t\t\t\n\t\t\telem.scrollLeft = Math.floor( (this.params.width / 2) - (scaled_crop_width / 2) );\n\t\t\telem.scrollTop = Math.floor( (this.params.height / 2) - (scaled_crop_height / 2) );\n\t\t}\n\t\telse {\n\t\t\t// no crop, set size to desired\n\t\t\telem.style.width = '' + this.params.width + 'px';\n\t\t\telem.style.height = '' + this.params.height + 'px';\n\t\t}\n\t},\n\t\n\treset: function() {\n\t\t// shutdown camera, reset to potentially attach again\n\t\tif (this.preview_active) this.unfreeze();\n\t\t\n\t\t// attempt to fix issue #64\n\t\tthis.unflip();\n\t\t\n\t\tif (this.userMedia) {\n\t\t\tif (this.stream) {\n\t\t\t\tif (this.stream.getVideoTracks) {\n\t\t\t\t\t// get video track to call stop on it\n\t\t\t\t\tvar tracks = this.stream.getVideoTracks();\n\t\t\t\t\tif (tracks && tracks[0] && tracks[0].stop) tracks[0].stop();\n\t\t\t\t}\n\t\t\t\telse if (this.stream.stop) {\n\t\t\t\t\t// deprecated, may be removed in future\n\t\t\t\t\tthis.stream.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t\tdelete this.stream;\n\t\t\tdelete this.video;\n\t\t}\n\n\t\tif ((this.userMedia !== true) && this.loaded && !this.iOS) {\n\t\t\t// call for turn off camera in flash\n\t\t\tvar movie = this.getMovie();\n\t\t\tif (movie && movie._releaseCamera) movie._releaseCamera();\n\t\t}\n\n\t\tif (this.container) {\n\t\t\tthis.container.innerHTML = '';\n\t\t\tdelete this.container;\n\t\t}\n\t\n\t\tthis.loaded = false;\n\t\tthis.live = false;\n\t},\n\t\n\tset: function() {\n\t\t// set one or more params\n\t\t// variable argument list: 1 param = hash, 2 params = key, value\n\t\tif (arguments.length == 1) {\n\t\t\tfor (var key in arguments[0]) {\n\t\t\t\tthis.params[key] = arguments[0][key];\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.params[ arguments[0] ] = arguments[1];\n\t\t}\n\t},\n\t\n\ton: function(name, callback) {\n\t\t// set callback hook\n\t\tname = name.replace(/^on/i, '').toLowerCase();\n\t\tif (!this.hooks[name]) this.hooks[name] = [];\n\t\tthis.hooks[name].push( callback );\n\t},\n\t\n\toff: function(name, callback) {\n\t\t// remove callback hook\n\t\tname = name.replace(/^on/i, '').toLowerCase();\n\t\tif (this.hooks[name]) {\n\t\t\tif (callback) {\n\t\t\t\t// remove one selected callback from list\n\t\t\t\tvar idx = this.hooks[name].indexOf(callback);\n\t\t\t\tif (idx > -1) this.hooks[name].splice(idx, 1);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// no callback specified, so clear all\n\t\t\t\tthis.hooks[name] = [];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tdispatch: function() {\n\t\t// fire hook callback, passing optional value to it\n\t\tvar name = arguments[0].replace(/^on/i, '').toLowerCase();\n\t\tvar args = Array.prototype.slice.call(arguments, 1);\n\t\t\n\t\tif (this.hooks[name] && this.hooks[name].length) {\n\t\t\tfor (var idx = 0, len = this.hooks[name].length; idx < len; idx++) {\n\t\t\t\tvar hook = this.hooks[name][idx];\n\t\t\t\t\n\t\t\t\tif (typeof(hook) == 'function') {\n\t\t\t\t\t// callback is function reference, call directly\n\t\t\t\t\thook.apply(this, args);\n\t\t\t\t}\n\t\t\t\telse if ((typeof(hook) == 'object') && (hook.length == 2)) {\n\t\t\t\t\t// callback is PHP-style object instance method\n\t\t\t\t\thook[0][hook[1]].apply(hook[0], args);\n\t\t\t\t}\n\t\t\t\telse if (window[hook]) {\n\t\t\t\t\t// callback is global function name\n\t\t\t\t\twindow[ hook ].apply(window, args);\n\t\t\t\t}\n\t\t\t} // loop\n\t\t\treturn true;\n\t\t}\n\t\telse if (name == 'error') {\n\t\t\tvar message;\n\t\t\tif ((args[0] instanceof FlashError) || (args[0] instanceof WebcamError)) {\n\t\t\t\tmessage = args[0].message;\n\t\t\t} else {\n\t\t\t\tmessage = \"Could not access webcam: \" + args[0].name + \": \" + \n\t\t\t\t\targs[0].message + \" \" + args[0].toString();\n\t\t\t}\n\n\t\t\t// default error handler if no custom one specified\n\t\t\talert(\"Webcam.js Error: \" + message);\n\t\t}\n\t\t\n\t\treturn false; // no hook defined\n\t},\n\n\tsetSWFLocation: function(value) {\n\t\t// for backward compatibility.\n\t\tthis.set('swfURL', value);\n\t},\n\t\n\tdetectFlash: function() {\n\t\t// return true if browser supports flash, false otherwise\n\t\t// Code snippet borrowed from: https://github.com/swfobject/swfobject\n\t\tvar SHOCKWAVE_FLASH = \"Shockwave Flash\",\n\t\t\tSHOCKWAVE_FLASH_AX = \"ShockwaveFlash.ShockwaveFlash\",\n        \tFLASH_MIME_TYPE = \"application/x-shockwave-flash\",\n        \twin = window,\n        \tnav = navigator,\n        \thasFlash = false;\n        \n        if (typeof nav.plugins !== \"undefined\" && typeof nav.plugins[SHOCKWAVE_FLASH] === \"object\") {\n        \tvar desc = nav.plugins[SHOCKWAVE_FLASH].description;\n        \tif (desc && (typeof nav.mimeTypes !== \"undefined\" && nav.mimeTypes[FLASH_MIME_TYPE] && nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {\n        \t\thasFlash = true;\n        \t}\n        }\n        else if (typeof win.ActiveXObject !== \"undefined\") {\n        \ttry {\n        \t\tvar ax = new ActiveXObject(SHOCKWAVE_FLASH_AX);\n        \t\tif (ax) {\n        \t\t\tvar ver = ax.GetVariable(\"$version\");\n        \t\t\tif (ver) hasFlash = true;\n        \t\t}\n        \t}\n        \tcatch (e) {;}\n        }\n        \n        return hasFlash;\n\t},\n\t\n\tgetSWFHTML: function() {\n\t\t// Return HTML for embedding flash based webcam capture movie\t\t\n\t\tvar html = '',\n\t\t\tswfURL = this.params.swfURL;\n\t\t\n\t\t// make sure we aren't running locally (flash doesn't work)\n\t\tif (location.protocol.match(/file/)) {\n\t\t\tthis.dispatch('error', new FlashError(\"Flash does not work from local disk.  Please run from a web server.\"));\n\t\t\treturn '<h3 style=\"color:red\">ERROR: the Webcam.js Flash fallback does not work from local disk.  Please run it from a web server.</h3>';\n\t\t}\n\t\t\n\t\t// make sure we have flash\n\t\tif (!this.detectFlash()) {\n\t\t\tthis.dispatch('error', new FlashError(\"Adobe Flash Player not found.  Please install from get.adobe.com/flashplayer and try again.\"));\n\t\t\treturn '<h3 style=\"color:red\">' + this.params.flashNotDetectedText + '</h3>';\n\t\t}\n\t\t\n\t\t// set default swfURL if not explicitly set\n\t\tif (!swfURL) {\n\t\t\t// find our script tag, and use that base URL\n\t\t\tvar base_url = '';\n\t\t\tvar scpts = document.getElementsByTagName('script');\n\t\t\tfor (var idx = 0, len = scpts.length; idx < len; idx++) {\n\t\t\t\tvar src = scpts[idx].getAttribute('src');\n\t\t\t\tif (src && src.match(/\\/webcam(\\.min)?\\.js/)) {\n\t\t\t\t\tbase_url = src.replace(/\\/webcam(\\.min)?\\.js.*$/, '');\n\t\t\t\t\tidx = len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (base_url) swfURL = base_url + '/webcam.swf';\n\t\t\telse swfURL = 'webcam.swf';\n\t\t}\n\t\t\n\t\t// if this is the user's first visit, set flashvar so flash privacy settings panel is shown first\n\t\tif (window.localStorage && !localStorage.getItem('visited')) {\n\t\t\tthis.params.new_user = 1;\n\t\t\tlocalStorage.setItem('visited', 1);\n\t\t}\n\t\t\n\t\t// construct flashvars string\n\t\tvar flashvars = '';\n\t\tfor (var key in this.params) {\n\t\t\tif (flashvars) flashvars += '&';\n\t\t\tflashvars += key + '=' + escape(this.params[key]);\n\t\t}\n\t\t\n\t\t// construct object/embed tag\n\t\thtml += '<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" type=\"application/x-shockwave-flash\" codebase=\"'+this.protocol+'://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0\" width=\"'+this.params.width+'\" height=\"'+this.params.height+'\" id=\"webcam_movie_obj\" align=\"middle\"><param name=\"wmode\" value=\"opaque\" /><param name=\"allowScriptAccess\" value=\"sameDomain \" /><param name=\"allowFullScreen\" value=\"false\" /><param name=\"movie\" value=\"'+swfURL+'\" /><param name=\"loop\" value=\"false\" /><param name=\"menu\" value=\"false\" /><param name=\"quality\" value=\"best\" /><param name=\"bgcolor\" value=\"#ffffff\" /><param name=\"flashvars\" value=\"'+flashvars+'\"/><embed id=\"webcam_movie_embed\" src=\"'+swfURL+'\" wmode=\"opaque\" loop=\"false\" menu=\"false\" quality=\"best\" bgcolor=\"#ffffff\" width=\"'+this.params.width+'\" height=\"'+this.params.height+'\" name=\"webcam_movie_embed\" align=\"middle\" allowScriptAccess=\"sameDomain\" allowFullScreen=\"false\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" flashvars=\"'+flashvars+'\"></embed></object>';\n\t\t\n\t\treturn html;\n\t},\n\t\n\tgetMovie: function() {\n\t\t// get reference to movie object/embed in DOM\n\t\tif (!this.loaded) return this.dispatch('error', new FlashError(\"Flash Movie is not loaded yet\"));\n\t\tvar movie = document.getElementById('webcam_movie_obj');\n\t\tif (!movie || !movie._snap) movie = document.getElementById('webcam_movie_embed');\n\t\tif (!movie) this.dispatch('error', new FlashError(\"Cannot locate Flash movie in DOM\"));\n\t\treturn movie;\n\t},\n\t\n\tfreeze: function() {\n\t\t// show preview, freeze camera\n\t\tvar self = this;\n\t\tvar params = this.params;\n\t\t\n\t\t// kill preview if already active\n\t\tif (this.preview_active) this.unfreeze();\n\t\t\n\t\t// determine scale factor\n\t\tvar scaleX = this.params.width / this.params.dest_width;\n\t\tvar scaleY = this.params.height / this.params.dest_height;\n\t\t\n\t\t// must unflip container as preview canvas will be pre-flipped\n\t\tthis.unflip();\n\t\t\n\t\t// calc final size of image\n\t\tvar final_width = params.crop_width || params.dest_width;\n\t\tvar final_height = params.crop_height || params.dest_height;\n\t\t\n\t\t// create canvas for holding preview\n\t\tvar preview_canvas = document.createElement('canvas');\n\t\tpreview_canvas.width = final_width;\n\t\tpreview_canvas.height = final_height;\n\t\tvar preview_context = preview_canvas.getContext('2d');\n\t\t\n\t\t// save for later use\n\t\tthis.preview_canvas = preview_canvas;\n\t\tthis.preview_context = preview_context;\n\t\t\n\t\t// scale for preview size\n\t\tif ((scaleX != 1.0) || (scaleY != 1.0)) {\n\t\t\tpreview_canvas.style.webkitTransformOrigin = '0px 0px';\n\t\t\tpreview_canvas.style.mozTransformOrigin = '0px 0px';\n\t\t\tpreview_canvas.style.msTransformOrigin = '0px 0px';\n\t\t\tpreview_canvas.style.oTransformOrigin = '0px 0px';\n\t\t\tpreview_canvas.style.transformOrigin = '0px 0px';\n\t\t\tpreview_canvas.style.webkitTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\tpreview_canvas.style.mozTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\tpreview_canvas.style.msTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\tpreview_canvas.style.oTransform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t\tpreview_canvas.style.transform = 'scaleX('+scaleX+') scaleY('+scaleY+')';\n\t\t}\n\t\t\n\t\t// take snapshot, but fire our own callback\n\t\tthis.snap( function() {\n\t\t\t// add preview image to dom, adjust for crop\n\t\t\tpreview_canvas.style.position = 'relative';\n\t\t\tpreview_canvas.style.left = '' + self.container.scrollLeft + 'px';\n\t\t\tpreview_canvas.style.top = '' + self.container.scrollTop + 'px';\n\t\t\t\n\t\t\tself.container.insertBefore( preview_canvas, self.peg );\n\t\t\tself.container.style.overflow = 'hidden';\n\t\t\t\n\t\t\t// set flag for user capture (use preview)\n\t\t\tself.preview_active = true;\n\t\t\t\n\t\t}, preview_canvas );\n\t},\n\t\n\tunfreeze: function() {\n\t\t// cancel preview and resume live video feed\n\t\tif (this.preview_active) {\n\t\t\t// remove preview canvas\n\t\t\tthis.container.removeChild( this.preview_canvas );\n\t\t\tdelete this.preview_context;\n\t\t\tdelete this.preview_canvas;\n\t\t\t\n\t\t\t// unflag\n\t\t\tthis.preview_active = false;\n\t\t\t\n\t\t\t// re-flip if we unflipped before\n\t\t\tthis.flip();\n\t\t}\n\t},\n\t\n\tflip: function() {\n\t\t// flip container horiz (mirror mode) if desired\n\t\tif (this.params.flip_horiz) {\n\t\t\tvar sty = this.container.style;\n\t\t\tsty.webkitTransform = 'scaleX(-1)';\n\t\t\tsty.mozTransform = 'scaleX(-1)';\n\t\t\tsty.msTransform = 'scaleX(-1)';\n\t\t\tsty.oTransform = 'scaleX(-1)';\n\t\t\tsty.transform = 'scaleX(-1)';\n\t\t\tsty.filter = 'FlipH';\n\t\t\tsty.msFilter = 'FlipH';\n\t\t}\n\t},\n\t\n\tunflip: function() {\n\t\t// unflip container horiz (mirror mode) if desired\n\t\tif (this.params.flip_horiz) {\n\t\t\tvar sty = this.container.style;\n\t\t\tsty.webkitTransform = 'scaleX(1)';\n\t\t\tsty.mozTransform = 'scaleX(1)';\n\t\t\tsty.msTransform = 'scaleX(1)';\n\t\t\tsty.oTransform = 'scaleX(1)';\n\t\t\tsty.transform = 'scaleX(1)';\n\t\t\tsty.filter = '';\n\t\t\tsty.msFilter = '';\n\t\t}\n\t},\n\t\n\tsavePreview: function(user_callback, user_canvas) {\n\t\t// save preview freeze and fire user callback\n\t\tvar params = this.params;\n\t\tvar canvas = this.preview_canvas;\n\t\tvar context = this.preview_context;\n\t\t\n\t\t// render to user canvas if desired\n\t\tif (user_canvas) {\n\t\t\tvar user_context = user_canvas.getContext('2d');\n\t\t\tuser_context.drawImage( canvas, 0, 0 );\n\t\t}\n\t\t\n\t\t// fire user callback if desired\n\t\tuser_callback(\n\t\t\tuser_canvas ? null : canvas.toDataURL('image/' + params.image_format, params.jpeg_quality / 100 ),\n\t\t\tcanvas,\n\t\t\tcontext\n\t\t);\n\t\t\n\t\t// remove preview\n\t\tif (this.params.unfreeze_snap) this.unfreeze();\n\t},\n\t\n\tsnap: function(user_callback, user_canvas) {\n\t\t// use global callback and canvas if not defined as parameter\n\t\tif (!user_callback) user_callback = this.params.user_callback;\n\t\tif (!user_canvas) user_canvas = this.params.user_canvas;\n\t\t\n\t\t// take snapshot and return image data uri\n\t\tvar self = this;\n\t\tvar params = this.params;\n\t\t\n\t\tif (!this.loaded) return this.dispatch('error', new WebcamError(\"Webcam is not loaded yet\"));\n\t\t// if (!this.live) return this.dispatch('error', new WebcamError(\"Webcam is not live yet\"));\n\t\tif (!user_callback) return this.dispatch('error', new WebcamError(\"Please provide a callback function or canvas to snap()\"));\n\t\t\n\t\t// if we have an active preview freeze, use that\n\t\tif (this.preview_active) {\n\t\t\tthis.savePreview( user_callback, user_canvas );\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\t// create offscreen canvas element to hold pixels\n\t\tvar canvas = document.createElement('canvas');\n\t\tcanvas.width = this.params.dest_width;\n\t\tcanvas.height = this.params.dest_height;\n\t\tvar context = canvas.getContext('2d');\n\t\t\n\t\t// flip canvas horizontally if desired\n\t\tif (this.params.flip_horiz) {\n\t\t\tcontext.translate( params.dest_width, 0 );\n\t\t\tcontext.scale( -1, 1 );\n\t\t}\n\t\t\n\t\t// create inline function, called after image load (flash) or immediately (native)\n\t\tvar func = function() {\n\t\t\t// render image if needed (flash)\n\t\t\tif (this.src && this.width && this.height) {\n\t\t\t\tcontext.drawImage(this, 0, 0, params.dest_width, params.dest_height);\n\t\t\t}\n\t\t\t\n\t\t\t// crop if desired\n\t\t\tif (params.crop_width && params.crop_height) {\n\t\t\t\tvar crop_canvas = document.createElement('canvas');\n\t\t\t\tcrop_canvas.width = params.crop_width;\n\t\t\t\tcrop_canvas.height = params.crop_height;\n\t\t\t\tvar crop_context = crop_canvas.getContext('2d');\n\t\t\t\t\n\t\t\t\tcrop_context.drawImage( canvas, \n\t\t\t\t\tMath.floor( (params.dest_width / 2) - (params.crop_width / 2) ),\n\t\t\t\t\tMath.floor( (params.dest_height / 2) - (params.crop_height / 2) ),\n\t\t\t\t\tparams.crop_width,\n\t\t\t\t\tparams.crop_height,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tparams.crop_width,\n\t\t\t\t\tparams.crop_height\n\t\t\t\t);\n\t\t\t\t\n\t\t\t\t// swap canvases\n\t\t\t\tcontext = crop_context;\n\t\t\t\tcanvas = crop_canvas;\n\t\t\t}\n\t\t\t\n\t\t\t// render to user canvas if desired\n\t\t\tif (user_canvas) {\n\t\t\t\tvar user_context = user_canvas.getContext('2d');\n\t\t\t\tuser_context.drawImage( canvas, 0, 0 );\n\t\t\t}\n\t\t\t\n\t\t\t// fire user callback if desired\n\t\t\tuser_callback(\n\t\t\t\tuser_canvas ? null : canvas.toDataURL('image/' + params.image_format, params.jpeg_quality / 100 ),\n\t\t\t\tcanvas,\n\t\t\t\tcontext\n\t\t\t);\n\t\t};\n\t\t\n\t\t// grab image frame from userMedia or flash movie\n\t\tif (this.userMedia) {\n\t\t\t// native implementation\n\t\t\tcontext.drawImage(this.video, 0, 0, this.params.dest_width, this.params.dest_height);\n\t\t\t\n\t\t\t// fire callback right away\n\t\t\tfunc();\n\t\t}\n\t\telse if (this.iOS) {\n\t\t\tvar div = document.getElementById(this.container.id+'-ios_div');\n\t\t\tvar img = document.getElementById(this.container.id+'-ios_img');\n\t\t\tvar input = document.getElementById(this.container.id+'-ios_input');\n\t\t\t// function for handle snapshot event (call user_callback and reset the interface)\n\t\t\tiFunc = function(event) {\n\t\t\t\tfunc.call(img);\n\t\t\t\timg.removeEventListener('load', iFunc);\n\t\t\t\tdiv.style.backgroundImage = 'none';\n\t\t\t\timg.removeAttribute('src');\n\t\t\t\tinput.value = null;\n\t\t\t};\n\t\t\tif (!input.value) {\n\t\t\t\t// No image selected yet, activate input field\n\t\t\t\timg.addEventListener('load', iFunc);\n\t\t\t\tinput.style.display = 'block';\n\t\t\t\tinput.focus();\n\t\t\t\tinput.click();\n\t\t\t\tinput.style.display = 'none';\n\t\t\t} else {\n\t\t\t\t// Image already selected\n\t\t\t\tiFunc(null);\n\t\t\t}\t\t\t\n\t\t}\n\t\telse {\n\t\t\t// flash fallback\n\t\t\tvar raw_data = this.getMovie()._snap();\n\t\t\t\n\t\t\t// render to image, fire callback when complete\n\t\t\tvar img = new Image();\n\t\t\timg.onload = func;\n\t\t\timg.src = 'data:image/'+this.params.image_format+';base64,' + raw_data;\n\t\t}\n\t\t\n\t\treturn null;\n\t},\n\t\n\tconfigure: function(panel) {\n\t\t// open flash configuration panel -- specify tab name:\n\t\t// \"camera\", \"privacy\", \"default\", \"localStorage\", \"microphone\", \"settingsManager\"\n\t\tif (!panel) panel = \"camera\";\n\t\tthis.getMovie()._configure(panel);\n\t},\n\t\n\tflashNotify: function(type, msg) {\n\t\t// receive notification from flash about event\n\t\tswitch (type) {\n\t\t\tcase 'flashLoadComplete':\n\t\t\t\t// movie loaded successfully\n\t\t\t\tthis.loaded = true;\n\t\t\t\tthis.dispatch('load');\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 'cameraLive':\n\t\t\t\t// camera is live and ready to snap\n\t\t\t\tthis.live = true;\n\t\t\t\tthis.dispatch('live');\n\t\t\t\tbreak;\n\n\t\t\tcase 'error':\n\t\t\t\t// Flash error\n\t\t\t\tthis.dispatch('error', new FlashError(msg));\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// catch-all event, just in case\n\t\t\t\t// console.log(\"webcam flash_notify: \" + type + \": \" + msg);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tb64ToUint6: function(nChr) {\n\t\t// convert base64 encoded character to 6-bit integer\n\t\t// from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding\n\t\treturn nChr > 64 && nChr < 91 ? nChr - 65\n\t\t\t: nChr > 96 && nChr < 123 ? nChr - 71\n\t\t\t: nChr > 47 && nChr < 58 ? nChr + 4\n\t\t\t: nChr === 43 ? 62 : nChr === 47 ? 63 : 0;\n\t},\n\n\tbase64DecToArr: function(sBase64, nBlocksSize) {\n\t\t// convert base64 encoded string to Uintarray\n\t\t// from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding\n\t\tvar sB64Enc = sBase64.replace(/[^A-Za-z0-9\\+\\/]/g, \"\"), nInLen = sB64Enc.length,\n\t\t\tnOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, \n\t\t\ttaBytes = new Uint8Array(nOutLen);\n\t\t\n\t\tfor (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {\n\t\t\tnMod4 = nInIdx & 3;\n\t\t\tnUint24 |= this.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;\n\t\t\tif (nMod4 === 3 || nInLen - nInIdx === 1) {\n\t\t\t\tfor (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {\n\t\t\t\t\ttaBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;\n\t\t\t\t}\n\t\t\t\tnUint24 = 0;\n\t\t\t}\n\t\t}\n\t\treturn taBytes;\n\t},\n\t\n\tupload: function(image_data_uri, target_url, callback) {\n\t\t// submit image data to server using binary AJAX\n\t\tvar form_elem_name = this.params.upload_name || 'webcam';\n\t\t\n\t\t// detect image format from within image_data_uri\n\t\tvar image_fmt = '';\n\t\tif (image_data_uri.match(/^data\\:image\\/(\\w+)/))\n\t\t\timage_fmt = RegExp.$1;\n\t\telse\n\t\t\tthrow \"Cannot locate image format in Data URI\";\n\t\t\n\t\t// extract raw base64 data from Data URI\n\t\tvar raw_image_data = image_data_uri.replace(/^data\\:image\\/\\w+\\;base64\\,/, '');\n\t\t\n\t\t// contruct use AJAX object\n\t\tvar http = new XMLHttpRequest();\n\t\thttp.open(\"POST\", target_url, true);\n\t\t\n\t\t// setup progress events\n\t\tif (http.upload && http.upload.addEventListener) {\n\t\t\thttp.upload.addEventListener( 'progress', function(e) {\n\t\t\t\tif (e.lengthComputable) {\n\t\t\t\t\tvar progress = e.loaded / e.total;\n\t\t\t\t\tWebcam.dispatch('uploadProgress', progress, e);\n\t\t\t\t}\n\t\t\t}, false );\n\t\t}\n\t\t\n\t\t// completion handler\n\t\tvar self = this;\n\t\thttp.onload = function() {\n\t\t\tif (callback) callback.apply( self, [http.status, http.responseText, http.statusText] );\n\t\t\tWebcam.dispatch('uploadComplete', http.status, http.responseText, http.statusText);\n\t\t};\n\t\t\n\t\t// create a blob and decode our base64 to binary\n\t\tvar blob = new Blob( [ this.base64DecToArr(raw_image_data) ], {type: 'image/'+image_fmt} );\n\t\t\n\t\t// stuff into a form, so servers can easily receive it as a standard file upload\n\t\tvar form = new FormData();\n\t\tform.append( form_elem_name, blob, form_elem_name+\".\"+image_fmt.replace(/e/, '') );\n\t\t\n\t\t// send data to server\n\t\thttp.send(form);\n\t}\n\t\n};\n\nWebcam.init();\n\nif (true) {\n\t!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { return Webcam; }).call(exports, __webpack_require__, exports, module),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n} \nelse {}\n\n}(window));\n\n\n//# sourceURL=webpack://kd-login/../../node_modules/webcamjs/webcam.js?");

/***/ })

}]);