From c9290875bf2d4455201099249451b58b9ffc40c4 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Wed, 5 Jun 2024 20:42:43 +0200 Subject: [PATCH] 8.8 --- lam/lib/plugins/captcha/FriendlyCaptcha.inc | 2 +- lam/sbom-libs.json | 16 +- ...1.10.5.css => 200_sweetalert2_11.11.1.css} | 0 ...ropper-1.6.0.css => 600_cropper-1.6.2.css} | 191 +- lam/templates/lib/410_cropper-1.6.2.js | 3273 +++++++++++++++++ ..._11.10.5.js => 620_sweetalert2_11.11.1.js} | 327 +- .../friendly-challenge-0.9.14.js | 1234 ------- .../friendly-challenge-0.9.15.js | 1596 ++++++++ 8 files changed, 5108 insertions(+), 1531 deletions(-) rename lam/style/{200_sweetalert2_11.10.5.css => 200_sweetalert2_11.11.1.css} (100%) rename lam/style/{600_cropper-1.6.0.css => 600_cropper-1.6.2.css} (62%) create mode 100644 lam/templates/lib/410_cropper-1.6.2.js rename lam/templates/lib/{620_sweetalert2_11.10.5.js => 620_sweetalert2_11.11.1.js} (95%) delete mode 100644 lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.14.js create mode 100644 lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.15.js diff --git a/lam/lib/plugins/captcha/FriendlyCaptcha.inc b/lam/lib/plugins/captcha/FriendlyCaptcha.inc index e50676714..3e3c62631 100644 --- a/lam/lib/plugins/captcha/FriendlyCaptcha.inc +++ b/lam/lib/plugins/captcha/FriendlyCaptcha.inc @@ -118,7 +118,7 @@ class htmlFriendlyCaptcha extends htmlElement { * @return array List of input field names and their type (name => type) */ function generateHTML($module, $input, $values, $restricted, $scope) { - $script = new htmlScript('../lib/extra/friendlyCaptcha/friendly-challenge-0.9.14.js'); + $script = new htmlScript('../lib/extra/friendlyCaptcha/friendly-challenge-0.9.15.js'); $script->generateHTML($module, $input, $values, $restricted, $scope); echo '
'; return []; diff --git a/lam/sbom-libs.json b/lam/sbom-libs.json index 076ac36c1..52dca02d9 100644 --- a/lam/sbom-libs.json +++ b/lam/sbom-libs.json @@ -1,10 +1,10 @@ { "bomFormat" : "CycloneDX", "specVersion" : "1.5", - "serialNumber" : "urn:uuid:49f02510-fe68-4816-a9a1-c5a80f752868", + "serialNumber" : "urn:uuid:f3e3a97d-1ae7-46db-a896-250fc05a857d", "version" : 1, "metadata" : { - "timestamp" : "2024-06-05T18:11:18Z", + "timestamp" : "2024-06-05T18:42:19Z", "tools" : [ { "vendor" : "OWASP", @@ -39,7 +39,7 @@ { "group" : "cdx:npm:package:bundled", "name" : "cropperjs", - "version" : "1.6.1", + "version" : "1.6.2", "licenses" : [ { "license" : { @@ -47,7 +47,7 @@ } } ], - "purl" : "pkg:npm/cropperjs@1.6.1", + "purl" : "pkg:npm/cropperjs@1.6.2", "type" : "library", "bom-ref" : "d0142b40-7a81-4f6b-b681-af8ab91ea836" }, @@ -69,7 +69,7 @@ { "group" : "cdx:npm:package:bundled", "name" : "friendly-challenge", - "version" : "0.9.14", + "version" : "0.9.15", "licenses" : [ { "license" : { @@ -77,7 +77,7 @@ } } ], - "purl" : "pkg:npm/friendly-challenge@3.7.1", + "purl" : "pkg:npm/friendly-challenge@0.9.15", "type" : "library", "bom-ref" : "5ffbae18-bc06-4fdb-ba19-f9e9e1afdda5" }, @@ -144,7 +144,7 @@ { "group" : "cdx:npm:package:bundled", "name" : "sweetalert2", - "version" : "11.10.5", + "version" : "11.11.1", "licenses" : [ { "license" : { @@ -152,7 +152,7 @@ } } ], - "purl" : "pkg:npm/sweetalert2@11.10.5", + "purl" : "pkg:npm/sweetalert2@11.11.1", "type" : "library", "bom-ref" : "b1e652b5-d76e-4b07-acab-2d1a0908a96f" }, diff --git a/lam/style/200_sweetalert2_11.10.5.css b/lam/style/200_sweetalert2_11.11.1.css similarity index 100% rename from lam/style/200_sweetalert2_11.10.5.css rename to lam/style/200_sweetalert2_11.11.1.css diff --git a/lam/style/600_cropper-1.6.0.css b/lam/style/600_cropper-1.6.2.css similarity index 62% rename from lam/style/600_cropper-1.6.0.css rename to lam/style/600_cropper-1.6.2.css index c4b9f98ce..db40c6446 100644 --- a/lam/style/600_cropper-1.6.0.css +++ b/lam/style/600_cropper-1.6.2.css @@ -1,24 +1,25 @@ /*! - * Cropper.js v1.6.1 + * Cropper.js v1.6.2 * https://fengyuanchen.github.io/cropperjs * * Copyright 2015-present Chen Fengyuan * Released under the MIT license * - * Date: 2023-09-17T03:44:17.565Z + * Date: 2024-04-21T07:43:02.731Z */ .cropper-container { - direction: ltr; - font-size: 0; - line-height: 0; - position: relative; - -ms-touch-action: none; - touch-action: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + direction: ltr; + font-size: 0; + line-height: 0; + position: relative; + -ms-touch-action: none; + touch-action: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .cropper-container img { @@ -31,49 +32,49 @@ min-height: 0 !important; min-width: 0 !important; width: 100%; -} + } .cropper-wrap-box, .cropper-canvas, .cropper-drag-box, .cropper-crop-box, .cropper-modal { - bottom: 0; - left: 0; - position: absolute; - right: 0; - top: 0; + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; } .cropper-wrap-box, .cropper-canvas { - overflow: hidden; + overflow: hidden; } .cropper-drag-box { - background-color: #fff; - opacity: 0; + background-color: #fff; + opacity: 0; } .cropper-modal { - background-color: #000; - opacity: 0.5; + background-color: #000; + opacity: 0.5; } .cropper-view-box { - display: block; - height: 100%; - outline: 1px solid #39f; - outline-color: rgba(51, 153, 255, 0.75); - overflow: hidden; - width: 100%; + display: block; + height: 100%; + outline: 1px solid #39f; + outline-color: rgba(51, 153, 255, 0.75); + overflow: hidden; + width: 100%; } .cropper-dashed { - border: 0 dashed #eee; - display: block; - opacity: 0.5; - position: absolute; + border: 0 dashed #eee; + display: block; + opacity: 0.5; + position: absolute; } .cropper-dashed.dashed-h { @@ -83,7 +84,7 @@ left: 0; top: calc(100% / 3); width: 100%; -} + } .cropper-dashed.dashed-v { border-left-width: 1px; @@ -92,58 +93,58 @@ left: calc(100% / 3); top: 0; width: calc(100% / 3); -} + } .cropper-center { - display: block; - height: 0; - left: 50%; - opacity: 0.75; - position: absolute; - top: 50%; - width: 0; + display: block; + height: 0; + left: 50%; + opacity: 0.75; + position: absolute; + top: 50%; + width: 0; } .cropper-center::before, -.cropper-center::after { + .cropper-center::after { background-color: #eee; content: ' '; display: block; position: absolute; -} + } .cropper-center::before { height: 1px; left: -3px; top: 0; width: 7px; -} + } .cropper-center::after { height: 7px; left: 0; top: -3px; width: 1px; -} + } .cropper-face, .cropper-line, .cropper-point { - display: block; - height: 100%; - opacity: 0.1; - position: absolute; - width: 100%; + display: block; + height: 100%; + opacity: 0.1; + position: absolute; + width: 100%; } .cropper-face { - background-color: #fff; - left: 0; - top: 0; + background-color: #fff; + left: 0; + top: 0; } .cropper-line { - background-color: #39f; + background-color: #39f; } .cropper-line.line-e { @@ -151,34 +152,34 @@ right: -3px; top: 0; width: 5px; -} + } .cropper-line.line-n { cursor: ns-resize; height: 5px; left: 0; top: -3px; -} + } .cropper-line.line-w { cursor: ew-resize; left: -3px; top: 0; width: 5px; -} + } .cropper-line.line-s { bottom: -3px; cursor: ns-resize; height: 5px; left: 0; -} + } .cropper-point { - background-color: #39f; - height: 5px; - opacity: 0.75; - width: 5px; + background-color: #39f; + height: 5px; + opacity: 0.75; + width: 5px; } .cropper-point.point-e { @@ -186,46 +187,46 @@ margin-top: -3px; right: -3px; top: 50%; -} + } .cropper-point.point-n { cursor: ns-resize; left: 50%; margin-left: -3px; top: -3px; -} + } .cropper-point.point-w { cursor: ew-resize; left: -3px; margin-top: -3px; top: 50%; -} + } .cropper-point.point-s { bottom: -3px; cursor: s-resize; left: 50%; margin-left: -3px; -} + } .cropper-point.point-ne { cursor: nesw-resize; right: -3px; top: -3px; -} + } .cropper-point.point-nw { cursor: nwse-resize; left: -3px; top: -3px; -} + } .cropper-point.point-sw { bottom: -3px; cursor: nesw-resize; left: -3px; -} + } .cropper-point.point-se { bottom: -3px; @@ -234,32 +235,32 @@ opacity: 1; right: -3px; width: 20px; -} + } @media (min-width: 768px) { - .cropper-point.point-se { - height: 15px; - width: 15px; +.cropper-point.point-se { + height: 15px; + width: 15px; + } } -} @media (min-width: 992px) { - .cropper-point.point-se { - height: 10px; - width: 10px; +.cropper-point.point-se { + height: 10px; + width: 10px; + } } -} @media (min-width: 1200px) { - .cropper-point.point-se { - height: 5px; - opacity: 0.75; - width: 5px; +.cropper-point.point-se { + height: 5px; + opacity: 0.75; + width: 5px; + } } -} .cropper-point.point-se::before { background-color: #39f; @@ -271,38 +272,38 @@ position: absolute; right: -50%; width: 200%; -} + } .cropper-invisible { - opacity: 0; + opacity: 0; } .cropper-bg { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC'); + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC'); } .cropper-hide { - display: block; - height: 0; - position: absolute; - width: 0; + display: block; + height: 0; + position: absolute; + width: 0; } .cropper-hidden { - display: none !important; + display: none !important; } .cropper-move { - cursor: move; + cursor: move; } .cropper-crop { - cursor: crosshair; + cursor: crosshair; } .cropper-disabled .cropper-drag-box, .cropper-disabled .cropper-face, .cropper-disabled .cropper-line, .cropper-disabled .cropper-point { - cursor: not-allowed; + cursor: not-allowed; } diff --git a/lam/templates/lib/410_cropper-1.6.2.js b/lam/templates/lib/410_cropper-1.6.2.js new file mode 100644 index 000000000..e9cf961a4 --- /dev/null +++ b/lam/templates/lib/410_cropper-1.6.2.js @@ -0,0 +1,3273 @@ +/*! + * Cropper.js v1.6.2 + * https://fengyuanchen.github.io/cropperjs + * + * Copyright 2015-present Chen Fengyuan + * Released under the MIT license + * + * Date: 2024-04-21T07:43:05.335Z + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Cropper = factory()); +})(this, (function () { 'use strict'; + + function ownKeys(e, r) { + var t = Object.keys(e); + if (Object.getOwnPropertySymbols) { + var o = Object.getOwnPropertySymbols(e); + r && (o = o.filter(function (r) { + return Object.getOwnPropertyDescriptor(e, r).enumerable; + })), t.push.apply(t, o); + } + return t; + } + function _objectSpread2(e) { + for (var r = 1; r < arguments.length; r++) { + var t = null != arguments[r] ? arguments[r] : {}; + r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { + _defineProperty(e, r, t[r]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { + Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); + }); + } + return e; + } + function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); + } + function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; + } + function _typeof(o) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _defineProperty(obj, key, value) { + key = _toPropertyKey(key); + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; + var WINDOW = IS_BROWSER ? window : {}; + var IS_TOUCH_DEVICE = IS_BROWSER && WINDOW.document.documentElement ? 'ontouchstart' in WINDOW.document.documentElement : false; + var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false; + var NAMESPACE = 'cropper'; + + // Actions + var ACTION_ALL = 'all'; + var ACTION_CROP = 'crop'; + var ACTION_MOVE = 'move'; + var ACTION_ZOOM = 'zoom'; + var ACTION_EAST = 'e'; + var ACTION_WEST = 'w'; + var ACTION_SOUTH = 's'; + var ACTION_NORTH = 'n'; + var ACTION_NORTH_EAST = 'ne'; + var ACTION_NORTH_WEST = 'nw'; + var ACTION_SOUTH_EAST = 'se'; + var ACTION_SOUTH_WEST = 'sw'; + + // Classes + var CLASS_CROP = "".concat(NAMESPACE, "-crop"); + var CLASS_DISABLED = "".concat(NAMESPACE, "-disabled"); + var CLASS_HIDDEN = "".concat(NAMESPACE, "-hidden"); + var CLASS_HIDE = "".concat(NAMESPACE, "-hide"); + var CLASS_INVISIBLE = "".concat(NAMESPACE, "-invisible"); + var CLASS_MODAL = "".concat(NAMESPACE, "-modal"); + var CLASS_MOVE = "".concat(NAMESPACE, "-move"); + + // Data keys + var DATA_ACTION = "".concat(NAMESPACE, "Action"); + var DATA_PREVIEW = "".concat(NAMESPACE, "Preview"); + + // Drag modes + var DRAG_MODE_CROP = 'crop'; + var DRAG_MODE_MOVE = 'move'; + var DRAG_MODE_NONE = 'none'; + + // Events + var EVENT_CROP = 'crop'; + var EVENT_CROP_END = 'cropend'; + var EVENT_CROP_MOVE = 'cropmove'; + var EVENT_CROP_START = 'cropstart'; + var EVENT_DBLCLICK = 'dblclick'; + var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown'; + var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove'; + var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup'; + var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START; + var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE; + var EVENT_POINTER_UP = HAS_POINTER_EVENT ? 'pointerup pointercancel' : EVENT_TOUCH_END; + var EVENT_READY = 'ready'; + var EVENT_RESIZE = 'resize'; + var EVENT_WHEEL = 'wheel'; + var EVENT_ZOOM = 'zoom'; + + // Mime types + var MIME_TYPE_JPEG = 'image/jpeg'; + + // RegExps + var REGEXP_ACTIONS = /^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/; + var REGEXP_DATA_URL = /^data:/; + var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; + var REGEXP_TAG_NAME = /^img|canvas$/i; + + // Misc + // Inspired by the default width and height of a canvas element. + var MIN_CONTAINER_WIDTH = 200; + var MIN_CONTAINER_HEIGHT = 100; + + var DEFAULTS = { + // Define the view mode of the cropper + viewMode: 0, + // 0, 1, 2, 3 + + // Define the dragging mode of the cropper + dragMode: DRAG_MODE_CROP, + // 'crop', 'move' or 'none' + + // Define the initial aspect ratio of the crop box + initialAspectRatio: NaN, + // Define the aspect ratio of the crop box + aspectRatio: NaN, + // An object with the previous cropping result data + data: null, + // A selector for adding extra containers to preview + preview: '', + // Re-render the cropper when resize the window + responsive: true, + // Restore the cropped area after resize the window + restore: true, + // Check if the current image is a cross-origin image + checkCrossOrigin: true, + // Check the current image's Exif Orientation information + checkOrientation: true, + // Show the black modal + modal: true, + // Show the dashed lines for guiding + guides: true, + // Show the center indicator for guiding + center: true, + // Show the white modal to highlight the crop box + highlight: true, + // Show the grid background + background: true, + // Enable to crop the image automatically when initialize + autoCrop: true, + // Define the percentage of automatic cropping area when initializes + autoCropArea: 0.8, + // Enable to move the image + movable: true, + // Enable to rotate the image + rotatable: true, + // Enable to scale the image + scalable: true, + // Enable to zoom the image + zoomable: true, + // Enable to zoom the image by dragging touch + zoomOnTouch: true, + // Enable to zoom the image by wheeling mouse + zoomOnWheel: true, + // Define zoom ratio when zoom the image by wheeling mouse + wheelZoomRatio: 0.1, + // Enable to move the crop box + cropBoxMovable: true, + // Enable to resize the crop box + cropBoxResizable: true, + // Toggle drag mode between "crop" and "move" when click twice on the cropper + toggleDragModeOnDblclick: true, + // Size limitation + minCanvasWidth: 0, + minCanvasHeight: 0, + minCropBoxWidth: 0, + minCropBoxHeight: 0, + minContainerWidth: MIN_CONTAINER_WIDTH, + minContainerHeight: MIN_CONTAINER_HEIGHT, + // Shortcuts of events + ready: null, + cropstart: null, + cropmove: null, + cropend: null, + crop: null, + zoom: null + }; + + var TEMPLATE = '
' + '
' + '
' + '
' + '
' + '
' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
' + '
'; + + /** + * Check if the given value is not a number. + */ + var isNaN = Number.isNaN || WINDOW.isNaN; + + /** + * Check if the given value is a number. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is a number, else `false`. + */ + function isNumber(value) { + return typeof value === 'number' && !isNaN(value); + } + + /** + * Check if the given value is a positive number. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is a positive number, else `false`. + */ + var isPositiveNumber = function isPositiveNumber(value) { + return value > 0 && value < Infinity; + }; + + /** + * Check if the given value is undefined. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is undefined, else `false`. + */ + function isUndefined(value) { + return typeof value === 'undefined'; + } + + /** + * Check if the given value is an object. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is an object, else `false`. + */ + function isObject(value) { + return _typeof(value) === 'object' && value !== null; + } + var hasOwnProperty = Object.prototype.hasOwnProperty; + + /** + * Check if the given value is a plain object. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is a plain object, else `false`. + */ + function isPlainObject(value) { + if (!isObject(value)) { + return false; + } + try { + var _constructor = value.constructor; + var prototype = _constructor.prototype; + return _constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf'); + } catch (error) { + return false; + } + } + + /** + * Check if the given value is a function. + * @param {*} value - The value to check. + * @returns {boolean} Returns `true` if the given value is a function, else `false`. + */ + function isFunction(value) { + return typeof value === 'function'; + } + var slice = Array.prototype.slice; + + /** + * Convert array-like or iterable object to an array. + * @param {*} value - The value to convert. + * @returns {Array} Returns a new array. + */ + function toArray(value) { + return Array.from ? Array.from(value) : slice.call(value); + } + + /** + * Iterate the given data. + * @param {*} data - The data to iterate. + * @param {Function} callback - The process function for each element. + * @returns {*} The original data. + */ + function forEach(data, callback) { + if (data && isFunction(callback)) { + if (Array.isArray(data) || isNumber(data.length) /* array-like */) { + toArray(data).forEach(function (value, key) { + callback.call(data, value, key, data); + }); + } else if (isObject(data)) { + Object.keys(data).forEach(function (key) { + callback.call(data, data[key], key, data); + }); + } + } + return data; + } + + /** + * Extend the given object. + * @param {*} target - The target object to extend. + * @param {*} args - The rest objects for merging to the target object. + * @returns {Object} The extended object. + */ + var assign = Object.assign || function assign(target) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + if (isObject(target) && args.length > 0) { + args.forEach(function (arg) { + if (isObject(arg)) { + Object.keys(arg).forEach(function (key) { + target[key] = arg[key]; + }); + } + }); + } + return target; + }; + var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + + /** + * Normalize decimal number. + * Check out {@link https://0.30000000000000004.com/} + * @param {number} value - The value to normalize. + * @param {number} [times=100000000000] - The times for normalizing. + * @returns {number} Returns the normalized number. + */ + function normalizeDecimalNumber(value) { + var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000; + return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value; + } + var REGEXP_SUFFIX = /^width|height|left|top|marginLeft|marginTop$/; + + /** + * Apply styles to the given element. + * @param {Element} element - The target element. + * @param {Object} styles - The styles for applying. + */ + function setStyle(element, styles) { + var style = element.style; + forEach(styles, function (value, property) { + if (REGEXP_SUFFIX.test(property) && isNumber(value)) { + value = "".concat(value, "px"); + } + style[property] = value; + }); + } + + /** + * Check if the given element has a special class. + * @param {Element} element - The element to check. + * @param {string} value - The class to search. + * @returns {boolean} Returns `true` if the special class was found. + */ + function hasClass(element, value) { + return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1; + } + + /** + * Add classes to the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be added. + */ + function addClass(element, value) { + if (!value) { + return; + } + if (isNumber(element.length)) { + forEach(element, function (elem) { + addClass(elem, value); + }); + return; + } + if (element.classList) { + element.classList.add(value); + return; + } + var className = element.className.trim(); + if (!className) { + element.className = value; + } else if (className.indexOf(value) < 0) { + element.className = "".concat(className, " ").concat(value); + } + } + + /** + * Remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be removed. + */ + function removeClass(element, value) { + if (!value) { + return; + } + if (isNumber(element.length)) { + forEach(element, function (elem) { + removeClass(elem, value); + }); + return; + } + if (element.classList) { + element.classList.remove(value); + return; + } + if (element.className.indexOf(value) >= 0) { + element.className = element.className.replace(value, ''); + } + } + + /** + * Add or remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be toggled. + * @param {boolean} added - Add only. + */ + function toggleClass(element, value, added) { + if (!value) { + return; + } + if (isNumber(element.length)) { + forEach(element, function (elem) { + toggleClass(elem, value, added); + }); + return; + } + + // IE10-11 doesn't support the second parameter of `classList.toggle` + if (added) { + addClass(element, value); + } else { + removeClass(element, value); + } + } + var REGEXP_CAMEL_CASE = /([a-z\d])([A-Z])/g; + + /** + * Transform the given string from camelCase to kebab-case + * @param {string} value - The value to transform. + * @returns {string} The transformed value. + */ + function toParamCase(value) { + return value.replace(REGEXP_CAMEL_CASE, '$1-$2').toLowerCase(); + } + + /** + * Get data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to get. + * @returns {string} The data value. + */ + function getData(element, name) { + if (isObject(element[name])) { + return element[name]; + } + if (element.dataset) { + return element.dataset[name]; + } + return element.getAttribute("data-".concat(toParamCase(name))); + } + + /** + * Set data to the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to set. + * @param {string} data - The data value. + */ + function setData(element, name, data) { + if (isObject(data)) { + element[name] = data; + } else if (element.dataset) { + element.dataset[name] = data; + } else { + element.setAttribute("data-".concat(toParamCase(name)), data); + } + } + + /** + * Remove data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to remove. + */ + function removeData(element, name) { + if (isObject(element[name])) { + try { + delete element[name]; + } catch (error) { + element[name] = undefined; + } + } else if (element.dataset) { + // #128 Safari not allows to delete dataset property + try { + delete element.dataset[name]; + } catch (error) { + element.dataset[name] = undefined; + } + } else { + element.removeAttribute("data-".concat(toParamCase(name))); + } + } + var REGEXP_SPACES = /\s\s*/; + var onceSupported = function () { + var supported = false; + if (IS_BROWSER) { + var once = false; + var listener = function listener() {}; + var options = Object.defineProperty({}, 'once', { + get: function get() { + supported = true; + return once; + }, + /** + * This setter can fix a `TypeError` in strict mode + * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only} + * @param {boolean} value - The value to set + */ + set: function set(value) { + once = value; + } + }); + WINDOW.addEventListener('test', listener, options); + WINDOW.removeEventListener('test', listener, options); + } + return supported; + }(); + + /** + * Remove event listener from the target element. + * @param {Element} element - The event target. + * @param {string} type - The event type(s). + * @param {Function} listener - The event listener. + * @param {Object} options - The event options. + */ + function removeListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + var handler = listener; + type.trim().split(REGEXP_SPACES).forEach(function (event) { + if (!onceSupported) { + var listeners = element.listeners; + if (listeners && listeners[event] && listeners[event][listener]) { + handler = listeners[event][listener]; + delete listeners[event][listener]; + if (Object.keys(listeners[event]).length === 0) { + delete listeners[event]; + } + if (Object.keys(listeners).length === 0) { + delete element.listeners; + } + } + } + element.removeEventListener(event, handler, options); + }); + } + + /** + * Add event listener to the target element. + * @param {Element} element - The event target. + * @param {string} type - The event type(s). + * @param {Function} listener - The event listener. + * @param {Object} options - The event options. + */ + function addListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + var _handler = listener; + type.trim().split(REGEXP_SPACES).forEach(function (event) { + if (options.once && !onceSupported) { + var _element$listeners = element.listeners, + listeners = _element$listeners === void 0 ? {} : _element$listeners; + _handler = function handler() { + delete listeners[event][listener]; + element.removeEventListener(event, _handler, options); + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + listener.apply(element, args); + }; + if (!listeners[event]) { + listeners[event] = {}; + } + if (listeners[event][listener]) { + element.removeEventListener(event, listeners[event][listener], options); + } + listeners[event][listener] = _handler; + element.listeners = listeners; + } + element.addEventListener(event, _handler, options); + }); + } + + /** + * Dispatch event on the target element. + * @param {Element} element - The event target. + * @param {string} type - The event type(s). + * @param {Object} data - The additional event data. + * @returns {boolean} Indicate if the event is default prevented or not. + */ + function dispatchEvent(element, type, data) { + var event; + + // Event and CustomEvent on IE9-11 are global objects, not constructors + if (isFunction(Event) && isFunction(CustomEvent)) { + event = new CustomEvent(type, { + detail: data, + bubbles: true, + cancelable: true + }); + } else { + event = document.createEvent('CustomEvent'); + event.initCustomEvent(type, true, true, data); + } + return element.dispatchEvent(event); + } + + /** + * Get the offset base on the document. + * @param {Element} element - The target element. + * @returns {Object} The offset data. + */ + function getOffset(element) { + var box = element.getBoundingClientRect(); + return { + left: box.left + (window.pageXOffset - document.documentElement.clientLeft), + top: box.top + (window.pageYOffset - document.documentElement.clientTop) + }; + } + var location = WINDOW.location; + var REGEXP_ORIGINS = /^(\w+:)\/\/([^:/?#]*):?(\d*)/i; + + /** + * Check if the given URL is a cross origin URL. + * @param {string} url - The target URL. + * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`. + */ + function isCrossOriginURL(url) { + var parts = url.match(REGEXP_ORIGINS); + return parts !== null && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); + } + + /** + * Add timestamp to the given URL. + * @param {string} url - The target URL. + * @returns {string} The result URL. + */ + function addTimestamp(url) { + var timestamp = "timestamp=".concat(new Date().getTime()); + return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; + } + + /** + * Get transforms base on the given object. + * @param {Object} obj - The target object. + * @returns {string} A string contains transform values. + */ + function getTransforms(_ref) { + var rotate = _ref.rotate, + scaleX = _ref.scaleX, + scaleY = _ref.scaleY, + translateX = _ref.translateX, + translateY = _ref.translateY; + var values = []; + if (isNumber(translateX) && translateX !== 0) { + values.push("translateX(".concat(translateX, "px)")); + } + if (isNumber(translateY) && translateY !== 0) { + values.push("translateY(".concat(translateY, "px)")); + } + + // Rotate should come first before scale to match orientation transform + if (isNumber(rotate) && rotate !== 0) { + values.push("rotate(".concat(rotate, "deg)")); + } + if (isNumber(scaleX) && scaleX !== 1) { + values.push("scaleX(".concat(scaleX, ")")); + } + if (isNumber(scaleY) && scaleY !== 1) { + values.push("scaleY(".concat(scaleY, ")")); + } + var transform = values.length ? values.join(' ') : 'none'; + return { + WebkitTransform: transform, + msTransform: transform, + transform: transform + }; + } + + /** + * Get the max ratio of a group of pointers. + * @param {string} pointers - The target pointers. + * @returns {number} The result ratio. + */ + function getMaxZoomRatio(pointers) { + var pointers2 = _objectSpread2({}, pointers); + var maxRatio = 0; + forEach(pointers, function (pointer, pointerId) { + delete pointers2[pointerId]; + forEach(pointers2, function (pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + if (Math.abs(ratio) > Math.abs(maxRatio)) { + maxRatio = ratio; + } + }); + }); + return maxRatio; + } + + /** + * Get a pointer from an event object. + * @param {Object} event - The target event object. + * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. + * @returns {Object} The result pointer contains start and/or end point coordinates. + */ + function getPointer(_ref2, endOnly) { + var pageX = _ref2.pageX, + pageY = _ref2.pageY; + var end = { + endX: pageX, + endY: pageY + }; + return endOnly ? end : _objectSpread2({ + startX: pageX, + startY: pageY + }, end); + } + + /** + * Get the center point coordinate of a group of pointers. + * @param {Object} pointers - The target pointers. + * @returns {Object} The center point coordinate. + */ + function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; + forEach(pointers, function (_ref3) { + var startX = _ref3.startX, + startY = _ref3.startY; + pageX += startX; + pageY += startY; + count += 1; + }); + pageX /= count; + pageY /= count; + return { + pageX: pageX, + pageY: pageY + }; + } + + /** + * Get the max sizes in a rectangle under the given aspect ratio. + * @param {Object} data - The original sizes. + * @param {string} [type='contain'] - The adjust type. + * @returns {Object} The result sizes. + */ + function getAdjustedSizes(_ref4) { + var aspectRatio = _ref4.aspectRatio, + height = _ref4.height, + width = _ref4.width; + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'contain'; + var isValidWidth = isPositiveNumber(width); + var isValidHeight = isPositiveNumber(height); + if (isValidWidth && isValidHeight) { + var adjustedWidth = height * aspectRatio; + if (type === 'contain' && adjustedWidth > width || type === 'cover' && adjustedWidth < width) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } + } else if (isValidWidth) { + height = width / aspectRatio; + } else if (isValidHeight) { + width = height * aspectRatio; + } + return { + width: width, + height: height + }; + } + + /** + * Get the new sizes of a rectangle after rotated. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ + function getRotatedSizes(_ref5) { + var width = _ref5.width, + height = _ref5.height, + degree = _ref5.degree; + degree = Math.abs(degree) % 180; + if (degree === 90) { + return { + width: height, + height: width + }; + } + var arc = degree % 90 * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + var newWidth = width * cosArc + height * sinArc; + var newHeight = width * sinArc + height * cosArc; + return degree > 90 ? { + width: newHeight, + height: newWidth + } : { + width: newWidth, + height: newHeight + }; + } + + /** + * Get a canvas which drew the given image. + * @param {HTMLImageElement} image - The image for drawing. + * @param {Object} imageData - The image data. + * @param {Object} canvasData - The canvas data. + * @param {Object} options - The options. + * @returns {HTMLCanvasElement} The result canvas. + */ + function getSourceCanvas(image, _ref6, _ref7, _ref8) { + var imageAspectRatio = _ref6.aspectRatio, + imageNaturalWidth = _ref6.naturalWidth, + imageNaturalHeight = _ref6.naturalHeight, + _ref6$rotate = _ref6.rotate, + rotate = _ref6$rotate === void 0 ? 0 : _ref6$rotate, + _ref6$scaleX = _ref6.scaleX, + scaleX = _ref6$scaleX === void 0 ? 1 : _ref6$scaleX, + _ref6$scaleY = _ref6.scaleY, + scaleY = _ref6$scaleY === void 0 ? 1 : _ref6$scaleY; + var aspectRatio = _ref7.aspectRatio, + naturalWidth = _ref7.naturalWidth, + naturalHeight = _ref7.naturalHeight; + var _ref8$fillColor = _ref8.fillColor, + fillColor = _ref8$fillColor === void 0 ? 'transparent' : _ref8$fillColor, + _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled, + imageSmoothingEnabled = _ref8$imageSmoothingE === void 0 ? true : _ref8$imageSmoothingE, + _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality, + imageSmoothingQuality = _ref8$imageSmoothingQ === void 0 ? 'low' : _ref8$imageSmoothingQ, + _ref8$maxWidth = _ref8.maxWidth, + maxWidth = _ref8$maxWidth === void 0 ? Infinity : _ref8$maxWidth, + _ref8$maxHeight = _ref8.maxHeight, + maxHeight = _ref8$maxHeight === void 0 ? Infinity : _ref8$maxHeight, + _ref8$minWidth = _ref8.minWidth, + minWidth = _ref8$minWidth === void 0 ? 0 : _ref8$minWidth, + _ref8$minHeight = _ref8.minHeight, + minHeight = _ref8$minHeight === void 0 ? 0 : _ref8$minHeight; + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var maxSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: maxWidth, + height: maxHeight + }); + var minSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: minWidth, + height: minHeight + }, 'cover'); + var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth)); + var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); + + // Note: should always use image's natural sizes for drawing as + // imageData.naturalWidth === canvasData.naturalHeight when rotate % 180 === 90 + var destMaxSizes = getAdjustedSizes({ + aspectRatio: imageAspectRatio, + width: maxWidth, + height: maxHeight + }); + var destMinSizes = getAdjustedSizes({ + aspectRatio: imageAspectRatio, + width: minWidth, + height: minHeight + }, 'cover'); + var destWidth = Math.min(destMaxSizes.width, Math.max(destMinSizes.width, imageNaturalWidth)); + var destHeight = Math.min(destMaxSizes.height, Math.max(destMinSizes.height, imageNaturalHeight)); + var params = [-destWidth / 2, -destHeight / 2, destWidth, destHeight]; + canvas.width = normalizeDecimalNumber(width); + canvas.height = normalizeDecimalNumber(height); + context.fillStyle = fillColor; + context.fillRect(0, 0, width, height); + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.imageSmoothingEnabled = imageSmoothingEnabled; + context.imageSmoothingQuality = imageSmoothingQuality; + context.drawImage.apply(context, [image].concat(_toConsumableArray(params.map(function (param) { + return Math.floor(normalizeDecimalNumber(param)); + })))); + context.restore(); + return canvas; + } + var fromCharCode = String.fromCharCode; + + /** + * Get string from char code in data view. + * @param {DataView} dataView - The data view for read. + * @param {number} start - The start index. + * @param {number} length - The read length. + * @returns {string} The read result. + */ + function getStringFromCharCode(dataView, start, length) { + var str = ''; + length += start; + for (var i = start; i < length; i += 1) { + str += fromCharCode(dataView.getUint8(i)); + } + return str; + } + var REGEXP_DATA_URL_HEAD = /^data:.*,/; + + /** + * Transform Data URL to array buffer. + * @param {string} dataURL - The Data URL to transform. + * @returns {ArrayBuffer} The result array buffer. + */ + function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var arrayBuffer = new ArrayBuffer(binary.length); + var uint8 = new Uint8Array(arrayBuffer); + forEach(uint8, function (value, i) { + uint8[i] = binary.charCodeAt(i); + }); + return arrayBuffer; + } + + /** + * Transform array buffer to Data URL. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {string} mimeType - The mime type of the Data URL. + * @returns {string} The result Data URL. + */ + function arrayBufferToDataURL(arrayBuffer, mimeType) { + var chunks = []; + + // Chunk Typed Array for better performance (#435) + var chunkSize = 8192; + var uint8 = new Uint8Array(arrayBuffer); + while (uint8.length > 0) { + // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9 + // eslint-disable-next-line prefer-spread + chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize)))); + uint8 = uint8.subarray(chunkSize); + } + return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join(''))); + } + + /** + * Get orientation value from given array buffer. + * @param {ArrayBuffer} arrayBuffer - The array buffer to read. + * @returns {number} The read orientation value. + */ + function resetAndGetOrientation(arrayBuffer) { + var dataView = new DataView(arrayBuffer); + var orientation; + + // Ignores range error when the image does not have correct Exif information + try { + var littleEndian; + var app1Start; + var ifdStart; + + // Only handle JPEG image (start by 0xFFD8) + if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { + var length = dataView.byteLength; + var offset = 2; + while (offset + 1 < length) { + if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { + app1Start = offset; + break; + } + offset += 1; + } + } + if (app1Start) { + var exifIDCode = app1Start + 4; + var tiffOffset = app1Start + 10; + if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { + var endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { + if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { + var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + if (firstIFDOffset >= 0x00000008) { + ifdStart = tiffOffset + firstIFDOffset; + } + } + } + } + } + if (ifdStart) { + var _length = dataView.getUint16(ifdStart, littleEndian); + var _offset; + var i; + for (i = 0; i < _length; i += 1) { + _offset = ifdStart + i * 12 + 2; + if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) { + // 8 is the offset of the current tag's value + _offset += 8; + + // Get the original orientation value + orientation = dataView.getUint16(_offset, littleEndian); + + // Override the orientation with its default value + dataView.setUint16(_offset, 1, littleEndian); + break; + } + } + } + } catch (error) { + orientation = 1; + } + return orientation; + } + + /** + * Parse Exif Orientation value. + * @param {number} orientation - The orientation to parse. + * @returns {Object} The parsed result. + */ + function parseOrientation(orientation) { + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + switch (orientation) { + // Flip horizontal + case 2: + scaleX = -1; + break; + + // Rotate left 180° + case 3: + rotate = -180; + break; + + // Flip vertical + case 4: + scaleY = -1; + break; + + // Flip vertical and rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // Rotate right 90° + case 6: + rotate = 90; + break; + + // Flip horizontal and rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // Rotate left 90° + case 8: + rotate = -90; + break; + } + return { + rotate: rotate, + scaleX: scaleX, + scaleY: scaleY + }; + } + + var render = { + render: function render() { + this.initContainer(); + this.initCanvas(); + this.initCropBox(); + this.renderCanvas(); + if (this.cropped) { + this.renderCropBox(); + } + }, + initContainer: function initContainer() { + var element = this.element, + options = this.options, + container = this.container, + cropper = this.cropper; + var minWidth = Number(options.minContainerWidth); + var minHeight = Number(options.minContainerHeight); + addClass(cropper, CLASS_HIDDEN); + removeClass(element, CLASS_HIDDEN); + var containerData = { + width: Math.max(container.offsetWidth, minWidth >= 0 ? minWidth : MIN_CONTAINER_WIDTH), + height: Math.max(container.offsetHeight, minHeight >= 0 ? minHeight : MIN_CONTAINER_HEIGHT) + }; + this.containerData = containerData; + setStyle(cropper, { + width: containerData.width, + height: containerData.height + }); + addClass(element, CLASS_HIDDEN); + removeClass(cropper, CLASS_HIDDEN); + }, + // Canvas (image wrapper) + initCanvas: function initCanvas() { + var containerData = this.containerData, + imageData = this.imageData; + var viewMode = this.options.viewMode; + var rotated = Math.abs(imageData.rotate) % 180 === 90; + var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth; + var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight; + var aspectRatio = naturalWidth / naturalHeight; + var canvasWidth = containerData.width; + var canvasHeight = containerData.height; + if (containerData.height * aspectRatio > containerData.width) { + if (viewMode === 3) { + canvasWidth = containerData.height * aspectRatio; + } else { + canvasHeight = containerData.width / aspectRatio; + } + } else if (viewMode === 3) { + canvasHeight = containerData.width / aspectRatio; + } else { + canvasWidth = containerData.height * aspectRatio; + } + var canvasData = { + aspectRatio: aspectRatio, + naturalWidth: naturalWidth, + naturalHeight: naturalHeight, + width: canvasWidth, + height: canvasHeight + }; + this.canvasData = canvasData; + this.limited = viewMode === 1 || viewMode === 2; + this.limitCanvas(true, true); + canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); + canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); + canvasData.left = (containerData.width - canvasData.width) / 2; + canvasData.top = (containerData.height - canvasData.height) / 2; + canvasData.oldLeft = canvasData.left; + canvasData.oldTop = canvasData.top; + this.initialCanvasData = assign({}, canvasData); + }, + limitCanvas: function limitCanvas(sizeLimited, positionLimited) { + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var viewMode = options.viewMode; + var aspectRatio = canvasData.aspectRatio; + var cropped = this.cropped && cropBoxData; + if (sizeLimited) { + var minCanvasWidth = Number(options.minCanvasWidth) || 0; + var minCanvasHeight = Number(options.minCanvasHeight) || 0; + if (viewMode > 1) { + minCanvasWidth = Math.max(minCanvasWidth, containerData.width); + minCanvasHeight = Math.max(minCanvasHeight, containerData.height); + if (viewMode === 3) { + if (minCanvasHeight * aspectRatio > minCanvasWidth) { + minCanvasWidth = minCanvasHeight * aspectRatio; + } else { + minCanvasHeight = minCanvasWidth / aspectRatio; + } + } + } else if (viewMode > 0) { + if (minCanvasWidth) { + minCanvasWidth = Math.max(minCanvasWidth, cropped ? cropBoxData.width : 0); + } else if (minCanvasHeight) { + minCanvasHeight = Math.max(minCanvasHeight, cropped ? cropBoxData.height : 0); + } else if (cropped) { + minCanvasWidth = cropBoxData.width; + minCanvasHeight = cropBoxData.height; + if (minCanvasHeight * aspectRatio > minCanvasWidth) { + minCanvasWidth = minCanvasHeight * aspectRatio; + } else { + minCanvasHeight = minCanvasWidth / aspectRatio; + } + } + } + var _getAdjustedSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: minCanvasWidth, + height: minCanvasHeight + }); + minCanvasWidth = _getAdjustedSizes.width; + minCanvasHeight = _getAdjustedSizes.height; + canvasData.minWidth = minCanvasWidth; + canvasData.minHeight = minCanvasHeight; + canvasData.maxWidth = Infinity; + canvasData.maxHeight = Infinity; + } + if (positionLimited) { + if (viewMode > (cropped ? 0 : 1)) { + var newCanvasLeft = containerData.width - canvasData.width; + var newCanvasTop = containerData.height - canvasData.height; + canvasData.minLeft = Math.min(0, newCanvasLeft); + canvasData.minTop = Math.min(0, newCanvasTop); + canvasData.maxLeft = Math.max(0, newCanvasLeft); + canvasData.maxTop = Math.max(0, newCanvasTop); + if (cropped && this.limited) { + canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width)); + canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height)); + canvasData.maxLeft = cropBoxData.left; + canvasData.maxTop = cropBoxData.top; + if (viewMode === 2) { + if (canvasData.width >= containerData.width) { + canvasData.minLeft = Math.min(0, newCanvasLeft); + canvasData.maxLeft = Math.max(0, newCanvasLeft); + } + if (canvasData.height >= containerData.height) { + canvasData.minTop = Math.min(0, newCanvasTop); + canvasData.maxTop = Math.max(0, newCanvasTop); + } + } + } + } else { + canvasData.minLeft = -canvasData.width; + canvasData.minTop = -canvasData.height; + canvasData.maxLeft = containerData.width; + canvasData.maxTop = containerData.height; + } + } + }, + renderCanvas: function renderCanvas(changed, transformed) { + var canvasData = this.canvasData, + imageData = this.imageData; + if (transformed) { + var _getRotatedSizes = getRotatedSizes({ + width: imageData.naturalWidth * Math.abs(imageData.scaleX || 1), + height: imageData.naturalHeight * Math.abs(imageData.scaleY || 1), + degree: imageData.rotate || 0 + }), + naturalWidth = _getRotatedSizes.width, + naturalHeight = _getRotatedSizes.height; + var width = canvasData.width * (naturalWidth / canvasData.naturalWidth); + var height = canvasData.height * (naturalHeight / canvasData.naturalHeight); + canvasData.left -= (width - canvasData.width) / 2; + canvasData.top -= (height - canvasData.height) / 2; + canvasData.width = width; + canvasData.height = height; + canvasData.aspectRatio = naturalWidth / naturalHeight; + canvasData.naturalWidth = naturalWidth; + canvasData.naturalHeight = naturalHeight; + this.limitCanvas(true, false); + } + if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) { + canvasData.left = canvasData.oldLeft; + } + if (canvasData.height > canvasData.maxHeight || canvasData.height < canvasData.minHeight) { + canvasData.top = canvasData.oldTop; + } + canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); + canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); + this.limitCanvas(false, true); + canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft); + canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop); + canvasData.oldLeft = canvasData.left; + canvasData.oldTop = canvasData.top; + setStyle(this.canvas, assign({ + width: canvasData.width, + height: canvasData.height + }, getTransforms({ + translateX: canvasData.left, + translateY: canvasData.top + }))); + this.renderImage(changed); + if (this.cropped && this.limited) { + this.limitCropBox(true, true); + } + }, + renderImage: function renderImage(changed) { + var canvasData = this.canvasData, + imageData = this.imageData; + var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth); + var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight); + assign(imageData, { + width: width, + height: height, + left: (canvasData.width - width) / 2, + top: (canvasData.height - height) / 2 + }); + setStyle(this.image, assign({ + width: imageData.width, + height: imageData.height + }, getTransforms(assign({ + translateX: imageData.left, + translateY: imageData.top + }, imageData)))); + if (changed) { + this.output(); + } + }, + initCropBox: function initCropBox() { + var options = this.options, + canvasData = this.canvasData; + var aspectRatio = options.aspectRatio || options.initialAspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; + var cropBoxData = { + width: canvasData.width, + height: canvasData.height + }; + if (aspectRatio) { + if (canvasData.height * aspectRatio > canvasData.width) { + cropBoxData.height = cropBoxData.width / aspectRatio; + } else { + cropBoxData.width = cropBoxData.height * aspectRatio; + } + } + this.cropBoxData = cropBoxData; + this.limitCropBox(true, true); + + // Initialize auto crop area + cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); + cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); + + // The width/height of auto crop area must large than "minWidth/Height" + cropBoxData.width = Math.max(cropBoxData.minWidth, cropBoxData.width * autoCropArea); + cropBoxData.height = Math.max(cropBoxData.minHeight, cropBoxData.height * autoCropArea); + cropBoxData.left = canvasData.left + (canvasData.width - cropBoxData.width) / 2; + cropBoxData.top = canvasData.top + (canvasData.height - cropBoxData.height) / 2; + cropBoxData.oldLeft = cropBoxData.left; + cropBoxData.oldTop = cropBoxData.top; + this.initialCropBoxData = assign({}, cropBoxData); + }, + limitCropBox: function limitCropBox(sizeLimited, positionLimited) { + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData, + limited = this.limited; + var aspectRatio = options.aspectRatio; + if (sizeLimited) { + var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; + var minCropBoxHeight = Number(options.minCropBoxHeight) || 0; + var maxCropBoxWidth = limited ? Math.min(containerData.width, canvasData.width, canvasData.width + canvasData.left, containerData.width - canvasData.left) : containerData.width; + var maxCropBoxHeight = limited ? Math.min(containerData.height, canvasData.height, canvasData.height + canvasData.top, containerData.height - canvasData.top) : containerData.height; + + // The min/maxCropBoxWidth/Height must be less than container's width/height + minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width); + minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height); + if (aspectRatio) { + if (minCropBoxWidth && minCropBoxHeight) { + if (minCropBoxHeight * aspectRatio > minCropBoxWidth) { + minCropBoxHeight = minCropBoxWidth / aspectRatio; + } else { + minCropBoxWidth = minCropBoxHeight * aspectRatio; + } + } else if (minCropBoxWidth) { + minCropBoxHeight = minCropBoxWidth / aspectRatio; + } else if (minCropBoxHeight) { + minCropBoxWidth = minCropBoxHeight * aspectRatio; + } + if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) { + maxCropBoxHeight = maxCropBoxWidth / aspectRatio; + } else { + maxCropBoxWidth = maxCropBoxHeight * aspectRatio; + } + } + + // The minWidth/Height must be less than maxWidth/Height + cropBoxData.minWidth = Math.min(minCropBoxWidth, maxCropBoxWidth); + cropBoxData.minHeight = Math.min(minCropBoxHeight, maxCropBoxHeight); + cropBoxData.maxWidth = maxCropBoxWidth; + cropBoxData.maxHeight = maxCropBoxHeight; + } + if (positionLimited) { + if (limited) { + cropBoxData.minLeft = Math.max(0, canvasData.left); + cropBoxData.minTop = Math.max(0, canvasData.top); + cropBoxData.maxLeft = Math.min(containerData.width, canvasData.left + canvasData.width) - cropBoxData.width; + cropBoxData.maxTop = Math.min(containerData.height, canvasData.top + canvasData.height) - cropBoxData.height; + } else { + cropBoxData.minLeft = 0; + cropBoxData.minTop = 0; + cropBoxData.maxLeft = containerData.width - cropBoxData.width; + cropBoxData.maxTop = containerData.height - cropBoxData.height; + } + } + }, + renderCropBox: function renderCropBox() { + var options = this.options, + containerData = this.containerData, + cropBoxData = this.cropBoxData; + if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) { + cropBoxData.left = cropBoxData.oldLeft; + } + if (cropBoxData.height > cropBoxData.maxHeight || cropBoxData.height < cropBoxData.minHeight) { + cropBoxData.top = cropBoxData.oldTop; + } + cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); + cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); + this.limitCropBox(false, true); + cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft); + cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop); + cropBoxData.oldLeft = cropBoxData.left; + cropBoxData.oldTop = cropBoxData.top; + if (options.movable && options.cropBoxMovable) { + // Turn to move the canvas when the crop box is equal to the container + setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL); + } + setStyle(this.cropBox, assign({ + width: cropBoxData.width, + height: cropBoxData.height + }, getTransforms({ + translateX: cropBoxData.left, + translateY: cropBoxData.top + }))); + if (this.cropped && this.limited) { + this.limitCanvas(true, true); + } + if (!this.disabled) { + this.output(); + } + }, + output: function output() { + this.preview(); + dispatchEvent(this.element, EVENT_CROP, this.getData()); + } + }; + + var preview = { + initPreview: function initPreview() { + var element = this.element, + crossOrigin = this.crossOrigin; + var preview = this.options.preview; + var url = crossOrigin ? this.crossOriginUrl : this.url; + var alt = element.alt || 'The image to preview'; + var image = document.createElement('img'); + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + image.src = url; + image.alt = alt; + this.viewBox.appendChild(image); + this.viewBoxImage = image; + if (!preview) { + return; + } + var previews = preview; + if (typeof preview === 'string') { + previews = element.ownerDocument.querySelectorAll(preview); + } else if (preview.querySelector) { + previews = [preview]; + } + this.previews = previews; + forEach(previews, function (el) { + var img = document.createElement('img'); + + // Save the original size for recover + setData(el, DATA_PREVIEW, { + width: el.offsetWidth, + height: el.offsetHeight, + html: el.innerHTML + }); + if (crossOrigin) { + img.crossOrigin = crossOrigin; + } + img.src = url; + img.alt = alt; + + /** + * Override img element styles + * Add `display:block` to avoid margin top issue + * Add `height:auto` to override `height` attribute on IE8 + * (Occur only when margin-top <= -height) + */ + img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;"'; + el.innerHTML = ''; + el.appendChild(img); + }); + }, + resetPreview: function resetPreview() { + forEach(this.previews, function (element) { + var data = getData(element, DATA_PREVIEW); + setStyle(element, { + width: data.width, + height: data.height + }); + element.innerHTML = data.html; + removeData(element, DATA_PREVIEW); + }); + }, + preview: function preview() { + var imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var cropBoxWidth = cropBoxData.width, + cropBoxHeight = cropBoxData.height; + var width = imageData.width, + height = imageData.height; + var left = cropBoxData.left - canvasData.left - imageData.left; + var top = cropBoxData.top - canvasData.top - imageData.top; + if (!this.cropped || this.disabled) { + return; + } + setStyle(this.viewBoxImage, assign({ + width: width, + height: height + }, getTransforms(assign({ + translateX: -left, + translateY: -top + }, imageData)))); + forEach(this.previews, function (element) { + var data = getData(element, DATA_PREVIEW); + var originalWidth = data.width; + var originalHeight = data.height; + var newWidth = originalWidth; + var newHeight = originalHeight; + var ratio = 1; + if (cropBoxWidth) { + ratio = originalWidth / cropBoxWidth; + newHeight = cropBoxHeight * ratio; + } + if (cropBoxHeight && newHeight > originalHeight) { + ratio = originalHeight / cropBoxHeight; + newWidth = cropBoxWidth * ratio; + newHeight = originalHeight; + } + setStyle(element, { + width: newWidth, + height: newHeight + }); + setStyle(element.getElementsByTagName('img')[0], assign({ + width: width * ratio, + height: height * ratio + }, getTransforms(assign({ + translateX: -left * ratio, + translateY: -top * ratio + }, imageData)))); + }); + } + }; + + var events = { + bind: function bind() { + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { + addListener(element, EVENT_CROP_START, options.cropstart); + } + if (isFunction(options.cropmove)) { + addListener(element, EVENT_CROP_MOVE, options.cropmove); + } + if (isFunction(options.cropend)) { + addListener(element, EVENT_CROP_END, options.cropend); + } + if (isFunction(options.crop)) { + addListener(element, EVENT_CROP, options.crop); + } + if (isFunction(options.zoom)) { + addListener(element, EVENT_ZOOM, options.zoom); + } + addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = this.cropStart.bind(this)); + if (options.zoomable && options.zoomOnWheel) { + addListener(cropper, EVENT_WHEEL, this.onWheel = this.wheel.bind(this), { + passive: false, + capture: true + }); + } + if (options.toggleDragModeOnDblclick) { + addListener(cropper, EVENT_DBLCLICK, this.onDblclick = this.dblclick.bind(this)); + } + addListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove = this.cropMove.bind(this)); + addListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd = this.cropEnd.bind(this)); + if (options.responsive) { + addListener(window, EVENT_RESIZE, this.onResize = this.resize.bind(this)); + } + }, + unbind: function unbind() { + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { + removeListener(element, EVENT_CROP_START, options.cropstart); + } + if (isFunction(options.cropmove)) { + removeListener(element, EVENT_CROP_MOVE, options.cropmove); + } + if (isFunction(options.cropend)) { + removeListener(element, EVENT_CROP_END, options.cropend); + } + if (isFunction(options.crop)) { + removeListener(element, EVENT_CROP, options.crop); + } + if (isFunction(options.zoom)) { + removeListener(element, EVENT_ZOOM, options.zoom); + } + removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart); + if (options.zoomable && options.zoomOnWheel) { + removeListener(cropper, EVENT_WHEEL, this.onWheel, { + passive: false, + capture: true + }); + } + if (options.toggleDragModeOnDblclick) { + removeListener(cropper, EVENT_DBLCLICK, this.onDblclick); + } + removeListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove); + removeListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd); + if (options.responsive) { + removeListener(window, EVENT_RESIZE, this.onResize); + } + } + }; + + var handlers = { + resize: function resize() { + if (this.disabled) { + return; + } + var options = this.options, + container = this.container, + containerData = this.containerData; + var ratioX = container.offsetWidth / containerData.width; + var ratioY = container.offsetHeight / containerData.height; + var ratio = Math.abs(ratioX - 1) > Math.abs(ratioY - 1) ? ratioX : ratioY; + + // Resize when width changed or height changed + if (ratio !== 1) { + var canvasData; + var cropBoxData; + if (options.restore) { + canvasData = this.getCanvasData(); + cropBoxData = this.getCropBoxData(); + } + this.render(); + if (options.restore) { + this.setCanvasData(forEach(canvasData, function (n, i) { + canvasData[i] = n * ratio; + })); + this.setCropBoxData(forEach(cropBoxData, function (n, i) { + cropBoxData[i] = n * ratio; + })); + } + } + }, + dblclick: function dblclick() { + if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) { + return; + } + this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP); + }, + wheel: function wheel(event) { + var _this = this; + var ratio = Number(this.options.wheelZoomRatio) || 0.1; + var delta = 1; + if (this.disabled) { + return; + } + event.preventDefault(); + + // Limit wheel speed to prevent zoom too fast (#21) + if (this.wheeling) { + return; + } + this.wheeling = true; + setTimeout(function () { + _this.wheeling = false; + }, 50); + if (event.deltaY) { + delta = event.deltaY > 0 ? 1 : -1; + } else if (event.wheelDelta) { + delta = -event.wheelDelta / 120; + } else if (event.detail) { + delta = event.detail > 0 ? 1 : -1; + } + this.zoom(-delta * ratio, event); + }, + cropStart: function cropStart(event) { + var buttons = event.buttons, + button = event.button; + if (this.disabled + + // Handle mouse event and pointer event and ignore touch event + || (event.type === 'mousedown' || event.type === 'pointerdown' && event.pointerType === 'mouse') && ( + // No primary button (Usually the left button) + isNumber(buttons) && buttons !== 1 || isNumber(button) && button !== 0 + + // Open context menu + || event.ctrlKey)) { + return; + } + var options = this.options, + pointers = this.pointers; + var action; + if (event.changedTouches) { + // Handle touch event + forEach(event.changedTouches, function (touch) { + pointers[touch.identifier] = getPointer(touch); + }); + } else { + // Handle mouse event and pointer event + pointers[event.pointerId || 0] = getPointer(event); + } + if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { + action = ACTION_ZOOM; + } else { + action = getData(event.target, DATA_ACTION); + } + if (!REGEXP_ACTIONS.test(action)) { + return; + } + if (dispatchEvent(this.element, EVENT_CROP_START, { + originalEvent: event, + action: action + }) === false) { + return; + } + + // This line is required for preventing page zooming in iOS browsers + event.preventDefault(); + this.action = action; + this.cropping = false; + if (action === ACTION_CROP) { + this.cropping = true; + addClass(this.dragBox, CLASS_MODAL); + } + }, + cropMove: function cropMove(event) { + var action = this.action; + if (this.disabled || !action) { + return; + } + var pointers = this.pointers; + event.preventDefault(); + if (dispatchEvent(this.element, EVENT_CROP_MOVE, { + originalEvent: event, + action: action + }) === false) { + return; + } + if (event.changedTouches) { + forEach(event.changedTouches, function (touch) { + // The first parameter should not be undefined (#432) + assign(pointers[touch.identifier] || {}, getPointer(touch, true)); + }); + } else { + assign(pointers[event.pointerId || 0] || {}, getPointer(event, true)); + } + this.change(event); + }, + cropEnd: function cropEnd(event) { + if (this.disabled) { + return; + } + var action = this.action, + pointers = this.pointers; + if (event.changedTouches) { + forEach(event.changedTouches, function (touch) { + delete pointers[touch.identifier]; + }); + } else { + delete pointers[event.pointerId || 0]; + } + if (!action) { + return; + } + event.preventDefault(); + if (!Object.keys(pointers).length) { + this.action = ''; + } + if (this.cropping) { + this.cropping = false; + toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal); + } + dispatchEvent(this.element, EVENT_CROP_END, { + originalEvent: event, + action: action + }); + } + }; + + var change = { + change: function change(event) { + var options = this.options, + canvasData = this.canvasData, + containerData = this.containerData, + cropBoxData = this.cropBoxData, + pointers = this.pointers; + var action = this.action; + var aspectRatio = options.aspectRatio; + var left = cropBoxData.left, + top = cropBoxData.top, + width = cropBoxData.width, + height = cropBoxData.height; + var right = left + width; + var bottom = top + height; + var minLeft = 0; + var minTop = 0; + var maxWidth = containerData.width; + var maxHeight = containerData.height; + var renderable = true; + var offset; + + // Locking aspect ratio in "free mode" by holding shift key + if (!aspectRatio && event.shiftKey) { + aspectRatio = width && height ? width / height : 1; + } + if (this.limited) { + minLeft = cropBoxData.minLeft; + minTop = cropBoxData.minTop; + maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width); + maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height); + } + var pointer = pointers[Object.keys(pointers)[0]]; + var range = { + x: pointer.endX - pointer.startX, + y: pointer.endY - pointer.startY + }; + var check = function check(side) { + switch (side) { + case ACTION_EAST: + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + break; + case ACTION_WEST: + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + break; + case ACTION_NORTH: + if (top + range.y < minTop) { + range.y = minTop - top; + } + break; + case ACTION_SOUTH: + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + break; + } + }; + switch (action) { + // Move crop box + case ACTION_ALL: + left += range.x; + top += range.y; + break; + + // Resize crop box + case ACTION_EAST: + if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= minTop || bottom >= maxHeight))) { + renderable = false; + break; + } + check(ACTION_EAST); + width += range.x; + if (width < 0) { + action = ACTION_WEST; + width = -width; + left -= width; + } + if (aspectRatio) { + height = width / aspectRatio; + top += (cropBoxData.height - height) / 2; + } + break; + case ACTION_NORTH: + if (range.y <= 0 && (top <= minTop || aspectRatio && (left <= minLeft || right >= maxWidth))) { + renderable = false; + break; + } + check(ACTION_NORTH); + height -= range.y; + top += range.y; + if (height < 0) { + action = ACTION_SOUTH; + height = -height; + top -= height; + } + if (aspectRatio) { + width = height * aspectRatio; + left += (cropBoxData.width - width) / 2; + } + break; + case ACTION_WEST: + if (range.x <= 0 && (left <= minLeft || aspectRatio && (top <= minTop || bottom >= maxHeight))) { + renderable = false; + break; + } + check(ACTION_WEST); + width -= range.x; + left += range.x; + if (width < 0) { + action = ACTION_EAST; + width = -width; + left -= width; + } + if (aspectRatio) { + height = width / aspectRatio; + top += (cropBoxData.height - height) / 2; + } + break; + case ACTION_SOUTH: + if (range.y >= 0 && (bottom >= maxHeight || aspectRatio && (left <= minLeft || right >= maxWidth))) { + renderable = false; + break; + } + check(ACTION_SOUTH); + height += range.y; + if (height < 0) { + action = ACTION_NORTH; + height = -height; + top -= height; + } + if (aspectRatio) { + width = height * aspectRatio; + left += (cropBoxData.width - width) / 2; + } + break; + case ACTION_NORTH_EAST: + if (aspectRatio) { + if (range.y <= 0 && (top <= minTop || right >= maxWidth)) { + renderable = false; + break; + } + check(ACTION_NORTH); + height -= range.y; + top += range.y; + width = height * aspectRatio; + } else { + check(ACTION_NORTH); + check(ACTION_EAST); + if (range.x >= 0) { + if (right < maxWidth) { + width += range.x; + } else if (range.y <= 0 && top <= minTop) { + renderable = false; + } + } else { + width += range.x; + } + if (range.y <= 0) { + if (top > minTop) { + height -= range.y; + top += range.y; + } + } else { + height -= range.y; + top += range.y; + } + } + if (width < 0 && height < 0) { + action = ACTION_SOUTH_WEST; + height = -height; + width = -width; + top -= height; + left -= width; + } else if (width < 0) { + action = ACTION_NORTH_WEST; + width = -width; + left -= width; + } else if (height < 0) { + action = ACTION_SOUTH_EAST; + height = -height; + top -= height; + } + break; + case ACTION_NORTH_WEST: + if (aspectRatio) { + if (range.y <= 0 && (top <= minTop || left <= minLeft)) { + renderable = false; + break; + } + check(ACTION_NORTH); + height -= range.y; + top += range.y; + width = height * aspectRatio; + left += cropBoxData.width - width; + } else { + check(ACTION_NORTH); + check(ACTION_WEST); + if (range.x <= 0) { + if (left > minLeft) { + width -= range.x; + left += range.x; + } else if (range.y <= 0 && top <= minTop) { + renderable = false; + } + } else { + width -= range.x; + left += range.x; + } + if (range.y <= 0) { + if (top > minTop) { + height -= range.y; + top += range.y; + } + } else { + height -= range.y; + top += range.y; + } + } + if (width < 0 && height < 0) { + action = ACTION_SOUTH_EAST; + height = -height; + width = -width; + top -= height; + left -= width; + } else if (width < 0) { + action = ACTION_NORTH_EAST; + width = -width; + left -= width; + } else if (height < 0) { + action = ACTION_SOUTH_WEST; + height = -height; + top -= height; + } + break; + case ACTION_SOUTH_WEST: + if (aspectRatio) { + if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) { + renderable = false; + break; + } + check(ACTION_WEST); + width -= range.x; + left += range.x; + height = width / aspectRatio; + } else { + check(ACTION_SOUTH); + check(ACTION_WEST); + if (range.x <= 0) { + if (left > minLeft) { + width -= range.x; + left += range.x; + } else if (range.y >= 0 && bottom >= maxHeight) { + renderable = false; + } + } else { + width -= range.x; + left += range.x; + } + if (range.y >= 0) { + if (bottom < maxHeight) { + height += range.y; + } + } else { + height += range.y; + } + } + if (width < 0 && height < 0) { + action = ACTION_NORTH_EAST; + height = -height; + width = -width; + top -= height; + left -= width; + } else if (width < 0) { + action = ACTION_SOUTH_EAST; + width = -width; + left -= width; + } else if (height < 0) { + action = ACTION_NORTH_WEST; + height = -height; + top -= height; + } + break; + case ACTION_SOUTH_EAST: + if (aspectRatio) { + if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) { + renderable = false; + break; + } + check(ACTION_EAST); + width += range.x; + height = width / aspectRatio; + } else { + check(ACTION_SOUTH); + check(ACTION_EAST); + if (range.x >= 0) { + if (right < maxWidth) { + width += range.x; + } else if (range.y >= 0 && bottom >= maxHeight) { + renderable = false; + } + } else { + width += range.x; + } + if (range.y >= 0) { + if (bottom < maxHeight) { + height += range.y; + } + } else { + height += range.y; + } + } + if (width < 0 && height < 0) { + action = ACTION_NORTH_WEST; + height = -height; + width = -width; + top -= height; + left -= width; + } else if (width < 0) { + action = ACTION_SOUTH_WEST; + width = -width; + left -= width; + } else if (height < 0) { + action = ACTION_NORTH_EAST; + height = -height; + top -= height; + } + break; + + // Move canvas + case ACTION_MOVE: + this.move(range.x, range.y); + renderable = false; + break; + + // Zoom canvas + case ACTION_ZOOM: + this.zoom(getMaxZoomRatio(pointers), event); + renderable = false; + break; + + // Create crop box + case ACTION_CROP: + if (!range.x || !range.y) { + renderable = false; + break; + } + offset = getOffset(this.cropper); + left = pointer.startX - offset.left; + top = pointer.startY - offset.top; + width = cropBoxData.minWidth; + height = cropBoxData.minHeight; + if (range.x > 0) { + action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST; + } else if (range.x < 0) { + left -= width; + action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST; + } + if (range.y < 0) { + top -= height; + } + + // Show the crop box if is hidden + if (!this.cropped) { + removeClass(this.cropBox, CLASS_HIDDEN); + this.cropped = true; + if (this.limited) { + this.limitCropBox(true, true); + } + } + break; + } + if (renderable) { + cropBoxData.width = width; + cropBoxData.height = height; + cropBoxData.left = left; + cropBoxData.top = top; + this.action = action; + this.renderCropBox(); + } + + // Override + forEach(pointers, function (p) { + p.startX = p.endX; + p.startY = p.endY; + }); + } + }; + + var methods = { + // Show the crop box manually + crop: function crop() { + if (this.ready && !this.cropped && !this.disabled) { + this.cropped = true; + this.limitCropBox(true, true); + if (this.options.modal) { + addClass(this.dragBox, CLASS_MODAL); + } + removeClass(this.cropBox, CLASS_HIDDEN); + this.setCropBoxData(this.initialCropBoxData); + } + return this; + }, + // Reset the image and crop box to their initial states + reset: function reset() { + if (this.ready && !this.disabled) { + this.imageData = assign({}, this.initialImageData); + this.canvasData = assign({}, this.initialCanvasData); + this.cropBoxData = assign({}, this.initialCropBoxData); + this.renderCanvas(); + if (this.cropped) { + this.renderCropBox(); + } + } + return this; + }, + // Clear the crop box + clear: function clear() { + if (this.cropped && !this.disabled) { + assign(this.cropBoxData, { + left: 0, + top: 0, + width: 0, + height: 0 + }); + this.cropped = false; + this.renderCropBox(); + this.limitCanvas(true, true); + + // Render canvas after crop box rendered + this.renderCanvas(); + removeClass(this.dragBox, CLASS_MODAL); + addClass(this.cropBox, CLASS_HIDDEN); + } + return this; + }, + /** + * Replace the image's src and rebuild the cropper + * @param {string} url - The new URL. + * @param {boolean} [hasSameSize] - Indicate if the new image has the same size as the old one. + * @returns {Cropper} this + */ + replace: function replace(url) { + var hasSameSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (!this.disabled && url) { + if (this.isImg) { + this.element.src = url; + } + if (hasSameSize) { + this.url = url; + this.image.src = url; + if (this.ready) { + this.viewBoxImage.src = url; + forEach(this.previews, function (element) { + element.getElementsByTagName('img')[0].src = url; + }); + } + } else { + if (this.isImg) { + this.replaced = true; + } + this.options.data = null; + this.uncreate(); + this.load(url); + } + } + return this; + }, + // Enable (unfreeze) the cropper + enable: function enable() { + if (this.ready && this.disabled) { + this.disabled = false; + removeClass(this.cropper, CLASS_DISABLED); + } + return this; + }, + // Disable (freeze) the cropper + disable: function disable() { + if (this.ready && !this.disabled) { + this.disabled = true; + addClass(this.cropper, CLASS_DISABLED); + } + return this; + }, + /** + * Destroy the cropper and remove the instance from the image + * @returns {Cropper} this + */ + destroy: function destroy() { + var element = this.element; + if (!element[NAMESPACE]) { + return this; + } + element[NAMESPACE] = undefined; + if (this.isImg && this.replaced) { + element.src = this.originalUrl; + } + this.uncreate(); + return this; + }, + /** + * Move the canvas with relative offsets + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} [offsetY=offsetX] - The relative offset distance on the y-axis. + * @returns {Cropper} this + */ + move: function move(offsetX) { + var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : offsetX; + var _this$canvasData = this.canvasData, + left = _this$canvasData.left, + top = _this$canvasData.top; + return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY)); + }, + /** + * Move the canvas to an absolute point + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Cropper} this + */ + moveTo: function moveTo(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var canvasData = this.canvasData; + var changed = false; + x = Number(x); + y = Number(y); + if (this.ready && !this.disabled && this.options.movable) { + if (isNumber(x)) { + canvasData.left = x; + changed = true; + } + if (isNumber(y)) { + canvasData.top = y; + changed = true; + } + if (changed) { + this.renderCanvas(true); + } + } + return this; + }, + /** + * Zoom the canvas with a relative ratio + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Cropper} this + */ + zoom: function zoom(ratio, _originalEvent) { + var canvasData = this.canvasData; + ratio = Number(ratio); + if (ratio < 0) { + ratio = 1 / (1 - ratio); + } else { + ratio = 1 + ratio; + } + return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, null, _originalEvent); + }, + /** + * Zoom the canvas to an absolute ratio + * @param {number} ratio - The target ratio. + * @param {Object} pivot - The zoom pivot point coordinate. + * @param {Event} _originalEvent - The original event if any. + * @returns {Cropper} this + */ + zoomTo: function zoomTo(ratio, pivot, _originalEvent) { + var options = this.options, + canvasData = this.canvasData; + var width = canvasData.width, + height = canvasData.height, + naturalWidth = canvasData.naturalWidth, + naturalHeight = canvasData.naturalHeight; + ratio = Number(ratio); + if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) { + var newWidth = naturalWidth * ratio; + var newHeight = naturalHeight * ratio; + if (dispatchEvent(this.element, EVENT_ZOOM, { + ratio: ratio, + oldRatio: width / naturalWidth, + originalEvent: _originalEvent + }) === false) { + return this; + } + if (_originalEvent) { + var pointers = this.pointers; + var offset = getOffset(this.cropper); + var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : { + pageX: _originalEvent.pageX, + pageY: _originalEvent.pageY + }; + + // Zoom from the triggering point of the event + canvasData.left -= (newWidth - width) * ((center.pageX - offset.left - canvasData.left) / width); + canvasData.top -= (newHeight - height) * ((center.pageY - offset.top - canvasData.top) / height); + } else if (isPlainObject(pivot) && isNumber(pivot.x) && isNumber(pivot.y)) { + canvasData.left -= (newWidth - width) * ((pivot.x - canvasData.left) / width); + canvasData.top -= (newHeight - height) * ((pivot.y - canvasData.top) / height); + } else { + // Zoom from the center of the canvas + canvasData.left -= (newWidth - width) / 2; + canvasData.top -= (newHeight - height) / 2; + } + canvasData.width = newWidth; + canvasData.height = newHeight; + this.renderCanvas(true); + } + return this; + }, + /** + * Rotate the canvas with a relative degree + * @param {number} degree - The rotate degree. + * @returns {Cropper} this + */ + rotate: function rotate(degree) { + return this.rotateTo((this.imageData.rotate || 0) + Number(degree)); + }, + /** + * Rotate the canvas to an absolute degree + * @param {number} degree - The rotate degree. + * @returns {Cropper} this + */ + rotateTo: function rotateTo(degree) { + degree = Number(degree); + if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) { + this.imageData.rotate = degree % 360; + this.renderCanvas(true, true); + } + return this; + }, + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Cropper} this + */ + scaleX: function scaleX(_scaleX) { + var scaleY = this.imageData.scaleY; + return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Cropper} this + */ + scaleY: function scaleY(_scaleY) { + var scaleX = this.imageData.scaleX; + return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + }, + /** + * Scale the image + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Cropper} this + */ + scale: function scale(scaleX) { + var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX; + var imageData = this.imageData; + var transformed = false; + scaleX = Number(scaleX); + scaleY = Number(scaleY); + if (this.ready && !this.disabled && this.options.scalable) { + if (isNumber(scaleX)) { + imageData.scaleX = scaleX; + transformed = true; + } + if (isNumber(scaleY)) { + imageData.scaleY = scaleY; + transformed = true; + } + if (transformed) { + this.renderCanvas(true, true); + } + } + return this; + }, + /** + * Get the cropped area position and size data (base on the original image) + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. + */ + getData: function getData() { + var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var data; + if (this.ready && this.cropped) { + data = { + x: cropBoxData.left - canvasData.left, + y: cropBoxData.top - canvasData.top, + width: cropBoxData.width, + height: cropBoxData.height + }; + var ratio = imageData.width / imageData.naturalWidth; + forEach(data, function (n, i) { + data[i] = n / ratio; + }); + if (rounded) { + // In case rounding off leads to extra 1px in right or bottom border + // we should round the top-left corner and the dimension (#343). + var bottom = Math.round(data.y + data.height); + var right = Math.round(data.x + data.width); + data.x = Math.round(data.x); + data.y = Math.round(data.y); + data.width = right - data.x; + data.height = bottom - data.y; + } + } else { + data = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + } + if (options.rotatable) { + data.rotate = imageData.rotate || 0; + } + if (options.scalable) { + data.scaleX = imageData.scaleX || 1; + data.scaleY = imageData.scaleY || 1; + } + return data; + }, + /** + * Set the cropped area position and size with new data + * @param {Object} data - The new data. + * @returns {Cropper} this + */ + setData: function setData(data) { + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData; + var cropBoxData = {}; + if (this.ready && !this.disabled && isPlainObject(data)) { + var transformed = false; + if (options.rotatable) { + if (isNumber(data.rotate) && data.rotate !== imageData.rotate) { + imageData.rotate = data.rotate; + transformed = true; + } + } + if (options.scalable) { + if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) { + imageData.scaleX = data.scaleX; + transformed = true; + } + if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) { + imageData.scaleY = data.scaleY; + transformed = true; + } + } + if (transformed) { + this.renderCanvas(true, true); + } + var ratio = imageData.width / imageData.naturalWidth; + if (isNumber(data.x)) { + cropBoxData.left = data.x * ratio + canvasData.left; + } + if (isNumber(data.y)) { + cropBoxData.top = data.y * ratio + canvasData.top; + } + if (isNumber(data.width)) { + cropBoxData.width = data.width * ratio; + } + if (isNumber(data.height)) { + cropBoxData.height = data.height * ratio; + } + this.setCropBoxData(cropBoxData); + } + return this; + }, + /** + * Get the container size data. + * @returns {Object} The result container data. + */ + getContainerData: function getContainerData() { + return this.ready ? assign({}, this.containerData) : {}; + }, + /** + * Get the image position and size data. + * @returns {Object} The result image data. + */ + getImageData: function getImageData() { + return this.sized ? assign({}, this.imageData) : {}; + }, + /** + * Get the canvas position and size data. + * @returns {Object} The result canvas data. + */ + getCanvasData: function getCanvasData() { + var canvasData = this.canvasData; + var data = {}; + if (this.ready) { + forEach(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) { + data[n] = canvasData[n]; + }); + } + return data; + }, + /** + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Cropper} this + */ + setCanvasData: function setCanvasData(data) { + var canvasData = this.canvasData; + var aspectRatio = canvasData.aspectRatio; + if (this.ready && !this.disabled && isPlainObject(data)) { + if (isNumber(data.left)) { + canvasData.left = data.left; + } + if (isNumber(data.top)) { + canvasData.top = data.top; + } + if (isNumber(data.width)) { + canvasData.width = data.width; + canvasData.height = data.width / aspectRatio; + } else if (isNumber(data.height)) { + canvasData.height = data.height; + canvasData.width = data.height * aspectRatio; + } + this.renderCanvas(true); + } + return this; + }, + /** + * Get the crop box position and size data. + * @returns {Object} The result crop box data. + */ + getCropBoxData: function getCropBoxData() { + var cropBoxData = this.cropBoxData; + var data; + if (this.ready && this.cropped) { + data = { + left: cropBoxData.left, + top: cropBoxData.top, + width: cropBoxData.width, + height: cropBoxData.height + }; + } + return data || {}; + }, + /** + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Cropper} this + */ + setCropBoxData: function setCropBoxData(data) { + var cropBoxData = this.cropBoxData; + var aspectRatio = this.options.aspectRatio; + var widthChanged; + var heightChanged; + if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) { + if (isNumber(data.left)) { + cropBoxData.left = data.left; + } + if (isNumber(data.top)) { + cropBoxData.top = data.top; + } + if (isNumber(data.width) && data.width !== cropBoxData.width) { + widthChanged = true; + cropBoxData.width = data.width; + } + if (isNumber(data.height) && data.height !== cropBoxData.height) { + heightChanged = true; + cropBoxData.height = data.height; + } + if (aspectRatio) { + if (widthChanged) { + cropBoxData.height = cropBoxData.width / aspectRatio; + } else if (heightChanged) { + cropBoxData.width = cropBoxData.height * aspectRatio; + } + } + this.renderCropBox(); + } + return this; + }, + /** + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. + */ + getCroppedCanvas: function getCroppedCanvas() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + if (!this.ready || !window.HTMLCanvasElement) { + return null; + } + var canvasData = this.canvasData; + var source = getSourceCanvas(this.image, this.imageData, canvasData, options); + + // Returns the source canvas if it is not cropped. + if (!this.cropped) { + return source; + } + var _this$getData = this.getData(options.rounded), + initialX = _this$getData.x, + initialY = _this$getData.y, + initialWidth = _this$getData.width, + initialHeight = _this$getData.height; + var ratio = source.width / Math.floor(canvasData.naturalWidth); + if (ratio !== 1) { + initialX *= ratio; + initialY *= ratio; + initialWidth *= ratio; + initialHeight *= ratio; + } + var aspectRatio = initialWidth / initialHeight; + var maxSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: options.maxWidth || Infinity, + height: options.maxHeight || Infinity + }); + var minSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: options.minWidth || 0, + height: options.minHeight || 0 + }, 'cover'); + var _getAdjustedSizes = getAdjustedSizes({ + aspectRatio: aspectRatio, + width: options.width || (ratio !== 1 ? source.width : initialWidth), + height: options.height || (ratio !== 1 ? source.height : initialHeight) + }), + width = _getAdjustedSizes.width, + height = _getAdjustedSizes.height; + width = Math.min(maxSizes.width, Math.max(minSizes.width, width)); + height = Math.min(maxSizes.height, Math.max(minSizes.height, height)); + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + canvas.width = normalizeDecimalNumber(width); + canvas.height = normalizeDecimalNumber(height); + context.fillStyle = options.fillColor || 'transparent'; + context.fillRect(0, 0, width, height); + var _options$imageSmoothi = options.imageSmoothingEnabled, + imageSmoothingEnabled = _options$imageSmoothi === void 0 ? true : _options$imageSmoothi, + imageSmoothingQuality = options.imageSmoothingQuality; + context.imageSmoothingEnabled = imageSmoothingEnabled; + if (imageSmoothingQuality) { + context.imageSmoothingQuality = imageSmoothingQuality; + } + + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage + var sourceWidth = source.width; + var sourceHeight = source.height; + + // Source canvas parameters + var srcX = initialX; + var srcY = initialY; + var srcWidth; + var srcHeight; + + // Destination canvas parameters + var dstX; + var dstY; + var dstWidth; + var dstHeight; + if (srcX <= -initialWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + srcWidth = Math.min(sourceWidth, initialWidth + srcX); + dstWidth = srcWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + srcWidth = Math.min(initialWidth, sourceWidth - srcX); + dstWidth = srcWidth; + } + if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + srcHeight = Math.min(sourceHeight, initialHeight + srcY); + dstHeight = srcHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + srcHeight = Math.min(initialHeight, sourceHeight - srcY); + dstHeight = srcHeight; + } + var params = [srcX, srcY, srcWidth, srcHeight]; + + // Avoid "IndexSizeError" + if (dstWidth > 0 && dstHeight > 0) { + var scale = width / initialWidth; + params.push(dstX * scale, dstY * scale, dstWidth * scale, dstHeight * scale); + } + + // All the numerical parameters should be integer for `drawImage` + // https://github.com/fengyuanchen/cropper/issues/476 + context.drawImage.apply(context, [source].concat(_toConsumableArray(params.map(function (param) { + return Math.floor(normalizeDecimalNumber(param)); + })))); + return canvas; + }, + /** + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Cropper} this + */ + setAspectRatio: function setAspectRatio(aspectRatio) { + var options = this.options; + if (!this.disabled && !isUndefined(aspectRatio)) { + // 0 -> NaN + options.aspectRatio = Math.max(0, aspectRatio) || NaN; + if (this.ready) { + this.initCropBox(); + if (this.cropped) { + this.renderCropBox(); + } + } + } + return this; + }, + /** + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Cropper} this + */ + setDragMode: function setDragMode(mode) { + var options = this.options, + dragBox = this.dragBox, + face = this.face; + if (this.ready && !this.disabled) { + var croppable = mode === DRAG_MODE_CROP; + var movable = options.movable && mode === DRAG_MODE_MOVE; + mode = croppable || movable ? mode : DRAG_MODE_NONE; + options.dragMode = mode; + setData(dragBox, DATA_ACTION, mode); + toggleClass(dragBox, CLASS_CROP, croppable); + toggleClass(dragBox, CLASS_MOVE, movable); + if (!options.cropBoxMovable) { + // Sync drag mode to crop box when it is not movable + setData(face, DATA_ACTION, mode); + toggleClass(face, CLASS_CROP, croppable); + toggleClass(face, CLASS_MOVE, movable); + } + } + return this; + } + }; + + var AnotherCropper = WINDOW.Cropper; + var Cropper = /*#__PURE__*/function () { + /** + * Create a new Cropper. + * @param {Element} element - The target element for cropping. + * @param {Object} [options={}] - The configuration options. + */ + function Cropper(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Cropper); + if (!element || !REGEXP_TAG_NAME.test(element.tagName)) { + throw new Error('The first argument is required and must be an or element.'); + } + this.element = element; + this.options = assign({}, DEFAULTS, isPlainObject(options) && options); + this.cropped = false; + this.disabled = false; + this.pointers = {}; + this.ready = false; + this.reloading = false; + this.replaced = false; + this.sized = false; + this.sizing = false; + this.init(); + } + return _createClass(Cropper, [{ + key: "init", + value: function init() { + var element = this.element; + var tagName = element.tagName.toLowerCase(); + var url; + if (element[NAMESPACE]) { + return; + } + element[NAMESPACE] = this; + if (tagName === 'img') { + this.isImg = true; + + // e.g.: "img/picture.jpg" + url = element.getAttribute('src') || ''; + this.originalUrl = url; + + // Stop when it's a blank image + if (!url) { + return; + } + + // e.g.: "https://example.com/img/picture.jpg" + url = element.src; + } else if (tagName === 'canvas' && window.HTMLCanvasElement) { + url = element.toDataURL(); + } + this.load(url); + } + }, { + key: "load", + value: function load(url) { + var _this = this; + if (!url) { + return; + } + this.url = url; + this.imageData = {}; + var element = this.element, + options = this.options; + if (!options.rotatable && !options.scalable) { + options.checkOrientation = false; + } + + // Only IE10+ supports Typed Arrays + if (!options.checkOrientation || !window.ArrayBuffer) { + this.clone(); + return; + } + + // Detect the mime type of the image directly if it is a Data URL + if (REGEXP_DATA_URL.test(url)) { + // Read ArrayBuffer from Data URL of JPEG images directly for better performance + if (REGEXP_DATA_URL_JPEG.test(url)) { + this.read(dataURLToArrayBuffer(url)); + } else { + // Only a JPEG image may contains Exif Orientation information, + // the rest types of Data URLs are not necessary to check orientation at all. + this.clone(); + } + return; + } + + // 1. Detect the mime type of the image by a XMLHttpRequest. + // 2. Load the image as ArrayBuffer for reading orientation if its a JPEG image. + var xhr = new XMLHttpRequest(); + var clone = this.clone.bind(this); + this.reloading = true; + this.xhr = xhr; + + // 1. Cross origin requests are only supported for protocol schemes: + // http, https, data, chrome, chrome-extension. + // 2. Access to XMLHttpRequest from a Data URL will be blocked by CORS policy + // in some browsers as IE11 and Safari. + xhr.onabort = clone; + xhr.onerror = clone; + xhr.ontimeout = clone; + xhr.onprogress = function () { + // Abort the request directly if it not a JPEG image for better performance + if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) { + xhr.abort(); + } + }; + xhr.onload = function () { + _this.read(xhr.response); + }; + xhr.onloadend = function () { + _this.reloading = false; + _this.xhr = null; + }; + + // Bust cache when there is a "crossOrigin" property to avoid browser cache error + if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) { + url = addTimestamp(url); + } + + // The third parameter is required for avoiding side-effect (#682) + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.withCredentials = element.crossOrigin === 'use-credentials'; + xhr.send(); + } + }, { + key: "read", + value: function read(arrayBuffer) { + var options = this.options, + imageData = this.imageData; + + // Reset the orientation value to its default value 1 + // as some iOS browsers will render image with its orientation + var orientation = resetAndGetOrientation(arrayBuffer); + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + if (orientation > 1) { + // Generate a new URL which has the default orientation value + this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG); + var _parseOrientation = parseOrientation(orientation); + rotate = _parseOrientation.rotate; + scaleX = _parseOrientation.scaleX; + scaleY = _parseOrientation.scaleY; + } + if (options.rotatable) { + imageData.rotate = rotate; + } + if (options.scalable) { + imageData.scaleX = scaleX; + imageData.scaleY = scaleY; + } + this.clone(); + } + }, { + key: "clone", + value: function clone() { + var element = this.element, + url = this.url; + var crossOrigin = element.crossOrigin; + var crossOriginUrl = url; + if (this.options.checkCrossOrigin && isCrossOriginURL(url)) { + if (!crossOrigin) { + crossOrigin = 'anonymous'; + } + + // Bust cache when there is not a "crossOrigin" property (#519) + crossOriginUrl = addTimestamp(url); + } + this.crossOrigin = crossOrigin; + this.crossOriginUrl = crossOriginUrl; + var image = document.createElement('img'); + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + image.src = crossOriginUrl || url; + image.alt = element.alt || 'The image to crop'; + this.image = image; + image.onload = this.start.bind(this); + image.onerror = this.stop.bind(this); + addClass(image, CLASS_HIDE); + element.parentNode.insertBefore(image, element.nextSibling); + } + }, { + key: "start", + value: function start() { + var _this2 = this; + var image = this.image; + image.onload = null; + image.onerror = null; + this.sizing = true; + + // Match all browsers that use WebKit as the layout engine in iOS devices, + // such as Safari for iOS, Chrome for iOS, and in-app browsers. + var isIOSWebKit = WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent); + var done = function done(naturalWidth, naturalHeight) { + assign(_this2.imageData, { + naturalWidth: naturalWidth, + naturalHeight: naturalHeight, + aspectRatio: naturalWidth / naturalHeight + }); + _this2.initialImageData = assign({}, _this2.imageData); + _this2.sizing = false; + _this2.sized = true; + _this2.build(); + }; + + // Most modern browsers (excepts iOS WebKit) + if (image.naturalWidth && !isIOSWebKit) { + done(image.naturalWidth, image.naturalHeight); + return; + } + var sizingImage = document.createElement('img'); + var body = document.body || document.documentElement; + this.sizingImage = sizingImage; + sizingImage.onload = function () { + done(sizingImage.width, sizingImage.height); + if (!isIOSWebKit) { + body.removeChild(sizingImage); + } + }; + sizingImage.src = image.src; + + // iOS WebKit will convert the image automatically + // with its orientation once append it into DOM (#279) + if (!isIOSWebKit) { + sizingImage.style.cssText = 'left:0;' + 'max-height:none!important;' + 'max-width:none!important;' + 'min-height:0!important;' + 'min-width:0!important;' + 'opacity:0;' + 'position:absolute;' + 'top:0;' + 'z-index:-1;'; + body.appendChild(sizingImage); + } + } + }, { + key: "stop", + value: function stop() { + var image = this.image; + image.onload = null; + image.onerror = null; + image.parentNode.removeChild(image); + this.image = null; + } + }, { + key: "build", + value: function build() { + if (!this.sized || this.ready) { + return; + } + var element = this.element, + options = this.options, + image = this.image; + + // Create cropper elements + var container = element.parentNode; + var template = document.createElement('div'); + template.innerHTML = TEMPLATE; + var cropper = template.querySelector(".".concat(NAMESPACE, "-container")); + var canvas = cropper.querySelector(".".concat(NAMESPACE, "-canvas")); + var dragBox = cropper.querySelector(".".concat(NAMESPACE, "-drag-box")); + var cropBox = cropper.querySelector(".".concat(NAMESPACE, "-crop-box")); + var face = cropBox.querySelector(".".concat(NAMESPACE, "-face")); + this.container = container; + this.cropper = cropper; + this.canvas = canvas; + this.dragBox = dragBox; + this.cropBox = cropBox; + this.viewBox = cropper.querySelector(".".concat(NAMESPACE, "-view-box")); + this.face = face; + canvas.appendChild(image); + + // Hide the original image + addClass(element, CLASS_HIDDEN); + + // Inserts the cropper after to the current image + container.insertBefore(cropper, element.nextSibling); + + // Show the hidden image + removeClass(image, CLASS_HIDE); + this.initPreview(); + this.bind(); + options.initialAspectRatio = Math.max(0, options.initialAspectRatio) || NaN; + options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; + options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; + addClass(cropBox, CLASS_HIDDEN); + if (!options.guides) { + addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-dashed")), CLASS_HIDDEN); + } + if (!options.center) { + addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-center")), CLASS_HIDDEN); + } + if (options.background) { + addClass(cropper, "".concat(NAMESPACE, "-bg")); + } + if (!options.highlight) { + addClass(face, CLASS_INVISIBLE); + } + if (options.cropBoxMovable) { + addClass(face, CLASS_MOVE); + setData(face, DATA_ACTION, ACTION_ALL); + } + if (!options.cropBoxResizable) { + addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-line")), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-point")), CLASS_HIDDEN); + } + this.render(); + this.ready = true; + this.setDragMode(options.dragMode); + if (options.autoCrop) { + this.crop(); + } + this.setData(options.data); + if (isFunction(options.ready)) { + addListener(element, EVENT_READY, options.ready, { + once: true + }); + } + dispatchEvent(element, EVENT_READY); + } + }, { + key: "unbuild", + value: function unbuild() { + if (!this.ready) { + return; + } + this.ready = false; + this.unbind(); + this.resetPreview(); + var parentNode = this.cropper.parentNode; + if (parentNode) { + parentNode.removeChild(this.cropper); + } + removeClass(this.element, CLASS_HIDDEN); + } + }, { + key: "uncreate", + value: function uncreate() { + if (this.ready) { + this.unbuild(); + this.ready = false; + this.cropped = false; + } else if (this.sizing) { + this.sizingImage.onload = null; + this.sizing = false; + this.sized = false; + } else if (this.reloading) { + this.xhr.onabort = null; + this.xhr.abort(); + } else if (this.image) { + this.stop(); + } + } + + /** + * Get the no conflict cropper class. + * @returns {Cropper} The cropper class. + */ + }], [{ + key: "noConflict", + value: function noConflict() { + window.Cropper = AnotherCropper; + return Cropper; + } + + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + }, { + key: "setDefaults", + value: function setDefaults(options) { + assign(DEFAULTS, isPlainObject(options) && options); + } + }]); + }(); + assign(Cropper.prototype, render, preview, events, handlers, change, methods); + + return Cropper; + +})); diff --git a/lam/templates/lib/620_sweetalert2_11.10.5.js b/lam/templates/lib/620_sweetalert2_11.11.1.js similarity index 95% rename from lam/templates/lib/620_sweetalert2_11.10.5.js rename to lam/templates/lib/620_sweetalert2_11.11.1.js index fa3b1cdcf..f05cda911 100644 --- a/lam/templates/lib/620_sweetalert2_11.10.5.js +++ b/lam/templates/lib/620_sweetalert2_11.11.1.js @@ -1,5 +1,5 @@ /*! -* sweetalert2 v11.10.5 +* sweetalert2 v11.11.1 * Released under the MIT License. */ (function (global, factory) { @@ -8,15 +8,86 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Sweetalert2 = factory()); })(this, (function () { 'use strict'; + function _arrayLikeToArray(r, a) { + (null == a || a > r.length) && (a = r.length); + for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; + return n; + } + function _arrayWithHoles(r) { + if (Array.isArray(r)) return r; + } + function _arrayWithoutHoles(r) { + if (Array.isArray(r)) return _arrayLikeToArray(r); + } + function _assertClassBrand(e, t, n) { + if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; + throw new TypeError("Private element is not present on this object"); + } + function _assertThisInitialized(e) { + if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return e; + } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _checkPrivateRedeclaration(e, t) { + if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); + } + function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); + } + function _classPrivateFieldGet2(s, a) { + return s.get(_assertClassBrand(s, a)); + } + function _classPrivateFieldInitSpec(e, t, a) { + _checkPrivateRedeclaration(e, t), t.set(e, a); + } + function _classPrivateFieldSet2(s, a, r) { + return s.set(_assertClassBrand(s, a), r), r; + } function _construct(t, e, r) { if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments); var o = [null]; o.push.apply(o, e); var p = new (t.bind.apply(t, o))(); - return r && _setPrototypeOf(p, r.prototype), p; + return p; + } + function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); + } + } + function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { + writable: !1 + }), e; + } + function _get() { + return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { + var p = _superPropBase(e, t); + if (p) { + var n = Object.getOwnPropertyDescriptor(p, t); + return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; + } + }, _get.apply(null, arguments); + } + function _getPrototypeOf(t) { + return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { + return t.__proto__ || Object.getPrototypeOf(t); + }, _getPrototypeOf(t); + } + function _inherits(t, e) { + if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); + t.prototype = Object.create(e && e.prototype, { + constructor: { + value: t, + writable: !0, + configurable: !0 + } + }), Object.defineProperty(t, "prototype", { + writable: !1 + }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { @@ -26,6 +97,9 @@ return !!t; })(); } + function _iterableToArray(r) { + if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); + } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { @@ -37,10 +111,7 @@ f = !0, o = !1; try { - if (i = (t = t.call(r)).next, 0 === l) { - if (Object(t) !== t) return; - f = !1; - } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); + if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { @@ -53,19 +124,45 @@ return a; } } + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _possibleConstructorReturn(t, e) { + if (e && ("object" == typeof e || "function" == typeof e)) return e; + if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); + return _assertThisInitialized(t); + } + function _setPrototypeOf(t, e) { + return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { + return t.__proto__ = e, t; + }, _setPrototypeOf(t, e); + } + function _slicedToArray(r, e) { + return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); + } + function _superPropBase(t, o) { + for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); + return t; + } + function _toConsumableArray(r) { + return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); + } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { - var i = e.call(t, r || "default"); + var i = e.call(t, r ); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } - return ("string" === r ? String : Number)(t); + return (String )(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); - return "symbol" == typeof i ? i : String(i); + return "symbol" == typeof i ? i : i + ""; } function _typeof(o) { "@babel/helpers - typeof"; @@ -76,168 +173,13 @@ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); - } - } - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - Object.defineProperty(Constructor, "prototype", { - writable: false - }); - return Constructor; - } - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function"); - } - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - writable: true, - configurable: true - } - }); - Object.defineProperty(subClass, "prototype", { - writable: false - }); - if (superClass) _setPrototypeOf(subClass, superClass); - } - function _getPrototypeOf(o) { - _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { - return o.__proto__ || Object.getPrototypeOf(o); - }; - return _getPrototypeOf(o); - } - function _setPrototypeOf(o, p) { - _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - return _setPrototypeOf(o, p); - } - function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - return self; - } - function _possibleConstructorReturn(self, call) { - if (call && (typeof call === "object" || typeof call === "function")) { - return call; - } else if (call !== void 0) { - throw new TypeError("Derived constructors may only return object or undefined"); - } - return _assertThisInitialized(self); - } - function _superPropBase(object, property) { - while (!Object.prototype.hasOwnProperty.call(object, property)) { - object = _getPrototypeOf(object); - if (object === null) break; - } - return object; - } - function _get() { - if (typeof Reflect !== "undefined" && Reflect.get) { - _get = Reflect.get.bind(); - } else { - _get = function _get(target, property, receiver) { - var base = _superPropBase(target, property); - if (!base) return; - var desc = Object.getOwnPropertyDescriptor(base, property); - if (desc.get) { - return desc.get.call(arguments.length < 3 ? target : receiver); - } - return desc.value; - }; - } - return _get.apply(this, arguments); - } - function _slicedToArray(arr, i) { - return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); - } - function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); - } - function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray(arr); - } - function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; - } - function _iterableToArray(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); - } - function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); - } - function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - function _classPrivateFieldGet(receiver, privateMap) { - var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); - return _classApplyDescriptorGet(receiver, descriptor); - } - function _classPrivateFieldSet(receiver, privateMap, value) { - var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); - _classApplyDescriptorSet(receiver, descriptor, value); - return value; - } - function _classExtractFieldDescriptor(receiver, privateMap, action) { - if (!privateMap.has(receiver)) { - throw new TypeError("attempted to " + action + " private field on non-instance"); - } - return privateMap.get(receiver); - } - function _classApplyDescriptorGet(receiver, descriptor) { - if (descriptor.get) { - return descriptor.get.call(receiver); - } - return descriptor.value; - } - function _classApplyDescriptorSet(receiver, descriptor, value) { - if (descriptor.set) { - descriptor.set.call(receiver, value); - } else { - if (!descriptor.writable) { - throw new TypeError("attempted to set read only private field"); - } - descriptor.value = value; + function _unsupportedIterableToArray(r, a) { + if (r) { + if ("string" == typeof r) return _arrayLikeToArray(r, a); + var t = {}.toString.call(r).slice(8, -1); + return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } - function _checkPrivateRedeclaration(obj, privateCollection) { - if (privateCollection.has(obj)) { - throw new TypeError("Cannot initialize the same private elements twice on an object"); - } - } - function _classPrivateFieldInitSpec(obj, privateMap, value) { - _checkPrivateRedeclaration(obj, privateMap); - privateMap.set(obj, value); - } var RESTORE_FOCUS_TIMEOUT = 100; @@ -2271,9 +2213,10 @@ // reader’s list of elements (headings, form controls, landmarks, etc.) in the document. var setAriaHidden = function setAriaHidden() { + var container = getContainer(); var bodyChildren = Array.from(document.body.children); bodyChildren.forEach(function (el) { - if (el === getContainer() || el.contains(getContainer())) { + if (el.contains(container)) { return; } if (el.hasAttribute('aria-hidden')) { @@ -3605,7 +3548,11 @@ * @param {DomCache} domCache */ var handleContainerMousedown = function handleContainerMousedown(domCache) { - domCache.container.onmousedown = function () { + domCache.container.onmousedown = function (e) { + // prevent the modal text from being selected on double click on the container (allowOutsideClick: false) + if (e.target === domCache.container) { + e.preventDefault(); + } domCache.popup.onmouseup = function (e) { domCache.popup.onmouseup = function () {}; // We also need to check if the mouseup target is a child of the popup @@ -3691,18 +3638,17 @@ */ function mixin(mixinParams) { var MixinSwal = /*#__PURE__*/function (_this) { - _inherits(MixinSwal, _this); function MixinSwal() { _classCallCheck(this, MixinSwal); return _callSuper(this, MixinSwal, arguments); } - _createClass(MixinSwal, [{ + _inherits(MixinSwal, _this); + return _createClass(MixinSwal, [{ key: "_main", value: function _main(params, priorityMixinParams) { return _get(_getPrototypeOf(MixinSwal.prototype), "_main", this).call(this, params, Object.assign({}, mixinParams, priorityMixinParams)); } }]); - return MixinSwal; }(this); // @ts-ignore return MixinSwal; } @@ -3868,7 +3814,7 @@ /** * @returns {number} */ - _createClass(Timer, [{ + return _createClass(Timer, [{ key: "start", value: function start() { if (!this.running) { @@ -3933,7 +3879,6 @@ return this.running; } }]); - return Timer; }(); var swalStringParams = ['swal-title', 'swal-html', 'swal-footer']; @@ -4019,25 +3964,25 @@ /** * @param {DocumentFragment} templateContent - * @returns {SweetAlertOptions} + * @returns {Pick} */ var getSwalImage = function getSwalImage(templateContent) { var result = {}; - /** @type {HTMLElement} */ + /** @type {HTMLElement | null} */ var image = templateContent.querySelector('swal-image'); if (image) { showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']); if (image.hasAttribute('src')) { - result.imageUrl = image.getAttribute('src'); + result.imageUrl = image.getAttribute('src') || undefined; } if (image.hasAttribute('width')) { - result.imageWidth = image.getAttribute('width'); + result.imageWidth = image.getAttribute('width') || undefined; } if (image.hasAttribute('height')) { - result.imageHeight = image.getAttribute('height'); + result.imageHeight = image.getAttribute('height') || undefined; } if (image.hasAttribute('alt')) { - result.imageAlt = image.getAttribute('alt'); + result.imageAlt = image.getAttribute('alt') || undefined; } } return result; @@ -4259,7 +4204,7 @@ * @returns {Promise} */ email: function email(string, validationMessage) { - return /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address'); + return /^[a-zA-Z0-9.+_'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]+$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address'); }, /** * @param {string} string @@ -4333,10 +4278,7 @@ /** * @type {Promise} */ - _classPrivateFieldInitSpec(this, _promise, { - writable: true, - value: void 0 - }); + _classPrivateFieldInitSpec(this, _promise, void 0); // Prevent run in Node env if (typeof window === 'undefined') { return; @@ -4354,9 +4296,9 @@ /** @type {boolean} */ this.isAwaitingPromise = false; - _classPrivateFieldSet(this, _promise, this._main(currentInstance.params)); + _classPrivateFieldSet2(_promise, this, this._main(currentInstance.params)); } - _createClass(SweetAlert, [{ + return _createClass(SweetAlert, [{ key: "_main", value: function _main(userParams) { var mixinParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; @@ -4397,15 +4339,14 @@ }, { key: "then", value: function then(onFulfilled) { - return _classPrivateFieldGet(this, _promise).then(onFulfilled); + return _classPrivateFieldGet2(_promise, this).then(onFulfilled); } }, { key: "finally", value: function _finally(onFinally) { - return _classPrivateFieldGet(this, _promise)["finally"](onFinally); + return _classPrivateFieldGet2(_promise, this)["finally"](onFinally); } }]); - return SweetAlert; }(); /** @@ -4621,7 +4562,7 @@ }; }); SweetAlert.DismissReason = DismissReason; - SweetAlert.version = '11.10.5'; + SweetAlert.version = '11.11.1'; var Swal = SweetAlert; // @ts-ignore diff --git a/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.14.js b/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.14.js deleted file mode 100644 index 21e19cbfc..000000000 --- a/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.14.js +++ /dev/null @@ -1,1234 +0,0 @@ -var css = '.frc-captcha *{margin:0;padding:0;border:0;text-align:initial;border-radius:px;filter:none!important;transition:none!important;font-weight:400;font-size:14px;line-height:1.2;text-decoration:none;background-color:initial;color:#222}.frc-captcha{position:relative;min-width:250px;max-width:312px;border:1px solid #f4f4f4;padding-bottom:12px;background-color:#fff}.frc-captcha b{font-weight:700}.frc-container{display:flex;align-items:center;min-height:52px}.frc-icon{fill:#222;stroke:#222;flex-shrink:0;margin:8px 8px 0}.frc-icon.frc-warning{fill:#c00}.frc-success .frc-icon{animation:1s ease-in both frc-fade-in}.frc-content{white-space:nowrap;display:flex;flex-direction:column;margin:4px 6px 0 0;overflow-x:auto;flex-grow:1}.frc-banner{position:absolute;bottom:0;right:6px;line-height:1}.frc-banner *{font-size:10px;opacity:.8;text-decoration:none}.frc-progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:3px 0;height:4px;border:none;background-color:#eee;color:#222;width:100%;transition:.5s linear}.frc-progress::-webkit-progress-bar{background:#eee}.frc-progress::-webkit-progress-value{background:#222}.frc-progress::-moz-progress-bar{background:#222}.frc-button{cursor:pointer;padding:2px 6px;background-color:#f1f1f1;border:1px solid transparent;text-align:center;font-weight:600;text-transform:none}.frc-button:focus{border:1px solid #333}.frc-button:hover{background-color:#ddd}.frc-captcha-solution{display:none}.frc-err-url{text-decoration:underline;font-size:.9em}.frc-rtl{direction:rtl}.frc-rtl .frc-content{margin:4px 0 0 6px}.frc-banner.frc-rtl{left:6px;right:auto}.dark.frc-captcha{color:#fff;background-color:#222;border-color:#333}.dark.frc-captcha *{color:#fff}.dark.frc-captcha button{background-color:#444}.dark .frc-icon{fill:#fff;stroke:#fff}.dark .frc-progress{background-color:#444}.dark .frc-progress::-webkit-progress-bar{background:#444}.dark .frc-progress::-webkit-progress-value{background:#ddd}.dark .frc-progress::-moz-progress-bar{background:#ddd}@keyframes frc-fade-in{from{opacity:0}to{opacity:1}}'; - -// This is not an enum to save some bytes in the output bundle. -const SOLVER_TYPE_JS = 1; -const CHALLENGE_SIZE_BYTES = 128; - -// @ts-ignore -const loaderSVG = ``; -const errorSVG = ``; -/** - * Base template used for all widget states - * The reason we use raw string interpolation here is so we don't have to ship something like lit-html. - */ -function getTemplate(fieldName, rtl, svgContent, svgAriaHidden, textContent, solutionString, buttonText, progress = false, debugData, additionalContainerClasses) { - return `
- -
- ${textContent} - ${buttonText ? `` : ""} - ${progress ? `0%` : ""} -
-
FriendlyCaptcha ⇗ -${fieldName === "-" ? "" : ``}`; -} -/** - * Used when the widget is ready to start solving. - */ -function getReadyHTML(fieldName, l) { - return getTemplate(fieldName, l.rtl, ``, true, l.text_ready, ".UNSTARTED", l.button_start, false); -} -/** - * Used when the widget is retrieving a puzzle - */ -function getFetchingHTML(fieldName, l) { - return getTemplate(fieldName, l.rtl, loaderSVG, true, l.text_fetching, ".FETCHING", undefined, true); -} -/** - * Used when the solver is running, displays a progress bar. - */ -function getRunningHTML(fieldName, l) { - return getTemplate(fieldName, l.rtl, loaderSVG, true, l.text_solving, ".UNFINISHED", undefined, true); -} -function getDoneHTML(fieldName, l, solution, data) { - const timeData = `${data.t.toFixed(0)}s (${((data.h / data.t) * 0.001).toFixed(0)}K/s)${data.solver === SOLVER_TYPE_JS ? " JS Fallback" : ""}`; - return getTemplate(fieldName, l.rtl, `${l.text_completed_sr}`, false, l.text_completed, solution, undefined, false, timeData, "frc-success"); -} -function getExpiredHTML(fieldName, l) { - return getTemplate(fieldName, l.rtl, errorSVG, true, l.text_expired, ".EXPIRED", l.button_restart); -} -function getErrorHTML(fieldName, l, errorDescription, recoverable = true, headless = false) { - return getTemplate(fieldName, l.rtl, errorSVG, true, `${l.text_error}
${errorDescription}`, headless ? ".HEADLESS_ERROR" : ".ERROR", recoverable ? l.button_retry : undefined); -} -function findCaptchaElements() { - const elements = document.querySelectorAll(".frc-captcha"); - if (elements.length === 0) { - console.warn("FriendlyCaptcha: No div was found with .frc-captcha class"); - } - return elements; -} -/** - * Injects the style if no #frc-style element is already present - * (to support custom stylesheets) - */ -function injectStyle() { - if (!document.querySelector("#frc-style")) { - const styleSheet = document.createElement("style"); - styleSheet.id = "frc-style"; - styleSheet.innerHTML = css; - document.head.appendChild(styleSheet); - } -} -/** - * @param element parent element of friendlycaptcha - * @param progress value between 0 and 1 - */ -function updateProgressBar(element, data) { - const p = element.querySelector(".frc-progress"); - const perc = (data.i + 1) / data.n; - if (p) { - p.value = perc; - p.innerText = perc.toFixed(2) + "%"; - p.title = data.i + 1 + "/" + data.n + " (" + ((data.h / data.t) * 0.001).toFixed(0) + "K/s)"; - } -} -/** - * Traverses parent nodes until a
is found, returns null if not found. - */ -function findParentFormElement(element) { - while (element.tagName !== "FORM") { - element = element.parentElement; - if (!element) { - return null; - } - } - return element; -} -/** - * Add listener to specified element that will only fire once on focus. - */ -function executeOnceOnFocusInEvent(element, listener) { - element.addEventListener("focusin", listener, { once: true, passive: true }); -} - -// Adapted from the base64-arraybuffer package implementation -// (https://github.com/niklasvh/base64-arraybuffer, MIT licensed) -const CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -const EQ_CHAR = "=".charCodeAt(0); -// Use a lookup table to find the index. -const lookup = new Uint8Array(256); -for (let i = 0; i < CHARS.length; i++) { - lookup[CHARS.charCodeAt(i)] = i; -} -function encode(bytes) { - const len = bytes.length; - let base64 = ""; - for (let i = 0; i < len; i += 3) { - const b0 = bytes[i + 0]; - const b1 = bytes[i + 1]; - const b2 = bytes[i + 2]; - // This temporary variable stops the NextJS 13 compiler from breaking this code in optimization. - // See issue https://github.com/FriendlyCaptcha/friendly-challenge/issues/165 - let t = ""; - t += CHARS.charAt(b0 >>> 2); - t += CHARS.charAt(((b0 & 3) << 4) | (b1 >>> 4)); - t += CHARS.charAt(((b1 & 15) << 2) | (b2 >>> 6)); - t += CHARS.charAt(b2 & 63); - base64 += t; - } - if (len % 3 === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } - else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - return base64; -} -function decode(base64) { - const len = base64.length; - let bufferLength = (len * 3) >>> 2; // * 0.75 - if (base64.charCodeAt(len - 1) === EQ_CHAR) - bufferLength--; - if (base64.charCodeAt(len - 2) === EQ_CHAR) - bufferLength--; - const bytes = new Uint8Array(bufferLength); - for (let i = 0, p = 0; i < len; i += 4) { - const encoded1 = lookup[base64.charCodeAt(i + 0)]; - const encoded2 = lookup[base64.charCodeAt(i + 1)]; - const encoded3 = lookup[base64.charCodeAt(i + 2)]; - const encoded4 = lookup[base64.charCodeAt(i + 3)]; - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - return bytes; -} - -// Defensive init to make it easier to integrate with Gatsby, NextJS, and friends. -let nav; -let ua; -if (typeof navigator !== "undefined") { - nav = navigator; - ua = nav.userAgent.toLowerCase(); -} -/** - * Headless browser detection on the clientside is imperfect. One can modify any clientside code to disable or change this check, - * and one can spoof whatever is checked here. However, that doesn't make it worthless: it's yet another hurdle for spammers and - * it stops unsophisticated scripters from making any request whatsoever. - */ -function isHeadless() { - return ( - //tell-tale bot signs - ua.indexOf("headless") !== -1 || - nav.appVersion.indexOf("Headless") !== -1 || - ua.indexOf("bot") !== -1 || // http://www.useragentstring.com/pages/useragentstring.php?typ=Browser - ua.indexOf("crawl") !== -1 || // Only IE5 has two distributions that has this on windows NT.. so yeah. - nav.webdriver === true || - !nav.language || - (nav.languages !== undefined && !nav.languages.length) // IE 11 does not support NavigatorLanguage.languages https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages - ); -} - -/** - * Maps a value between 0 and 255 to a difficulty threshold (as uint32) - * Difficulty 0 maps to 99.99% probability of being right on the first attempt - * Anything above 250 needs 2^32 tries on average to solve. - * 150 to 180 seems reasonable - */ -function difficultyToThreshold(value) { - if (value > 255) { - value = 255; - } - else if (value < 0) { - value = 0; - } - return Math.pow(2, (255.999 - value) / 8.0) >>> 0; -} - -const PUZZLE_EXPIRY_OFFSET = 13; -const NUMBER_OF_PUZZLES_OFFSET = 14; -const PUZZLE_DIFFICULTY_OFFSET = 15; -function getPuzzleSolverInputs(puzzleBuffer, numPuzzles) { - const startingPoints = []; - for (let i = 0; i < numPuzzles; i++) { - const input = new Uint8Array(CHALLENGE_SIZE_BYTES); - input.set(puzzleBuffer); - input[120] = i; - startingPoints.push(input); - } - return startingPoints; -} - -function decodeBase64Puzzle(base64Puzzle) { - const parts = base64Puzzle.split("."); - const puzzle = parts[1]; - const arr = decode(puzzle); - return { - signature: parts[0], - base64: puzzle, - buffer: arr, - n: arr[NUMBER_OF_PUZZLES_OFFSET], - threshold: difficultyToThreshold(arr[PUZZLE_DIFFICULTY_OFFSET]), - expiry: arr[PUZZLE_EXPIRY_OFFSET] * 300000, - }; -} -async function getPuzzle(urlsSeparatedByComma, siteKey, lang) { - const urls = urlsSeparatedByComma.split(","); - for (let i = 0; i < urls.length; i++) { - try { - const response = await fetchAndRetryWithBackoff(urls[i] + "?sitekey=" + siteKey, { headers: [["x-frc-client", "js-0.9.14"]], mode: "cors" }, 2); - if (response.ok) { - const json = await response.json(); - return json.data.puzzle; - } - else { - let json; - try { - json = await response.json(); - } - catch (e) { - /* Do nothing, the error is not valid JSON */ - } - if (json && json.errors && json.errors[0] === "endpoint_not_enabled") { - throw Error(`Endpoint not allowed (${response.status})`); - } - if (i === urls.length - 1) { - throw Error(`Response status ${response.status} ${response.statusText} ${json ? json.errors : ""}`); - } - } - } - catch (e) { - console.error("[FRC Fetch]:", e); - const err = new Error(`${lang.text_fetch_error} ${urls[i]}`); - err.rawError = e; - throw err; - } - } - // This code should never be reached. - throw Error(`Internal error`); -} -/** - * Retries given request with exponential backoff (starting with 1000ms delay, multiplying by 4 every time) - * @param url Request (can be string url) to fetch - * @param opts Options for fetch - * @param n Number of times to attempt before giving up. - */ -async function fetchAndRetryWithBackoff(url, opts, n) { - let time = 1000; - return fetch(url, opts).catch(async (error) => { - if (n === 0) - throw error; - await new Promise((r) => setTimeout(r, time)); - time *= 4; - return fetchAndRetryWithBackoff(url, opts, n - 1); - }); -} - -// English -const LANG_EN = { - text_init: "Initializing...", - text_ready: "Anti-Robot Verification", - button_start: "Click to start verification", - text_fetching: "Fetching Challenge", - text_solving: "Verifying you are human...", - text_completed: "I am human", - text_completed_sr: "Automatic spam check completed", - text_expired: "Anti-Robot verification expired", - button_restart: "Restart", - text_error: "Verification failed", - button_retry: "Retry", - text_fetch_error: "Failed to connect to", -}; -// French -const LANG_FR = { - text_init: "Chargement...", - text_ready: "Vérification Anti-Robot", - button_start: "Clique ici pour vérifier", - text_fetching: "Chargement du défi", - text_solving: "Nous vérifions que vous n'êtes pas un robot...", - text_completed: "Je ne suis pas un robot", - text_completed_sr: "Vérification automatique des spams terminée", - text_expired: "Vérification anti-robot expirée", - button_restart: "Redémarrer", - text_error: "Échec de la vérification", - button_retry: "Recommencer", - text_fetch_error: "Problème de connexion avec", -}; -// German -const LANG_DE = { - text_init: "Initialisierung...", - text_ready: "Anti-Roboter-Verifizierung", - button_start: "Hier klicken", - text_fetching: "Herausforderung laden...", - text_solving: "Verifizierung, dass Sie ein Mensch sind...", - text_completed: "Ich bin ein Mensch", - text_completed_sr: "Automatische Spamprüfung abgeschlossen", - text_expired: "Verifizierung abgelaufen", - button_restart: "Erneut starten", - text_error: "Verifizierung fehlgeschlagen", - button_retry: "Erneut versuchen", - text_fetch_error: "Verbindungsproblem mit", -}; -// Dutch -const LANG_NL = { - text_init: "Initializeren...", - text_ready: "Anti-robotverificatie", - button_start: "Klik om te starten", - text_fetching: "Aan het laden...", - text_solving: "Anti-robotverificatie bezig...", - text_completed: "Ik ben een mens", - text_completed_sr: "Automatische anti-spamcheck voltooid", - text_expired: "Verificatie verlopen", - button_restart: "Opnieuw starten", - text_error: "Verificatie mislukt", - button_retry: "Opnieuw proberen", - text_fetch_error: "Verbinding mislukt met", -}; -// Italian -const LANG_IT = { - text_init: "Inizializzazione...", - text_ready: "Verifica Anti-Robot", - button_start: "Clicca per iniziare", - text_fetching: "Caricamento...", - text_solving: "Verificando che sei umano...", - text_completed: "Non sono un robot", - text_completed_sr: "Controllo automatico dello spam completato", - text_expired: "Verifica Anti-Robot scaduta", - button_restart: "Ricomincia", - text_error: "Verifica fallita", - button_retry: "Riprova", - text_fetch_error: "Problema di connessione con", -}; -// Portuguese -const LANG_PT = { - text_init: "Inicializando...", - text_ready: "Verificação Anti-Robô", - button_start: "Clique para iniciar verificação", - text_fetching: "Carregando...", - text_solving: "Verificando se você é humano...", - text_completed: "Eu sou humano", - text_completed_sr: "Verificação automática de spam concluída", - text_expired: "Verificação Anti-Robô expirada", - button_restart: "Reiniciar", - text_error: "Verificação falhou", - button_retry: "Tentar novamente", - text_fetch_error: "Falha de conexão com", -}; -// Spanish -const LANG_ES = { - text_init: "Inicializando...", - text_ready: "Verificación Anti-Robot", - button_start: "Haga clic para iniciar la verificación", - text_fetching: "Cargando desafío", - text_solving: "Verificando que eres humano...", - text_completed: "Soy humano", - text_completed_sr: "Verificación automática de spam completada", - text_expired: "Verificación Anti-Robot expirada", - button_restart: "Reiniciar", - text_error: "Ha fallado la verificación", - button_retry: "Intentar de nuevo", - text_fetch_error: "Error al conectarse a", -}; -// Catalan -const LANG_CA = { - text_init: "Inicialitzant...", - text_ready: "Verificació Anti-Robot", - button_start: "Fes clic per començar la verificació", - text_fetching: "Carregant repte", - text_solving: "Verificant que ets humà...", - text_completed: "Soc humà", - text_completed_sr: "Verificació automàtica de correu brossa completada", - text_expired: "La verificació Anti-Robot ha expirat", - button_restart: "Reiniciar", - text_error: "Ha fallat la verificació", - button_retry: "Tornar a provar", - text_fetch_error: "Error connectant a", -}; -// Japanese -const LANG_JA = { - text_init: "開始しています...", - text_ready: "アンチロボット認証", - button_start: "クリックして認証を開始", - text_fetching: "ロードしています", - text_solving: "認証中...", - text_completed: "私はロボットではありません", - text_completed_sr: "自動スパムチェックが完了しました", - text_expired: "認証の期限が切れています", - button_restart: "再度認証を行う", - text_error: "認証にエラーが発生しました", - button_retry: "再度認証を行う", - text_fetch_error: "接続ができませんでした", -}; -// Danish -const LANG_DA = { - text_init: "Aktiverer...", - text_ready: "Jeg er ikke en robot", - button_start: "Klik for at starte verifikationen", - text_fetching: "Henter data", - text_solving: "Kontrollerer at du er et menneske...", - text_completed: "Jeg er et menneske.", - text_completed_sr: "Automatisk spamkontrol gennemført", - text_expired: "Verifikationen kunne ikke fuldføres", - button_restart: "Genstart", - text_error: "Bekræftelse mislykkedes", - button_retry: "Prøv igen", - text_fetch_error: "Forbindelsen mislykkedes", -}; -// Russian -const LANG_RU = { - text_init: "Инициализация...", - text_ready: "АнтиРобот проверка", - button_start: "Нажмите, чтобы начать проверку", - text_fetching: "Получаю задачу", - text_solving: "Проверяю, что вы человек...", - text_completed: "Я человек", - text_completed_sr: "Aвтоматическая проверка на спам завершена", - text_expired: "Срок АнтиРоботной проверки истёк", - button_restart: "Начать заново", - text_error: "Ошибка проверки", - button_retry: "Повторить ещё раз", - text_fetch_error: "Ошибка подключения", -}; -// Swedish -const LANG_SV = { - text_init: "Aktiverar...", - text_ready: "Jag är inte en robot", - button_start: "Klicka för att verifiera", - text_fetching: "Hämtar data", - text_solving: "Kontrollerar att du är människa...", - text_completed: "Jag är en människa", - text_completed_sr: "Automatisk spamkontroll slutförd", - text_expired: "Anti-robot-verifieringen har löpt ut", - button_restart: "Börja om", - text_error: "Verifiering kunde inte slutföras", - button_retry: "Omstart", - text_fetch_error: "Verifiering misslyckades", -}; -// Turkish -const LANG_TR = { - text_init: "Başlatılıyor...", - text_ready: "Anti-Robot Doğrulaması", - button_start: "Doğrulamayı başlatmak için tıklayın", - text_fetching: "Yükleniyor", - text_solving: "Robot olmadığınız doğrulanıyor...", - text_completed: "Ben bir insanım", - text_completed_sr: "Otomatik spam kontrolü tamamlandı", - text_expired: "Anti-Robot doğrulamasının süresi doldu", - button_restart: "Yeniden başlat", - text_error: "Doğrulama başarısız oldu", - button_retry: "Tekrar dene", - text_fetch_error: "Bağlantı başarısız oldu", -}; -// Greek -const LANG_EL = { - text_init: "Προετοιμασία...", - text_ready: "Anti-Robot Επαλήθευση", - button_start: " Κάντε κλικ για να ξεκινήσει η επαλήθευση", - text_fetching: " Λήψη πρόκλησης", - text_solving: " Επιβεβαίωση ανθρώπου...", - text_completed: "Είμαι άνθρωπος", - text_completed_sr: " Ο αυτόματος έλεγχος ανεπιθύμητου περιεχομένου ολοκληρώθηκε", - text_expired: " Η επαλήθευση Anti-Robot έληξε", - button_restart: " Επανεκκίνηση", - text_error: " Η επαλήθευση απέτυχε", - button_retry: " Δοκιμάστε ξανά", - text_fetch_error: " Αποτυχία σύνδεσης με", -}; -// Ukrainian -const LANG_UK = { - text_init: "Ініціалізація...", - text_ready: "Антиробот верифікація", - button_start: "Натисніть, щоб розпочати верифікацію", - text_fetching: "З’єднання", - text_solving: "Перевірка, що ви не робот...", - text_completed: "Я не робот", - text_completed_sr: "Автоматична перевірка спаму завершена", - text_expired: "Час вичерпано", - button_restart: "Почати знову", - text_error: "Верифікація не вдалась", - button_retry: "Спробувати знову", - text_fetch_error: "Не вдалось з’єднатись", -}; -// Bulgarian -const LANG_BG = { - text_init: "Инициализиране...", - text_ready: "Анти-робот проверка", - button_start: "Щракнете, за да започнете проверката", - text_fetching: "Предизвикателство", - text_solving: "Проверяваме дали си човек...", - text_completed: "Аз съм човек", - text_completed_sr: "Автоматичната проверка за спам е завършена", - text_expired: "Анти-Робот проверката изтече", - button_restart: "Рестартирайте", - text_error: "Неуспешна проверка", - button_retry: "Опитайте пак", - text_fetch_error: "Неуспешно свързване с", -}; -// Czech -const LANG_CS = { - text_init: "Inicializace...", - text_ready: "Ověření proti robotům", - button_start: "Klikněte pro ověření", - text_fetching: "Problém při načítání", - text_solving: "Ověření, že jste člověk...", - text_completed: "Jsem člověk", - text_completed_sr: "Automatická kontrola spamu dokončena", - text_expired: "Ověření proti robotům vypršelo", - button_restart: "Restartovat", - text_error: "Ověření se nezdařilo", - button_retry: "Zkusit znovu", - text_fetch_error: "Připojení se nezdařilo", -}; -// Slovak -const LANG_SK = { - text_init: "Inicializácia...", - text_ready: "Overenie proti robotom", - button_start: "Kliknite pre overenie", - text_fetching: "Problém pri načítaní", - text_solving: "Overenie, že ste človek...", - text_completed: "Som človek", - text_completed_sr: "Automatická kontrola spamu dokončená", - text_expired: "Overenie proti robotom vypršalo", - button_restart: "Reštartovať", - text_error: "Overenie sa nepodarilo", - button_retry: "Skúsiť znova", - text_fetch_error: "Pripojenie sa nepodarilo", -}; -// Norwegian -const LANG_NO = { - text_init: " Aktiverer...", - text_ready: "Jeg er ikke en robot", - button_start: "Klikk for å starte verifiseringen", - text_fetching: "Henter data", - text_solving: "Sjekker at du er et menneske...", - text_completed: "Jeg er et menneske", - text_completed_sr: "Automatisk spam-sjekk fullført", - text_expired: "Verifisering kunne ikke fullføres", - button_restart: "Omstart", - text_error: "Bekreftelsen mislyktes", - button_retry: "Prøv på nytt", - text_fetch_error: "Tilkoblingen mislyktes", -}; -// Finnish -const LANG_FI = { - text_init: "Aktivoidaan...", - text_ready: "En ole robotti", - button_start: "Aloita vahvistus klikkaamalla", - text_fetching: "Haetaan tietoja", - text_solving: "Tarkistaa, että olet ihminen...", - text_completed: "Olen ihminen", - text_completed_sr: "Automaattinen roskapostin tarkistus suoritettu", - text_expired: "Vahvistusta ei voitu suorittaa loppuun", - button_restart: "Uudelleenkäynnistys", - text_error: "Vahvistus epäonnistui", - button_retry: "Yritä uudelleen", - text_fetch_error: "Yhteys epäonnistui", -}; -// Latvian -const LANG_LV = { - text_init: "Notiek inicializēšana...", - text_ready: "Verifikācija, ka neesat robots", - button_start: "Noklikšķiniet, lai sāktu verifikāciju", - text_fetching: "Notiek drošības uzdevuma izgūšana", - text_solving: "Notiek pārbaude, vai esat cilvēks...", - text_completed: "Es esmu cilvēks", - text_completed_sr: "Automātiska surogātpasta pārbaude pabeigta", - text_expired: "Verifikācijas, ka neesat robots, derīgums beidzies", - button_restart: "Restartēt", - text_error: "Verifikācija neizdevās", - button_retry: "Mēģināt vēlreiz", - text_fetch_error: "Neizdevās izveidot savienojumu ar", -}; -// Lithuanian -const LANG_LT = { - text_init: "Inicijuojama...", - text_ready: "Patikrinimas, ar nesate robotas", - button_start: "Spustelėkite patikrinimui pradėti", - text_fetching: "Gavimo iššūkis", - text_solving: "Tikrinama, ar esate žmogus...", - text_completed: "Esu žmogus", - text_completed_sr: "Automatinė patikra dėl pašto šiukšlių atlikta", - text_expired: "Patikrinimas, ar nesate robotas, baigė galioti", - button_restart: "Pradėti iš naujo", - text_error: "Patikrinimas nepavyko", - button_retry: "Kartoti", - text_fetch_error: "Nepavyko prisijungti prie", -}; -// Polish -const LANG_PL = { - text_init: "Inicjowanie...", - text_ready: "Weryfikacja antybotowa", - button_start: "Kliknij, aby rozpocząć weryfikację", - text_fetching: "Pobieranie", - text_solving: "Weryfikacja, czy nie jesteś robotem...", - text_completed: "Nie jestem robotem", - text_completed_sr: "Zakończono automatyczne sprawdzanie spamu", - text_expired: "Weryfikacja antybotowa wygasła", - button_restart: "Uruchom ponownie", - text_error: "Weryfikacja nie powiodła się", - button_retry: "Spróbuj ponownie", - text_fetch_error: "Nie udało się połączyć z", -}; -// Estonian -const LANG_ET = { - text_init: "Initsialiseerimine...", - text_ready: "Robotivastane kinnitus", - button_start: "Kinnitamisega alustamiseks klõpsake", - text_fetching: "Väljakutse toomine", - text_solving: "Kinnitatakse, et sa oled inimene...", - text_completed: "Ma olen inimene", - text_completed_sr: "Automaatne rämpsposti kontroll on lõpetatud", - text_expired: "Robotivastane kinnitus aegus", - button_restart: "Taaskäivita", - text_error: "Kinnitamine nurjus", - button_retry: "Proovi uuesti", - text_fetch_error: "Ühenduse loomine nurjus", -}; -// Croatian -const LANG_HR = { - text_init: "Početno postavljanje...", - text_ready: "Provjera protiv robota", - button_start: "Kliknite za početak provjere", - text_fetching: "Dohvaćanje izazova", - text_solving: "Provjeravamo jeste li čovjek...", - text_completed: "Nisam robot", - text_completed_sr: "Automatska provjera je završena", - text_expired: "Vrijeme za provjeru protiv robota je isteklo", - button_restart: "Osvježi", - text_error: "Provjera nije uspjlela", - button_retry: " Ponovo pokreni", - text_fetch_error: "Nije moguće uspostaviti vezu", -}; -// Serbian -const LANG_SR = { - text_init: "Pokretanje...", - text_ready: "Anti-Robot Verifikacija", - button_start: "Kliknite da biste započeli verifikaciju", - text_fetching: "Učitavanje izazova", - text_solving: "Verifikacija da ste čovek...", - text_completed: "Ja sam čovek", - text_completed_sr: "Automatska provera neželjene pošte je završena", - text_expired: "Anti-Robot verifikacija je istekla", - button_restart: "Ponovo pokrenuti", - text_error: "Verifikacija nije uspela", - button_retry: "Pokušajte ponovo", - text_fetch_error: "Neuspelo povezivanje sa...", -}; -// Slovenian -const LANG_SL = { - text_init: "Inicializiranje...", - text_ready: "Preverjanje robotov", - button_start: "Kliknite za začetek preverjanja", - text_fetching: "Prenašanje izziva", - text_solving: "Preverjamo, ali ste človek", - text_completed: "Nisem robot", - text_completed_sr: "Avtomatsko preverjanje je zaključeno", - text_expired: "Preverjanje robotov je poteklo", - button_restart: "Osveži", - text_error: "Preverjanje ni uspelo", - button_retry: "Poskusi ponovno", - text_fetch_error: "Povezave ni bilo mogoče vzpostaviti", -}; -// Hungarian -const LANG_HU = { - text_init: "Inicializálás...", - text_ready: "Robotellenes ellenőrzés", - button_start: "Kattintson az ellenőrzés megkezdéséhez", - text_fetching: "Feladvány lekérése", - text_solving: "Annak igazolása, hogy Ön nem robot...", - text_completed: "Nem vagyok robot", - text_completed_sr: "Automatikus spam ellenőrzés befejeződött", - text_expired: "Robotellenes ellenőrzés lejárt", - button_restart: "Újraindítás", - text_error: "Az ellenőrzés nem sikerült", - button_retry: "Próbálja újra", - text_fetch_error: "Nem sikerült csatlakozni", -}; -// Romanian -const LANG_RO = { - text_init: "Se inițializează...", - text_ready: "Verificare anti-robot", - button_start: "Click pentru a începe verificarea", - text_fetching: "Downloading", - text_solving: "Verificare că ești om...", - text_completed: "Sunt om", - text_completed_sr: "Verificarea automată a spam-ului a fost finalizată", - text_expired: "Verificarea anti-robot a expirat", - button_restart: "Restart", - text_error: "Verificare eșuată", - button_retry: "Reîncearcă", - text_fetch_error: "Nu s-a putut conecta", -}; -// Chinese -const LANG_ZH = { - text_init: "初始化中……", - text_ready: "人机验证", - button_start: "点击开始", - text_fetching: "正在加载", - text_solving: "人机校验中……", - text_completed: "我不是机器人", - text_completed_sr: "人机验证完成", - text_expired: "验证已过期", - button_restart: "重新开始", - text_error: "校验失败", - button_retry: "重试", - text_fetch_error: "无法连接到", -}; -// Traditional Chinese -const LANG_ZH_TW = { - text_init: "正在初始化……", - text_ready: "反機器人驗證", - button_start: "點擊開始驗證", - text_fetching: "載入中", - text_solving: "反機器人驗證中……", - text_completed: "我不是機器人", - text_completed_sr: "驗證完成", - text_expired: "驗證超時", - button_restart: "重新開始", - text_error: "驗證失敗", - button_retry: "重試", - text_fetch_error: "無法連線到", -}; -// Vietnamese -const LANG_VI = { - text_init: "Đang khởi tạo...", - text_ready: "Xác minh chống Robot", - button_start: "Bấm vào đây để xác minh", - text_fetching: "Tìm nạp và xử lý thử thách", - text_solving: "Xác minh bạn là người...", - text_completed: "Bạn là con người", - text_completed_sr: "Xác minh hoàn tất", - text_expired: "Xác minh đã hết hạn", - button_restart: "Khởi động lại", - text_error: "Xác minh thất bại", - button_retry: "Thử lại", - text_fetch_error: "Không kết nối được", -}; -// Hebrew -const LANG_HE = { - text_init: "בביצוע...", - text_ready: "אימות אנוש", - button_start: "צריך ללחוץ להתחלת האימות", - text_fetching: "אתגר המענה בהכנה", - text_solving: "מתבצע אימות אנוש...", - text_completed: "אני לא רובוט", - text_completed_sr: "בדיקת הספאם האוטומטית הסתיימה", - text_expired: "פג תוקף אימות האנוש", - button_restart: "להתחיל שוב", - text_error: "אימות האנוש נכשל", - button_retry: "לנסות שוב", - text_fetch_error: "נכשל החיבור אל", - rtl: true, -}; -// Thai -const LANG_TH = { - text_init: "การเริ่มต้น...", - text_ready: " การตรวจสอบต่อต้านหุ่นยนต์", - button_start: "คลิกเพื่อเริ่มการตรวจสอบ", - text_fetching: "การดึงความท้าทาย", - text_solving: "ยืนยันว่าคุณเป็นมนุษย์...", - text_completed: "ฉันเป็นมนุษย์", - text_completed_sr: "การตรวจสอบสแปมอัตโนมัติเสร็จสมบูรณ์", - text_expired: "การตรวจสอบ ต่อต้านหุ่นยนต์ หมดอายุ", - button_restart: "รีสตาร์ท", - text_error: "การยืนยันล้มเหลว", - button_retry: "ลองใหม่", - text_fetch_error: "ไม่สามารถเชื่อมต่อได้" -}; -const localizations = { - en: LANG_EN, - de: LANG_DE, - nl: LANG_NL, - fr: LANG_FR, - it: LANG_IT, - pt: LANG_PT, - es: LANG_ES, - ca: LANG_CA, - ja: LANG_JA, - da: LANG_DA, - ru: LANG_RU, - sv: LANG_SV, - tr: LANG_TR, - el: LANG_EL, - uk: LANG_UK, - bg: LANG_BG, - cs: LANG_CS, - sk: LANG_SK, - no: LANG_NO, - fi: LANG_FI, - lv: LANG_LV, - lt: LANG_LT, - pl: LANG_PL, - et: LANG_ET, - hr: LANG_HR, - sr: LANG_SR, - sl: LANG_SL, - hu: LANG_HU, - ro: LANG_RO, - zh: LANG_ZH, - zh_tw: LANG_ZH_TW, - vi: LANG_VI, - he: LANG_HE, - th: LANG_TH, - // alternative language codes - nb: LANG_NO, -}; - -function createDiagnosticsBuffer(solverID, timeToSolved) { - const arr = new Uint8Array(3); - const view = new DataView(arr.buffer); - view.setUint8(0, solverID); - view.setUint16(1, timeToSolved); - return arr; -} - -var workerString = "!function(){\"use strict\";const A=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",I=\"=\".charCodeAt(0),g=new Uint8Array(256);for(let I=0;I{const g=function(A){return new Uint32Array(C.buffer)[(B+4>>>2)+2*A]}(A),e=31-Math.clz32(g>>>6&31),o=I.length,i=Q(o<>>2]=t(i),n[r+4>>>2]=i,n[r+8>>>2]=o<>>e)+A]=t(I[A]);else s.set(I,i>>>e);return r},I.__getUint8Array=A=>{const I=new Uint32Array(C.buffer),g=I[A+4>>>2];return new Uint8Array(C.buffer,g,I[g-4>>>2]>>>0)},function(A,I={}){const g=A.__argumentsLength?I=>{A.__argumentsLength.value=I}:A.__setArgumentsLength||A.__setargc||(()=>({}));for(const C in A){if(!Object.prototype.hasOwnProperty.call(A,C))continue;const Q=A[C],t=C.split(\".\")[0];\"function\"==typeof Q&&Q!==g?(I[t]=(...A)=>(g(A.length),Q(...A))).original=Q:I[t]=Q}return I}(g,I)}class Q{constructor(A){this.b=new Uint8Array(128),this.h=new Uint32Array(16),this.t=0,this.c=0,this.v=new Uint32Array(32),this.m=new Uint32Array(32),this.outlen=A}}function t(A,I){return A[I]^A[I+1]<<8^A[I+2]<<16^A[I+3]<<24}function B(A,I,g,C,Q,t,B,e){const o=I[B],i=I[B+1],r=I[e],n=I[e+1];let E,s,w,c,a=A[g],D=A[g+1],h=A[C],f=A[C+1],y=A[Q],l=A[Q+1],u=A[t],N=A[t+1];E=a+h,s=(a&h|(a|h)&~E)>>>31,a=E,D=D+f+s,E=a+o,s=(a&o|(a|o)&~E)>>>31,a=E,D=D+i+s,w=u^a,c=N^D,u=c,N=w,E=y+u,s=(y&u|(y|u)&~E)>>>31,y=E,l=l+N+s,w=h^y,c=f^l,h=w>>>24^c<<8,f=c>>>24^w<<8,E=a+h,s=(a&h|(a|h)&~E)>>>31,a=E,D=D+f+s,E=a+r,s=(a&r|(a|r)&~E)>>>31,a=E,D=D+n+s,w=u^a,c=N^D,u=w>>>16^c<<16,N=c>>>16^w<<16,E=y+u,s=(y&u|(y|u)&~E)>>>31,y=E,l=l+N+s,w=h^y,c=f^l,h=c>>>31^w<<1,f=w>>>31^c<<1,A[g]=a,A[g+1]=D,A[C]=h,A[C+1]=f,A[Q]=y,A[Q+1]=l,A[t]=u,A[t+1]=N}const e=[4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225],o=[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6,22,16,24,0,10,4,30,26,20,28,6,12,14,2,18,8,14,18,6,2,26,24,22,28,4,12,10,20,8,0,30,16,18,0,10,14,4,8,20,30,28,2,22,24,12,16,6,26,4,24,12,20,0,22,16,6,8,26,14,10,30,28,2,18,24,10,2,30,28,26,8,20,0,14,12,6,18,4,16,22,26,22,14,28,24,2,6,18,10,0,30,8,16,12,4,20,12,30,28,18,22,6,0,16,24,4,26,14,2,8,20,10,20,4,16,8,14,12,2,10,30,22,18,28,6,24,26,0,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6];function i(A,I){const g=A.v,C=A.m;for(let I=0;I<16;I++)g[I]=A.h[I],g[I+16]=e[I];g[24]=g[24]^A.t,g[25]=g[25]^A.t/4294967296,I&&(g[28]=~g[28],g[29]=~g[29]);for(let I=0;I<32;I++)C[I]=t(A.b,4*I);for(let A=0;A<12;A++)B(g,C,0,8,16,24,o[16*A+0],o[16*A+1]),B(g,C,2,10,18,26,o[16*A+2],o[16*A+3]),B(g,C,4,12,20,28,o[16*A+4],o[16*A+5]),B(g,C,6,14,22,30,o[16*A+6],o[16*A+7]),B(g,C,0,10,20,30,o[16*A+8],o[16*A+9]),B(g,C,2,12,22,24,o[16*A+10],o[16*A+11]),B(g,C,4,14,16,26,o[16*A+12],o[16*A+13]),B(g,C,6,8,18,28,o[16*A+14],o[16*A+15]);for(let I=0;I<16;I++)A.h[I]=A.h[I]^g[I]^g[I+16]}function r(A,I){for(let I=0;I<16;I++)A.h[I]=e[I];A.b.set(I),A.h[0]^=16842752^A.outlen}async function n(){return(A,I,g=4294967295)=>{const C=function(A,I,g){if(128!=A.length)throw Error(\"Invalid input\");const C=A.buffer,t=new DataView(C),B=new Q(32);B.t=128;const e=t.getUint32(124,!0),o=e+g;for(let g=e;gs=A));self.onerror=A=>{self.postMessage({type:\"error\",message:JSON.stringify(A)})},self.onmessage=async A=>{const Q=A.data;try{if(\"solver\"===Q.type){if(Q.forceJS){E=1;const A=await n();s(A)}else try{E=2;const A=WebAssembly.compile(function(A){const C=A.length;let Q=3*C>>>2;A.charCodeAt(C-1)===I&&Q--,A.charCodeAt(C-2)===I&&Q--;const t=new Uint8Array(Q);for(let I=0,Q=0;I>4,t[Q++]=(15&B)<<4|e>>2,t[Q++]=(3&e)<<6|63&o}return t}(\"AGFzbQEAAAABKghgAABgAn9/AGADf39/AX9gAX8AYAR/f39/AGAAAX9gAX8Bf2ACf38BfwINAQNlbnYFYWJvcnQABAMMCwcGAwAAAQIFAQIABQMBAAEGFgR/AUEAC38BQQALfwBBAwt/AEHgDAsHbgkGbWVtb3J5AgAHX19hbGxvYwABCF9fcmV0YWluAAIJX19yZWxlYXNlAAMJX19jb2xsZWN0AAQHX19yZXNldAAFC19fcnR0aV9iYXNlAwMNVWludDhBcnJheV9JRAMCDHNvbHZlQmxha2UyYgAKCAELCvQSC5IBAQV/IABB8P///wNLBEAACyMBQRBqIgQgAEEPakFwcSICQRAgAkEQSxsiBmoiAj8AIgVBEHQiA0sEQCAFIAIgA2tB//8DakGAgHxxQRB2IgMgBSADShtAAEEASARAIANAAEEASARAAAsLCyACJAEgBEEQayICIAY2AgAgAkEBNgIEIAIgATYCCCACIAA2AgwgBAsEACAACwMAAQsDAAELBgAjACQBC7sCAQF/AkAgAUUNACAAQQA6AAAgACABakEEayICQQA6AAMgAUECTQ0AIABBADoAASAAQQA6AAIgAkEAOgACIAJBADoAASABQQZNDQAgAEEAOgADIAJBADoAACABQQhNDQAgAEEAIABrQQNxIgJqIgBBADYCACAAIAEgAmtBfHEiAmpBHGsiAUEANgIYIAJBCE0NACAAQQA2AgQgAEEANgIIIAFBADYCECABQQA2AhQgAkEYTQ0AIABBADYCDCAAQQA2AhAgAEEANgIUIABBADYCGCABQQA2AgAgAUEANgIEIAFBADYCCCABQQA2AgwgACAAQQRxQRhqIgFqIQAgAiABayEBA0AgAUEgTwRAIABCADcDACAAQgA3AwggAEIANwMQIABCADcDGCABQSBrIQEgAEEgaiEADAELCwsLcgACfyAARQRAQQxBAhABIQALIAALQQA2AgAgAEEANgIEIABBADYCCCABQfD///8DIAJ2SwRAQcAKQfAKQRJBORAAAAsgASACdCIBQQAQASICIAEQBiAAKAIAGiAAIAI2AgAgACACNgIEIAAgATYCCCAAC88BAQJ/QaABQQAQASIAQQxBAxABQYABQQAQBzYCACAAQQxBBBABQQhBAxAHNgIEIABCADcDCCAAQQA2AhAgAEIANwMYIABCADcDICAAQgA3AyggAEIANwMwIABCADcDOCAAQgA3A0AgAEIANwNIIABCADcDUCAAQgA3A1ggAEIANwNgIABCADcDaCAAQgA3A3AgAEIANwN4IABCADcDgAEgAEIANwOIASAAQgA3A5ABQYABQQUQASIBQYABEAYgACABNgKYASAAQSA2ApwBIAAL2AkCA38SfiAAKAIEIQIgACgCmAEhAwNAIARBgAFIBEAgAyAEaiABIARqKQMANwMAIARBCGohBAwBCwsgAigCBCkDACEMIAIoAgQpAwghDSACKAIEKQMQIQ4gAigCBCkDGCEPIAIoAgQpAyAhBSACKAIEKQMoIQsgAigCBCkDMCEGIAIoAgQpAzghB0KIkvOd/8z5hOoAIQhCu86qptjQ67O7fyEJQqvw0/Sv7ry3PCEQQvHt9Pilp/2npX8hCiAAKQMIQtGFmu/6z5SH0QCFIRFCn9j52cKR2oKbfyESQpSF+aXAyom+YCETQvnC+JuRo7Pw2wAhFEEAIQQDQCAEQcABSARAIAUgCCARIAwgBSADIARBgAhqIgEtAABBA3RqKQMAfHwiBYVCIIoiDHwiCIVCGIoiESAIIAwgBSARIAMgAS0AAUEDdGopAwB8fCIMhUIQiiIIfCIVhUI/iiEFIAsgCSASIA0gCyADIAEtAAJBA3RqKQMAfHwiDYVCIIoiCXwiEYVCGIohCyAGIBAgEyAOIAYgAyABLQAEQQN0aikDAHx8IgaFQiCKIg58IhCFQhiKIhIgECAOIAYgEiADIAEtAAVBA3RqKQMAfHwiDoVCEIoiE3wiEIVCP4ohBiAHIAogFCAPIAcgAyABLQAGQQN0aikDAHx8IgeFQiCKIg98IgqFQhiKIhIgCiAPIAcgEiADIAEtAAdBA3RqKQMAfHwiD4VCEIoiCnwiEoVCP4ohByAQIAogDCARIAkgDSALIAMgAS0AA0EDdGopAwB8fCINhUIQiiIJfCIWIAuFQj+KIgwgAyABLQAIQQN0aikDAHx8IhCFQiCKIgp8IgsgECALIAyFQhiKIhEgAyABLQAJQQN0aikDAHx8IgwgCoVCEIoiFHwiECARhUI/iiELIAYgEiAIIA0gBiADIAEtAApBA3RqKQMAfHwiDYVCIIoiCHwiCoVCGIoiBiANIAYgAyABLQALQQN0aikDAHx8Ig0gCIVCEIoiESAKfCIKhUI/iiEGIAcgFSAJIA4gByADIAEtAAxBA3RqKQMAfHwiDoVCIIoiCHwiCYVCGIoiByAOIAcgAyABLQANQQN0aikDAHx8Ig4gCIVCEIoiEiAJfCIIhUI/iiEHIAUgFiATIA8gBSADIAEtAA5BA3RqKQMAfHwiD4VCIIoiCXwiFYVCGIoiBSAPIAUgAyABLQAPQQN0aikDAHx8Ig8gCYVCEIoiEyAVfCIJhUI/iiEFIARBEGohBAwBCwsgAigCBCACKAIEKQMAIAggDIWFNwMAIAIoAgQgAigCBCkDCCAJIA2FhTcDCCACKAIEIAIoAgQpAxAgDiAQhYU3AxAgAigCBCACKAIEKQMYIAogD4WFNwMYIAIoAgQgAigCBCkDICAFIBGFhTcDICACKAIEIAIoAgQpAyggCyAShYU3AyggAigCBCACKAIEKQMwIAYgE4WFNwMwIAIoAgQgAigCBCkDOCAHIBSFhTcDOCAAIAw3AxggACANNwMgIAAgDjcDKCAAIA83AzAgACAFNwM4IAAgCzcDQCAAIAY3A0ggACAHNwNQIAAgCDcDWCAAIAk3A2AgACAQNwNoIAAgCjcDcCAAIBE3A3ggACASNwOAASAAIBM3A4gBIAAgFDcDkAEL4QIBBH8gACgCCEGAAUcEQEHQCUGACkEeQQUQAAALIAAoAgAhBBAIIgMoAgQhBSADQoABNwMIIAQoAnwiACACaiEGA0AgACAGSQRAIAQgADYCfCADKAIEIgIoAgQgAygCnAGtQoiS95X/zPmE6gCFNwMAIAIoAgRCu86qptjQ67O7fzcDCCACKAIEQqvw0/Sv7ry3PDcDECACKAIEQvHt9Pilp/2npX83AxggAigCBELRhZrv+s+Uh9EANwMgIAIoAgRCn9j52cKR2oKbfzcDKCACKAIEQuv6htq/tfbBHzcDMCACKAIEQvnC+JuRo7Pw2wA3AzggAyAEEAkgBSgCBCkDAKcgAUkEQEEAIAUoAgAiAUEQaygCDCICSwRAQfALQbAMQc0NQQUQAAALQQxBAxABIgAgATYCACAAIAI2AgggACABNgIEIAAPCyAAQQFqIQAMAQsLQQxBAxABQQBBABAHCwwAQaANJABBoA0kAQsL+gQJAEGBCAu/AQECAwQFBgcICQoLDA0ODw4KBAgJDw0GAQwAAgsHBQMLCAwABQIPDQoOAwYHAQkEBwkDAQ0MCw4CBgUKBAAPCAkABQcCBAoPDgELDAYIAw0CDAYKAAsIAwQNBwUPDgEJDAUBDw4NBAoABwYDCQIICw0LBw4MAQMJBQAPBAgGAgoGDw4JCwMACAwCDQcBBAoFCgIIBAcGAQUPCwkOAwwNAAABAgMEBQYHCAkKCwwNDg8OCgQICQ8NBgEMAAILBwUDAEHACQspGgAAAAEAAAABAAAAGgAAAEkAbgB2AGEAbABpAGQAIABpAG4AcAB1AHQAQfAJCzEiAAAAAQAAAAEAAAAiAAAAcwByAGMALwBzAG8AbAB2AGUAcgBXAGEAcwBtAC4AdABzAEGwCgsrHAAAAAEAAAABAAAAHAAAAEkAbgB2AGEAbABpAGQAIABsAGUAbgBnAHQAaABB4AoLNSYAAAABAAAAAQAAACYAAAB+AGwAaQBiAC8AYQByAHIAYQB5AGIAdQBmAGYAZQByAC4AdABzAEGgCws1JgAAAAEAAAABAAAAJgAAAH4AbABpAGIALwBzAHQAYQB0AGkAYwBhAHIAcgBhAHkALgB0AHMAQeALCzMkAAAAAQAAAAEAAAAkAAAASQBuAGQAZQB4ACAAbwB1AHQAIABvAGYAIAByAGEAbgBnAGUAQaAMCzMkAAAAAQAAAAEAAAAkAAAAfgBsAGkAYgAvAHQAeQBwAGUAZABhAHIAcgBhAHkALgB0AHMAQeAMCy4GAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAYQAAAAIAAAAhAgAAAgAAACQC\")),Q=await async function(A){const I=await async function(A){const I={env:{abort(){throw Error(\"Wasm aborted\")}}};return{exports:C(await WebAssembly.instantiate(A,I))}}(A),g=I.exports.__retain(I.exports.__allocArray(I.exports.Uint8Array_ID,new Uint8Array(128)));let Q=I.exports.__getUint8Array(g);return(A,C,t=4294967295)=>{Q.set(A);const B=I.exports.solveBlake2b(g,C,t);Q=I.exports.__getUint8Array(g);const e=I.exports.__getUint8Array(B);return I.exports.__release(B),[Q,e]}}(await A);s(Q)}catch(A){console.log(\"FriendlyCaptcha failed to initialize WebAssembly, falling back to Javascript solver: \"+A.toString()),E=1;const I=await n();s(I)}self.postMessage({type:\"ready\",solver:E})}else if(\"start\"===Q.type){const A=await w;self.postMessage({type:\"started\"});let I,g=0;for(let C=0;C<256;C++){Q.puzzleSolverInput[123]=C;const[t,B]=A(Q.puzzleSolverInput,Q.threshold);if(0!==B.length){I=t;break}console.warn(\"FC: Internal error or no solution found\"),g+=Math.pow(2,32)-1}g+=new DataView(I.slice(-4).buffer).getUint32(0,!0),self.postMessage({type:\"done\",solution:I.slice(-8),h:g,puzzleIndex:Q.puzzleIndex,puzzleNumber:Q.puzzleNumber})}}catch(A){setTimeout((()=>{throw A}))}}}();"; - -// Defensive init to make it easier to integrate with Gatsby and friends. -let URL; -if (typeof window !== "undefined") { - URL = window.URL || window.webkitURL; -} -class WorkerGroup { - constructor() { - this.workers = []; - this.puzzleNumber = 0; - this.numPuzzles = 0; - this.threshold = 0; - this.startTime = 0; - this.progress = 0; - this.totalHashes = 0; - this.puzzleSolverInputs = []; - // The index of the next puzzle - this.puzzleIndex = 0; - this.solutionBuffer = new Uint8Array(0); - // initialize some value, so ts is happy - this.solverType = 1; - this.readyCount = 0; - this.startCount = 0; - this.progressCallback = () => 0; - this.readyCallback = () => 0; - this.startedCallback = () => 0; - this.doneCallback = () => 0; - this.errorCallback = () => 0; - } - init() { - this.terminateWorkers(); - this.progress = 0; - this.totalHashes = 0; - this.readyCount = 0; - this.startCount = 0; - // Setup four workers for now - later we could calculate this depending on the device - this.workers = new Array(4); - const workerBlob = new Blob([workerString], { type: "text/javascript" }); - for (let i = 0; i < this.workers.length; i++) { - this.workers[i] = new Worker(URL.createObjectURL(workerBlob)); - this.workers[i].onerror = (e) => this.errorCallback(e); - this.workers[i].onmessage = (e) => { - const data = e.data; - if (!data) - return; - if (data.type === "ready") { - this.readyCount++; - this.solverType = data.solver; - // We are ready, when all workers are ready - if (this.readyCount == this.workers.length) { - this.readyCallback(); - } - } - else if (data.type === "started") { - this.startCount++; - // We started, when the first worker starts working - if (this.startCount == 1) { - this.startTime = Date.now(); - this.startedCallback(); - } - } - else if (data.type === "done") { - if (data.puzzleNumber !== this.puzzleNumber) - return; // solution belongs to a previous puzzle - if (this.puzzleIndex < this.puzzleSolverInputs.length) { - this.workers[i].postMessage({ - type: "start", - puzzleSolverInput: this.puzzleSolverInputs[this.puzzleIndex], - threshold: this.threshold, - puzzleIndex: this.puzzleIndex, - puzzleNumber: this.puzzleNumber, - }); - this.puzzleIndex++; - } - this.progress++; - this.totalHashes += data.h; - this.progressCallback({ - n: this.numPuzzles, - h: this.totalHashes, - t: (Date.now() - this.startTime) / 1000, - i: this.progress, - }); - this.solutionBuffer.set(data.solution, data.puzzleIndex * 8); - // We are done, when all puzzles have been solved - if (this.progress == this.numPuzzles) { - const totalTime = (Date.now() - this.startTime) / 1000; - this.doneCallback({ - solution: this.solutionBuffer, - h: this.totalHashes, - t: totalTime, - diagnostics: createDiagnosticsBuffer(this.solverType, totalTime), - solver: this.solverType, - }); - } - } - else if (data.type === "error") { - this.errorCallback(data); - } - }; - } - } - setupSolver(forceJS = false) { - const msg = { type: "solver", forceJS: forceJS }; - for (let i = 0; i < this.workers.length; i++) { - this.workers[i].postMessage(msg); - } - } - start(puzzle) { - this.puzzleSolverInputs = getPuzzleSolverInputs(puzzle.buffer, puzzle.n); - this.solutionBuffer = new Uint8Array(8 * puzzle.n); - this.numPuzzles = puzzle.n; - this.threshold = puzzle.threshold; - this.puzzleIndex = 0; - this.puzzleNumber++; - for (let i = 0; i < this.workers.length; i++) { - if (this.puzzleIndex === this.puzzleSolverInputs.length) - break; - this.workers[i].postMessage({ - type: "start", - puzzleSolverInput: this.puzzleSolverInputs[i], - threshold: this.threshold, - puzzleIndex: this.puzzleIndex, - puzzleNumber: this.puzzleNumber, - }); - this.puzzleIndex++; - } - } - terminateWorkers() { - if (this.workers.length == 0) - return; - for (let i = 0; i < this.workers.length; i++) { - this.workers[i].terminate(); - } - this.workers = []; - } -} - -const PUZZLE_ENDPOINT_URL = "https://api.friendlycaptcha.com/api/v1/puzzle"; -class WidgetInstance { - constructor(element, options = {}) { - this.workerGroup = new WorkerGroup(); - /** - * The captcha has been succesfully solved. - */ - this.valid = false; - /** - * Some errors may cause a need for the (worker) to be reinitialized. If this is - * true `init` will be called again when start is called. - */ - this.needsReInit = false; - /** - * Start() has been called at least once ever. - */ - this.hasBeenStarted = false; - this.hasBeenDestroyed = false; - this.opts = Object.assign({ - forceJSFallback: false, - skipStyleInjection: false, - startMode: "focus", - puzzleEndpoint: element.dataset["puzzleEndpoint"] || PUZZLE_ENDPOINT_URL, - startedCallback: () => 0, - readyCallback: () => 0, - doneCallback: () => 0, - errorCallback: () => 0, - sitekey: element.dataset["sitekey"] || "", - language: element.dataset["lang"] || "en", - solutionFieldName: element.dataset["solutionFieldName"] || "frc-captcha-solution", - }, options); - this.e = element; - this.e.friendlyChallengeWidget = this; - this.loadLanguage(); - // @ts-ignore Ignore is required as TS thinks that `this.lang` is not assigned yet, but it happens in `this.loadLanguage()` above. - element.innerText = this.lang.text_init; - if (!this.opts.skipStyleInjection) { - injectStyle(); - } - this.init(this.opts.startMode === "auto" || this.e.dataset["start"] === "auto"); - } - init(forceStart) { - if (this.hasBeenDestroyed) { - console.error("FriendlyCaptcha widget has been destroyed using destroy(), it can not be used anymore."); - return; - } - this.initWorkerGroup(); - if (forceStart) { - this.start(); - } - else if (this.e.dataset["start"] !== "none" && - (this.opts.startMode === "focus" || this.e.dataset["start"] === "focus")) { - const form = findParentFormElement(this.e); - if (form) { - executeOnceOnFocusInEvent(form, () => this.start()); - } - else { - console.log("FriendlyCaptcha div seems not to be contained in a form, autostart will not work"); - } - } - } - /** - * Loads the configured language, or a language passed to this function. - * Note that only the next update will be in the new language, consider calling `reset()` after switching languages. - */ - loadLanguage(lang) { - if (lang !== undefined) { - this.opts.language = lang; - } - else if (this.e.dataset["lang"]) { - this.opts.language = this.e.dataset["lang"]; - } - if (typeof this.opts.language === "string") { - let l = localizations[this.opts.language.toLowerCase()]; - if (l === undefined) { - console.error('FriendlyCaptcha: language "' + this.opts.language + '" not found.'); - // Fall back to English - l = localizations.en; - } - this.lang = l; - } - else { - // We assign to a copy of the English language localization, so that any missing values will be English - this.lang = Object.assign(Object.assign({}, localizations.en), this.opts.language); - } - } - /** - * Add a listener to the button that calls `this.start` on click. - */ - makeButtonStart() { - const b = this.e.querySelector("button"); - if (b) { - b.addEventListener("click", (e) => this.start(), { once: true, passive: true }); - b.addEventListener("touchstart", (e) => this.start(), { once: true, passive: true }); - } - } - onWorkerError(e) { - this.hasBeenStarted = false; - this.needsReInit = true; - if (this.expiryTimeout) - clearTimeout(this.expiryTimeout); - console.error("[FRC]", e); - this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Background worker error " + e.message); - this.makeButtonStart(); - // Just out of precaution - this.opts.forceJSFallback = true; - } - initWorkerGroup() { - this.workerGroup.progressCallback = (progress) => { - updateProgressBar(this.e, progress); - }; - this.workerGroup.readyCallback = () => { - this.e.innerHTML = getReadyHTML(this.opts.solutionFieldName, this.lang); - this.makeButtonStart(); - this.opts.readyCallback(); - }; - this.workerGroup.startedCallback = () => { - this.e.innerHTML = getRunningHTML(this.opts.solutionFieldName, this.lang); - this.opts.startedCallback(); - }; - this.workerGroup.doneCallback = (data) => { - const solutionPayload = this.handleDone(data); - this.opts.doneCallback(solutionPayload); - const callback = this.e.dataset["callback"]; - if (callback) { - window[callback](solutionPayload); - } - }; - this.workerGroup.errorCallback = (e) => { - this.onWorkerError(e); - }; - this.workerGroup.init(); - this.workerGroup.setupSolver(this.opts.forceJSFallback); - } - expire() { - this.hasBeenStarted = false; - // Node.isConnected will be undefined in older browsers - if (this.e.isConnected !== false) { - this.e.innerHTML = getExpiredHTML(this.opts.solutionFieldName, this.lang); - this.makeButtonStart(); - } - } - async start() { - if (this.hasBeenDestroyed) { - console.error("Can not start FriendlyCaptcha widget which has been destroyed"); - return; - } - if (this.hasBeenStarted) { - console.warn("Can not start FriendlyCaptcha widget which has already been started"); - return; - } - const sitekey = this.opts.sitekey || this.e.dataset["sitekey"]; - if (!sitekey) { - console.error("FriendlyCaptcha: sitekey not set on frc-captcha element"); - this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Website problem: sitekey not set", false); - return; - } - if (isHeadless()) { - this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Browser check failed, try a different browser", false, true); - return; - } - if (this.needsReInit) { - this.needsReInit = false; - this.init(true); - return; - } - this.hasBeenStarted = true; - try { - this.e.innerHTML = getFetchingHTML(this.opts.solutionFieldName, this.lang); - this.puzzle = decodeBase64Puzzle(await getPuzzle(this.opts.puzzleEndpoint, sitekey, this.lang)); - if (this.expiryTimeout) - clearTimeout(this.expiryTimeout); - this.expiryTimeout = setTimeout(() => this.expire(), this.puzzle.expiry - 30000); // 30s grace - } - catch (e) { - console.error("[FRC]", e); - this.hasBeenStarted = false; - if (this.expiryTimeout) - clearTimeout(this.expiryTimeout); - this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, e.message); - this.makeButtonStart(); - const code = "error_getting_puzzle"; - this.opts.errorCallback({ code, description: e.toString(), error: e }); - const callback = this.e.dataset["callback-error"]; - if (callback) { - window[callback](this); - } - return; - } - this.workerGroup.start(this.puzzle); - } - /** - * This is to be called when the puzzle has been succesfully completed. - * Here the hidden field gets updated with the solution. - * @param data message from the webworker - */ - handleDone(data) { - this.valid = true; - const puzzleSolutionMessage = `${this.puzzle.signature}.${this.puzzle.base64}.${encode(data.solution)}.${encode(data.diagnostics)}`; - this.e.innerHTML = getDoneHTML(this.opts.solutionFieldName, this.lang, puzzleSolutionMessage, data); - // this.worker = null; // This literally crashes very old browsers.. - this.needsReInit = true; - return puzzleSolutionMessage; - } - /** - * Cleans up the widget entirely, removing any DOM elements and terminating any background workers. - * After it is destroyed it can no longer be used for any purpose. - */ - destroy() { - this.workerGroup.terminateWorkers(); - this.needsReInit = false; - this.hasBeenStarted = false; - if (this.expiryTimeout) - clearTimeout(this.expiryTimeout); - if (this.e) { - this.e.remove(); - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore - delete this.e; - } - this.hasBeenDestroyed = true; - } - /** - * Resets the widget to the initial state. - * This is useful in situations where the page does not refresh when you submit and the form may be re-submitted again - */ - reset() { - if (this.hasBeenDestroyed) { - console.error("FriendlyCaptcha widget has been destroyed, it can not be used anymore"); - return; - } - this.workerGroup.terminateWorkers(); - this.needsReInit = false; - this.hasBeenStarted = false; - if (this.expiryTimeout) - clearTimeout(this.expiryTimeout); - this.init(this.opts.startMode === "auto" || this.e.dataset["start"] === "auto"); - } -} - -window.friendlyChallenge = { - WidgetInstance: WidgetInstance, -}; -function setup() { - let autoWidget = window.friendlyChallenge.autoWidget; - const elements = findCaptchaElements(); - for (let index = 0; index < elements.length; index++) { - const hElement = elements[index]; - if (hElement && !hElement.dataset["attached"]) { - autoWidget = new WidgetInstance(hElement); - // We set the "data-attached" attribute so we don't attach to the same element twice. - hElement.dataset["attached"] = "1"; - } - } - window.friendlyChallenge.autoWidget = autoWidget; -} -if (document.readyState !== "loading") { - setup(); -} -else { - document.addEventListener("DOMContentLoaded", setup); -} diff --git a/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.15.js b/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.15.js new file mode 100644 index 000000000..45bd46784 --- /dev/null +++ b/lam/templates/lib/extra/friendlyCaptcha/friendly-challenge-0.9.15.js @@ -0,0 +1,1596 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } + +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +(function () { + 'use strict'; + + var css = '.frc-captcha *{margin:0;padding:0;border:0;text-align:initial;border-radius:px;filter:none!important;transition:none!important;font-weight:400;font-size:14px;line-height:1.2;text-decoration:none;background-color:initial;color:#222}.frc-captcha{position:relative;min-width:250px;max-width:312px;border:1px solid #f4f4f4;padding-bottom:12px;background-color:#fff}.frc-captcha b{font-weight:700}.frc-container{display:flex;align-items:center;min-height:52px}.frc-icon{fill:#222;stroke:#222;flex-shrink:0;margin:8px 8px 0}.frc-icon.frc-warning{fill:#c00}.frc-success .frc-icon{animation:1s ease-in both frc-fade-in}.frc-content{white-space:nowrap;display:flex;flex-direction:column;margin:4px 6px 0 0;overflow-x:auto;flex-grow:1}.frc-banner{position:absolute;bottom:0;right:6px;line-height:1}.frc-banner *{font-size:10px;opacity:.8;text-decoration:none}.frc-progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:3px 0;height:4px;border:none;background-color:#eee;color:#222;width:100%;transition:.5s linear}.frc-progress::-webkit-progress-bar{background:#eee}.frc-progress::-webkit-progress-value{background:#222}.frc-progress::-moz-progress-bar{background:#222}.frc-button{cursor:pointer;padding:2px 6px;background-color:#f1f1f1;border:1px solid transparent;text-align:center;font-weight:600;text-transform:none}.frc-button:focus{border:1px solid #333}.frc-button:hover{background-color:#ddd}.frc-captcha-solution{display:none}.frc-err-url{text-decoration:underline;font-size:.9em}.frc-rtl{direction:rtl}.frc-rtl .frc-content{margin:4px 0 0 6px}.frc-banner.frc-rtl{left:6px;right:auto}.dark.frc-captcha{color:#fff;background-color:#222;border-color:#333}.dark.frc-captcha *{color:#fff}.dark.frc-captcha button{background-color:#444}.dark .frc-icon{fill:#fff;stroke:#fff}.dark .frc-progress{background-color:#444}.dark .frc-progress::-webkit-progress-bar{background:#444}.dark .frc-progress::-webkit-progress-value{background:#ddd}.dark .frc-progress::-moz-progress-bar{background:#ddd}@keyframes frc-fade-in{from{opacity:0}to{opacity:1}}'; // This is not an enum to save some bytes in the output bundle. + + var SOLVER_TYPE_JS = 1; + var CHALLENGE_SIZE_BYTES = 128; // @ts-ignore + + var loaderSVG = ""; + var errorSVG = ""; + /** + * Base template used for all widget states + * The reason we use raw string interpolation here is so we don't have to ship something like lit-html. + */ + + function getTemplate(fieldName, rtl, svgContent, svgAriaHidden, textContent, solutionString, buttonText) { + var progress = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false; + var debugData = arguments.length > 8 ? arguments[8] : undefined; + var additionalContainerClasses = arguments.length > 9 ? arguments[9] : undefined; + return "
\n\n
\n ").concat(textContent, "\n ").concat(buttonText ? "") : "", "\n ").concat(progress ? "0%" : "", "\n
\n
FriendlyCaptcha \u21D7\n").concat(fieldName === "-" ? "" : "")); + } + /** + * Used when the widget is ready to start solving. + */ + + + function getReadyHTML(fieldName, l) { + return getTemplate(fieldName, l.rtl, "", true, l.text_ready, ".UNSTARTED", l.button_start, false); + } + /** + * Used when the widget is retrieving a puzzle + */ + + + function getFetchingHTML(fieldName, l) { + return getTemplate(fieldName, l.rtl, loaderSVG, true, l.text_fetching, ".FETCHING", undefined, true); + } + /** + * Used when the solver is running, displays a progress bar. + */ + + + function getRunningHTML(fieldName, l) { + return getTemplate(fieldName, l.rtl, loaderSVG, true, l.text_solving, ".UNFINISHED", undefined, true); + } + + function getDoneHTML(fieldName, l, solution, data) { + var timeData = "".concat(data.t.toFixed(0), "s (").concat((data.h / data.t * 0.001).toFixed(0), "K/s)").concat(data.solver === SOLVER_TYPE_JS ? " JS Fallback" : ""); + return getTemplate(fieldName, l.rtl, "".concat(l.text_completed_sr, ""), false, l.text_completed, solution, undefined, false, timeData, "frc-success"); + } + + function getExpiredHTML(fieldName, l) { + return getTemplate(fieldName, l.rtl, errorSVG, true, l.text_expired, ".EXPIRED", l.button_restart); + } + + function getErrorHTML(fieldName, l, errorDescription) { + var recoverable = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var headless = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + return getTemplate(fieldName, l.rtl, errorSVG, true, "".concat(l.text_error, "
").concat(errorDescription), headless ? ".HEADLESS_ERROR" : ".ERROR", recoverable ? l.button_retry : undefined); + } + + function findCaptchaElements() { + var elements = document.querySelectorAll(".frc-captcha"); + + if (elements.length === 0) { + console.warn("FriendlyCaptcha: No div was found with .frc-captcha class"); + } + + return elements; + } + /** + * Injects the style if no #frc-style element is already present + * (to support custom stylesheets) + */ + + + function injectStyle() { + if (!document.querySelector("#frc-style")) { + var styleSheet = document.createElement("style"); + styleSheet.id = "frc-style"; + styleSheet.innerHTML = css; + document.head.appendChild(styleSheet); + } + } + /** + * @param element parent element of friendlycaptcha + * @param progress value between 0 and 1 + */ + + + function updateProgressBar(element, data) { + var p = element.querySelector(".frc-progress"); + var perc = (data.i + 1) / data.n; + + if (p) { + p.value = perc; + p.innerText = perc.toFixed(2) + "%"; + p.title = data.i + 1 + "/" + data.n + " (" + (data.h / data.t * 0.001).toFixed(0) + "K/s)"; + } + } + /** + * Traverses parent nodes until a is found, returns null if not found. + */ + + + function findParentFormElement(element) { + while (element.tagName !== "FORM") { + element = element.parentElement; + + if (!element) { + return null; + } + } + + return element; + } + /** + * Add listener to specified element that will only fire once on focus. + */ + + + function executeOnceOnFocusInEvent(element, listener) { + element.addEventListener("focusin", listener, { + once: true, + passive: true + }); + } // Adapted from the base64-arraybuffer package implementation + // (https://github.com/niklasvh/base64-arraybuffer, MIT licensed) + + + var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var EQ_CHAR = "=".charCodeAt(0); // Use a lookup table to find the index. + + var lookup = new Uint8Array(256); + + for (var i = 0; i < CHARS.length; i++) { + lookup[CHARS.charCodeAt(i)] = i; + } + + function encode(bytes) { + var len = bytes.length; + var base64 = ""; + + for (var _i = 0; _i < len; _i += 3) { + var b0 = bytes[_i + 0]; + var b1 = bytes[_i + 1]; + var b2 = bytes[_i + 2]; // This temporary variable stops the NextJS 13 compiler from breaking this code in optimization. + // See issue https://github.com/FriendlyCaptcha/friendly-challenge/issues/165 + + var t = ""; + t += CHARS.charAt(b0 >>> 2); + t += CHARS.charAt((b0 & 3) << 4 | b1 >>> 4); + t += CHARS.charAt((b1 & 15) << 2 | b2 >>> 6); + t += CHARS.charAt(b2 & 63); + base64 += t; + } + + if (len % 3 === 2) { + base64 = base64.substring(0, base64.length - 1) + "="; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + "=="; + } + + return base64; + } + + function decode(base64) { + var len = base64.length; + var bufferLength = len * 3 >>> 2; // * 0.75 + + if (base64.charCodeAt(len - 1) === EQ_CHAR) bufferLength--; + if (base64.charCodeAt(len - 2) === EQ_CHAR) bufferLength--; + var bytes = new Uint8Array(bufferLength); + + for (var _i2 = 0, p = 0; _i2 < len; _i2 += 4) { + var encoded1 = lookup[base64.charCodeAt(_i2 + 0)]; + var encoded2 = lookup[base64.charCodeAt(_i2 + 1)]; + var encoded3 = lookup[base64.charCodeAt(_i2 + 2)]; + var encoded4 = lookup[base64.charCodeAt(_i2 + 3)]; + bytes[p++] = encoded1 << 2 | encoded2 >> 4; + bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2; + bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63; + } + + return bytes; + } // Defensive init to make it easier to integrate with Gatsby, NextJS, and friends. + + + var nav; + var ua; + + if (typeof navigator !== "undefined" && typeof navigator.userAgent === "string") { + nav = navigator; + ua = nav.userAgent.toLowerCase(); + } + /** + * Headless browser detection on the clientside is imperfect. One can modify any clientside code to disable or change this check, + * and one can spoof whatever is checked here. However, that doesn't make it worthless: it's yet another hurdle for spammers and + * it stops unsophisticated scripters from making any request whatsoever. + */ + + + function isHeadless() { + return (//tell-tale bot signs + ua.indexOf("headless") !== -1 || nav.appVersion.indexOf("Headless") !== -1 || ua.indexOf("bot") !== -1 || // http://www.useragentstring.com/pages/useragentstring.php?typ=Browser + ua.indexOf("crawl") !== -1 || // Only IE5 has two distributions that has this on windows NT.. so yeah. + nav.webdriver === true || !nav.language || nav.languages !== undefined && !nav.languages.length // IE 11 does not support NavigatorLanguage.languages https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages + + ); + } + /** + * Maps a value between 0 and 255 to a difficulty threshold (as uint32) + * Difficulty 0 maps to 99.99% probability of being right on the first attempt + * Anything above 250 needs 2^32 tries on average to solve. + * 150 to 180 seems reasonable + */ + + + function difficultyToThreshold(value) { + if (value > 255) { + value = 255; + } else if (value < 0) { + value = 0; + } + + return Math.pow(2, (255.999 - value) / 8.0) >>> 0; + } + + var PUZZLE_EXPIRY_OFFSET = 13; + var NUMBER_OF_PUZZLES_OFFSET = 14; + var PUZZLE_DIFFICULTY_OFFSET = 15; + + function getPuzzleSolverInputs(puzzleBuffer, numPuzzles) { + var startingPoints = []; + + for (var _i3 = 0; _i3 < numPuzzles; _i3++) { + var input = new Uint8Array(CHALLENGE_SIZE_BYTES); + input.set(puzzleBuffer); + input[120] = _i3; + startingPoints.push(input); + } + + return startingPoints; + } + + function decodeBase64Puzzle(base64Puzzle) { + var parts = base64Puzzle.split("."); + var puzzle = parts[1]; + var arr = decode(puzzle); + return { + signature: parts[0], + base64: puzzle, + buffer: arr, + n: arr[NUMBER_OF_PUZZLES_OFFSET], + threshold: difficultyToThreshold(arr[PUZZLE_DIFFICULTY_OFFSET]), + expiry: arr[PUZZLE_EXPIRY_OFFSET] * 300000 + }; + } + + function getPuzzle(urlsSeparatedByComma, siteKey, lang) { + return new Promise(function ($return, $error) { + var urls; + urls = urlsSeparatedByComma.split(","); + var $Loop_4_trampoline, $Loop_4_local; + + function $Loop_4_step() { + var _$Loop_4_local = $Loop_4_local(), + _$Loop_4_local2 = _slicedToArray(_$Loop_4_local, 1), + i = _$Loop_4_local2[0]; + + i++; + return $Loop_4.bind(this, i); + } + + function $Loop_4(i) { + $Loop_4_local = function $Loop_4_local() { + return [i]; + }; + + if (i < urls.length) { + var $Try_1_Post = function $Try_1_Post() { + try { + return $Loop_4_step; + } catch ($boundEx) { + return $error($boundEx); + } + }; + + var $Try_1_Catch = function $Try_1_Catch(e) { + try { + { + console.error("[FRC Fetch]:", e); + var err; + err = new Error("".concat(lang.text_fetch_error, " ").concat(urls[i], "")); + err.rawError = e; + throw err; + } + } catch ($boundEx) { + return $error($boundEx); + } + }; + + try { + var response; + return Promise.resolve(fetchAndRetryWithBackoff(urls[i] + "?sitekey=" + siteKey, { + headers: [["x-frc-client", "js-0.9.14"]], + mode: "cors" + }, 2)).then(function ($await_7) { + try { + var $If_6 = function $If_6() { + return $Try_1_Post(); + }; + + response = $await_7; + + if (response.ok) { + var json; + return Promise.resolve(response.json()).then(function ($await_8) { + try { + json = $await_8; + return $return(json.data.puzzle); + } catch ($boundEx) { + return $Try_1_Catch($boundEx); + } + }, $Try_1_Catch); + } else { + var _json; + + var $Try_2_Post = function () { + try { + if (_json && _json.errors && _json.errors[0] === "endpoint_not_enabled") { + throw Error("Endpoint not allowed (".concat(response.status, ")")); + } + + if (i === urls.length - 1) { + throw Error("Response status ".concat(response.status, " ").concat(response.statusText, " ").concat(_json ? _json.errors : "")); + } + + return $If_6.call(this); + } catch ($boundEx) { + return $Try_1_Catch($boundEx); + } + }.bind(this); + + var $Try_2_Catch = function $Try_2_Catch(e) { + /* Do nothing, the error is not valid JSON */ + try { + return $Try_2_Post(); + } catch ($boundEx) { + return $Try_1_Catch($boundEx); + } + }; + + try { + return Promise.resolve(response.json()).then(function ($await_9) { + try { + _json = $await_9; + return $Try_2_Post(); + } catch ($boundEx) { + return $Try_2_Catch($boundEx); + } + }, $Try_2_Catch); + } catch (e) { + $Try_2_Catch(e); + } + } + + return $If_6.call(this); + } catch ($boundEx) { + return $Try_1_Catch($boundEx); + } + }.bind(this), $Try_1_Catch); + } catch (e) { + $Try_1_Catch(e); + } + } else return [1]; + } + + return ($Loop_4_trampoline = function (q) { + while (q) { + if (q.then) return void q.then($Loop_4_trampoline, $error); + + try { + if (q.pop) { + if (q.length) return q.pop() ? $Loop_4_exit.call(this) : q;else q = $Loop_4_step; + } else q = q.call(this); + } catch (_exception) { + return $error(_exception); + } + } + }.bind(this))($Loop_4.bind(this, 0)); + + function $Loop_4_exit() { + // This code should never be reached. + return $error(Error("Internal error")); + } + }); + } + /** + * Retries given request with exponential backoff (starting with 1000ms delay, multiplying by 4 every time) + * @param url Request (can be string url) to fetch + * @param opts Options for fetch + * @param n Number of times to attempt before giving up. + */ + + + function fetchAndRetryWithBackoff(url, opts, n) { + return new Promise(function ($return, $error) { + var time = 1000; + return $return(fetch(url, opts).catch(function (error) { + return new Promise(function ($return, $error) { + if (n === 0) return $error(error); + return Promise.resolve(new Promise(function (r) { + return setTimeout(r, time); + })).then(function ($await_10) { + try { + time *= 4; + return $return(fetchAndRetryWithBackoff(url, opts, n - 1)); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + }); + })); + }); + } // English + + + var LANG_EN = { + text_init: "Initializing...", + text_ready: "Anti-Robot Verification", + button_start: "Click to start verification", + text_fetching: "Fetching Challenge", + text_solving: "Verifying you are human...", + text_completed: "I am human", + text_completed_sr: "Automatic spam check completed", + text_expired: "Anti-Robot verification expired", + button_restart: "Restart", + text_error: "Verification failed", + button_retry: "Retry", + text_fetch_error: "Failed to connect to" + }; // French + + var LANG_FR = { + text_init: "Chargement...", + text_ready: "Vérification Anti-Robot", + button_start: "Clique ici pour vérifier", + text_fetching: "Chargement du défi", + text_solving: "Nous vérifions que vous n'êtes pas un robot...", + text_completed: "Je ne suis pas un robot", + text_completed_sr: "Vérification automatique des spams terminée", + text_expired: "Vérification anti-robot expirée", + button_restart: "Redémarrer", + text_error: "Échec de la vérification", + button_retry: "Recommencer", + text_fetch_error: "Problème de connexion avec" + }; // German + + var LANG_DE = { + text_init: "Initialisierung...", + text_ready: "Anti-Roboter-Verifizierung", + button_start: "Hier klicken", + text_fetching: "Herausforderung laden...", + text_solving: "Verifizierung, dass Sie ein Mensch sind...", + text_completed: "Ich bin ein Mensch", + text_completed_sr: "Automatische Spamprüfung abgeschlossen", + text_expired: "Verifizierung abgelaufen", + button_restart: "Erneut starten", + text_error: "Verifizierung fehlgeschlagen", + button_retry: "Erneut versuchen", + text_fetch_error: "Verbindungsproblem mit" + }; // Dutch + + var LANG_NL = { + text_init: "Initializeren...", + text_ready: "Anti-robotverificatie", + button_start: "Klik om te starten", + text_fetching: "Aan het laden...", + text_solving: "Anti-robotverificatie bezig...", + text_completed: "Ik ben een mens", + text_completed_sr: "Automatische anti-spamcheck voltooid", + text_expired: "Verificatie verlopen", + button_restart: "Opnieuw starten", + text_error: "Verificatie mislukt", + button_retry: "Opnieuw proberen", + text_fetch_error: "Verbinding mislukt met" + }; // Italian + + var LANG_IT = { + text_init: "Inizializzazione...", + text_ready: "Verifica Anti-Robot", + button_start: "Clicca per iniziare", + text_fetching: "Caricamento...", + text_solving: "Verificando che sei umano...", + text_completed: "Non sono un robot", + text_completed_sr: "Controllo automatico dello spam completato", + text_expired: "Verifica Anti-Robot scaduta", + button_restart: "Ricomincia", + text_error: "Verifica fallita", + button_retry: "Riprova", + text_fetch_error: "Problema di connessione con" + }; // Portuguese + + var LANG_PT = { + text_init: "Inicializando...", + text_ready: "Verificação Anti-Robô", + button_start: "Clique para iniciar verificação", + text_fetching: "Carregando...", + text_solving: "Verificando se você é humano...", + text_completed: "Eu sou humano", + text_completed_sr: "Verificação automática de spam concluída", + text_expired: "Verificação Anti-Robô expirada", + button_restart: "Reiniciar", + text_error: "Verificação falhou", + button_retry: "Tentar novamente", + text_fetch_error: "Falha de conexão com" + }; // Spanish + + var LANG_ES = { + text_init: "Inicializando...", + text_ready: "Verificación Anti-Robot", + button_start: "Haga clic para iniciar la verificación", + text_fetching: "Cargando desafío", + text_solving: "Verificando que eres humano...", + text_completed: "Soy humano", + text_completed_sr: "Verificación automática de spam completada", + text_expired: "Verificación Anti-Robot expirada", + button_restart: "Reiniciar", + text_error: "Ha fallado la verificación", + button_retry: "Intentar de nuevo", + text_fetch_error: "Error al conectarse a" + }; // Catalan + + var LANG_CA = { + text_init: "Inicialitzant...", + text_ready: "Verificació Anti-Robot", + button_start: "Fes clic per començar la verificació", + text_fetching: "Carregant repte", + text_solving: "Verificant que ets humà...", + text_completed: "Soc humà", + text_completed_sr: "Verificació automàtica de correu brossa completada", + text_expired: "La verificació Anti-Robot ha expirat", + button_restart: "Reiniciar", + text_error: "Ha fallat la verificació", + button_retry: "Tornar a provar", + text_fetch_error: "Error connectant a" + }; // Japanese + + var LANG_JA = { + text_init: "開始しています...", + text_ready: "アンチロボット認証", + button_start: "クリックして認証を開始", + text_fetching: "ロードしています", + text_solving: "認証中...", + text_completed: "私はロボットではありません", + text_completed_sr: "自動スパムチェックが完了しました", + text_expired: "認証の期限が切れています", + button_restart: "再度認証を行う", + text_error: "認証にエラーが発生しました", + button_retry: "再度認証を行う", + text_fetch_error: "接続ができませんでした" + }; // Danish + + var LANG_DA = { + text_init: "Aktiverer...", + text_ready: "Jeg er ikke en robot", + button_start: "Klik for at starte verifikationen", + text_fetching: "Henter data", + text_solving: "Kontrollerer at du er et menneske...", + text_completed: "Jeg er et menneske.", + text_completed_sr: "Automatisk spamkontrol gennemført", + text_expired: "Verifikationen kunne ikke fuldføres", + button_restart: "Genstart", + text_error: "Bekræftelse mislykkedes", + button_retry: "Prøv igen", + text_fetch_error: "Forbindelsen mislykkedes" + }; // Russian + + var LANG_RU = { + text_init: "Инициализация...", + text_ready: "АнтиРобот проверка", + button_start: "Нажмите, чтобы начать проверку", + text_fetching: "Получаю задачу", + text_solving: "Проверяю, что вы человек...", + text_completed: "Я человек", + text_completed_sr: "Aвтоматическая проверка на спам завершена", + text_expired: "Срок АнтиРоботной проверки истёк", + button_restart: "Начать заново", + text_error: "Ошибка проверки", + button_retry: "Повторить ещё раз", + text_fetch_error: "Ошибка подключения" + }; // Swedish + + var LANG_SV = { + text_init: "Aktiverar...", + text_ready: "Jag är inte en robot", + button_start: "Klicka för att verifiera", + text_fetching: "Hämtar data", + text_solving: "Kontrollerar att du är människa...", + text_completed: "Jag är en människa", + text_completed_sr: "Automatisk spamkontroll slutförd", + text_expired: "Anti-robot-verifieringen har löpt ut", + button_restart: "Börja om", + text_error: "Verifiering kunde inte slutföras", + button_retry: "Omstart", + text_fetch_error: "Verifiering misslyckades" + }; // Turkish + + var LANG_TR = { + text_init: "Başlatılıyor...", + text_ready: "Anti-Robot Doğrulaması", + button_start: "Doğrulamayı başlatmak için tıklayın", + text_fetching: "Yükleniyor", + text_solving: "Robot olmadığınız doğrulanıyor...", + text_completed: "Ben bir insanım", + text_completed_sr: "Otomatik spam kontrolü tamamlandı", + text_expired: "Anti-Robot doğrulamasının süresi doldu", + button_restart: "Yeniden başlat", + text_error: "Doğrulama başarısız oldu", + button_retry: "Tekrar dene", + text_fetch_error: "Bağlantı başarısız oldu" + }; // Greek + + var LANG_EL = { + text_init: "Προετοιμασία...", + text_ready: "Anti-Robot Επαλήθευση", + button_start: " Κάντε κλικ για να ξεκινήσει η επαλήθευση", + text_fetching: " Λήψη πρόκλησης", + text_solving: " Επιβεβαίωση ανθρώπου...", + text_completed: "Είμαι άνθρωπος", + text_completed_sr: " Ο αυτόματος έλεγχος ανεπιθύμητου περιεχομένου ολοκληρώθηκε", + text_expired: " Η επαλήθευση Anti-Robot έληξε", + button_restart: " Επανεκκίνηση", + text_error: " Η επαλήθευση απέτυχε", + button_retry: " Δοκιμάστε ξανά", + text_fetch_error: " Αποτυχία σύνδεσης με" + }; // Ukrainian + + var LANG_UK = { + text_init: "Ініціалізація...", + text_ready: "Антиробот верифікація", + button_start: "Натисніть, щоб розпочати верифікацію", + text_fetching: "З’єднання", + text_solving: "Перевірка, що ви не робот...", + text_completed: "Я не робот", + text_completed_sr: "Автоматична перевірка спаму завершена", + text_expired: "Час вичерпано", + button_restart: "Почати знову", + text_error: "Верифікація не вдалась", + button_retry: "Спробувати знову", + text_fetch_error: "Не вдалось з’єднатись" + }; // Bulgarian + + var LANG_BG = { + text_init: "Инициализиране...", + text_ready: "Анти-робот проверка", + button_start: "Щракнете, за да започнете проверката", + text_fetching: "Предизвикателство", + text_solving: "Проверяваме дали си човек...", + text_completed: "Аз съм човек", + text_completed_sr: "Автоматичната проверка за спам е завършена", + text_expired: "Анти-Робот проверката изтече", + button_restart: "Рестартирайте", + text_error: "Неуспешна проверка", + button_retry: "Опитайте пак", + text_fetch_error: "Неуспешно свързване с" + }; // Czech + + var LANG_CS = { + text_init: "Inicializace...", + text_ready: "Ověření proti robotům", + button_start: "Klikněte pro ověření", + text_fetching: "Problém při načítání", + text_solving: "Ověření, že jste člověk...", + text_completed: "Jsem člověk", + text_completed_sr: "Automatická kontrola spamu dokončena", + text_expired: "Ověření proti robotům vypršelo", + button_restart: "Restartovat", + text_error: "Ověření se nezdařilo", + button_retry: "Zkusit znovu", + text_fetch_error: "Připojení se nezdařilo" + }; // Slovak + + var LANG_SK = { + text_init: "Inicializácia...", + text_ready: "Overenie proti robotom", + button_start: "Kliknite pre overenie", + text_fetching: "Problém pri načítaní", + text_solving: "Overenie, že ste človek...", + text_completed: "Som človek", + text_completed_sr: "Automatická kontrola spamu dokončená", + text_expired: "Overenie proti robotom vypršalo", + button_restart: "Reštartovať", + text_error: "Overenie sa nepodarilo", + button_retry: "Skúsiť znova", + text_fetch_error: "Pripojenie sa nepodarilo" + }; // Norwegian + + var LANG_NO = { + text_init: " Aktiverer...", + text_ready: "Jeg er ikke en robot", + button_start: "Klikk for å starte verifiseringen", + text_fetching: "Henter data", + text_solving: "Sjekker at du er et menneske...", + text_completed: "Jeg er et menneske", + text_completed_sr: "Automatisk spam-sjekk fullført", + text_expired: "Verifisering kunne ikke fullføres", + button_restart: "Omstart", + text_error: "Bekreftelsen mislyktes", + button_retry: "Prøv på nytt", + text_fetch_error: "Tilkoblingen mislyktes" + }; // Finnish + + var LANG_FI = { + text_init: "Aktivoidaan...", + text_ready: "En ole robotti", + button_start: "Aloita vahvistus klikkaamalla", + text_fetching: "Haetaan tietoja", + text_solving: "Tarkistaa, että olet ihminen...", + text_completed: "Olen ihminen", + text_completed_sr: "Automaattinen roskapostin tarkistus suoritettu", + text_expired: "Vahvistusta ei voitu suorittaa loppuun", + button_restart: "Uudelleenkäynnistys", + text_error: "Vahvistus epäonnistui", + button_retry: "Yritä uudelleen", + text_fetch_error: "Yhteys epäonnistui" + }; // Latvian + + var LANG_LV = { + text_init: "Notiek inicializēšana...", + text_ready: "Verifikācija, ka neesat robots", + button_start: "Noklikšķiniet, lai sāktu verifikāciju", + text_fetching: "Notiek drošības uzdevuma izgūšana", + text_solving: "Notiek pārbaude, vai esat cilvēks...", + text_completed: "Es esmu cilvēks", + text_completed_sr: "Automātiska surogātpasta pārbaude pabeigta", + text_expired: "Verifikācijas, ka neesat robots, derīgums beidzies", + button_restart: "Restartēt", + text_error: "Verifikācija neizdevās", + button_retry: "Mēģināt vēlreiz", + text_fetch_error: "Neizdevās izveidot savienojumu ar" + }; // Lithuanian + + var LANG_LT = { + text_init: "Inicijuojama...", + text_ready: "Patikrinimas, ar nesate robotas", + button_start: "Spustelėkite patikrinimui pradėti", + text_fetching: "Gavimo iššūkis", + text_solving: "Tikrinama, ar esate žmogus...", + text_completed: "Esu žmogus", + text_completed_sr: "Automatinė patikra dėl pašto šiukšlių atlikta", + text_expired: "Patikrinimas, ar nesate robotas, baigė galioti", + button_restart: "Pradėti iš naujo", + text_error: "Patikrinimas nepavyko", + button_retry: "Kartoti", + text_fetch_error: "Nepavyko prisijungti prie" + }; // Polish + + var LANG_PL = { + text_init: "Inicjowanie...", + text_ready: "Weryfikacja antybotowa", + button_start: "Kliknij, aby rozpocząć weryfikację", + text_fetching: "Pobieranie", + text_solving: "Weryfikacja, czy nie jesteś robotem...", + text_completed: "Nie jestem robotem", + text_completed_sr: "Zakończono automatyczne sprawdzanie spamu", + text_expired: "Weryfikacja antybotowa wygasła", + button_restart: "Uruchom ponownie", + text_error: "Weryfikacja nie powiodła się", + button_retry: "Spróbuj ponownie", + text_fetch_error: "Nie udało się połączyć z" + }; // Estonian + + var LANG_ET = { + text_init: "Initsialiseerimine...", + text_ready: "Robotivastane kinnitus", + button_start: "Kinnitamisega alustamiseks klõpsake", + text_fetching: "Väljakutse toomine", + text_solving: "Kinnitatakse, et sa oled inimene...", + text_completed: "Ma olen inimene", + text_completed_sr: "Automaatne rämpsposti kontroll on lõpetatud", + text_expired: "Robotivastane kinnitus aegus", + button_restart: "Taaskäivita", + text_error: "Kinnitamine nurjus", + button_retry: "Proovi uuesti", + text_fetch_error: "Ühenduse loomine nurjus" + }; // Croatian + + var LANG_HR = { + text_init: "Početno postavljanje...", + text_ready: "Provjera protiv robota", + button_start: "Kliknite za početak provjere", + text_fetching: "Dohvaćanje izazova", + text_solving: "Provjeravamo jeste li čovjek...", + text_completed: "Nisam robot", + text_completed_sr: "Automatska provjera je završena", + text_expired: "Vrijeme za provjeru protiv robota je isteklo", + button_restart: "Osvježi", + text_error: "Provjera nije uspjlela", + button_retry: " Ponovo pokreni", + text_fetch_error: "Nije moguće uspostaviti vezu" + }; // Serbian + + var LANG_SR = { + text_init: "Pokretanje...", + text_ready: "Anti-Robot Verifikacija", + button_start: "Kliknite da biste započeli verifikaciju", + text_fetching: "Učitavanje izazova", + text_solving: "Verifikacija da ste čovek...", + text_completed: "Ja sam čovek", + text_completed_sr: "Automatska provera neželjene pošte je završena", + text_expired: "Anti-Robot verifikacija je istekla", + button_restart: "Ponovo pokrenuti", + text_error: "Verifikacija nije uspela", + button_retry: "Pokušajte ponovo", + text_fetch_error: "Neuspelo povezivanje sa..." + }; // Slovenian + + var LANG_SL = { + text_init: "Inicializiranje...", + text_ready: "Preverjanje robotov", + button_start: "Kliknite za začetek preverjanja", + text_fetching: "Prenašanje izziva", + text_solving: "Preverjamo, ali ste človek", + text_completed: "Nisem robot", + text_completed_sr: "Avtomatsko preverjanje je zaključeno", + text_expired: "Preverjanje robotov je poteklo", + button_restart: "Osveži", + text_error: "Preverjanje ni uspelo", + button_retry: "Poskusi ponovno", + text_fetch_error: "Povezave ni bilo mogoče vzpostaviti" + }; // Hungarian + + var LANG_HU = { + text_init: "Inicializálás...", + text_ready: "Robotellenes ellenőrzés", + button_start: "Kattintson az ellenőrzés megkezdéséhez", + text_fetching: "Feladvány lekérése", + text_solving: "Annak igazolása, hogy Ön nem robot...", + text_completed: "Nem vagyok robot", + text_completed_sr: "Automatikus spam ellenőrzés befejeződött", + text_expired: "Robotellenes ellenőrzés lejárt", + button_restart: "Újraindítás", + text_error: "Az ellenőrzés nem sikerült", + button_retry: "Próbálja újra", + text_fetch_error: "Nem sikerült csatlakozni" + }; // Romanian + + var LANG_RO = { + text_init: "Se inițializează...", + text_ready: "Verificare anti-robot", + button_start: "Click pentru a începe verificarea", + text_fetching: "Downloading", + text_solving: "Verificare că ești om...", + text_completed: "Sunt om", + text_completed_sr: "Verificarea automată a spam-ului a fost finalizată", + text_expired: "Verificarea anti-robot a expirat", + button_restart: "Restart", + text_error: "Verificare eșuată", + button_retry: "Reîncearcă", + text_fetch_error: "Nu s-a putut conecta" + }; // Chinese + + var LANG_ZH = { + text_init: "初始化中……", + text_ready: "人机验证", + button_start: "点击开始", + text_fetching: "正在加载", + text_solving: "人机校验中……", + text_completed: "我不是机器人", + text_completed_sr: "人机验证完成", + text_expired: "验证已过期", + button_restart: "重新开始", + text_error: "校验失败", + button_retry: "重试", + text_fetch_error: "无法连接到" + }; // Traditional Chinese + + var LANG_ZH_TW = { + text_init: "正在初始化……", + text_ready: "反機器人驗證", + button_start: "點擊開始驗證", + text_fetching: "載入中", + text_solving: "反機器人驗證中……", + text_completed: "我不是機器人", + text_completed_sr: "驗證完成", + text_expired: "驗證超時", + button_restart: "重新開始", + text_error: "驗證失敗", + button_retry: "重試", + text_fetch_error: "無法連線到" + }; // Vietnamese + + var LANG_VI = { + text_init: "Đang khởi tạo...", + text_ready: "Xác minh chống Robot", + button_start: "Bấm vào đây để xác minh", + text_fetching: "Tìm nạp và xử lý thử thách", + text_solving: "Xác minh bạn là người...", + text_completed: "Bạn là con người", + text_completed_sr: "Xác minh hoàn tất", + text_expired: "Xác minh đã hết hạn", + button_restart: "Khởi động lại", + text_error: "Xác minh thất bại", + button_retry: "Thử lại", + text_fetch_error: "Không kết nối được" + }; // Hebrew + + var LANG_HE = { + text_init: "בביצוע...", + text_ready: "אימות אנוש", + button_start: "צריך ללחוץ להתחלת האימות", + text_fetching: "אתגר המענה בהכנה", + text_solving: "מתבצע אימות אנוש...", + text_completed: "אני לא רובוט", + text_completed_sr: "בדיקת הספאם האוטומטית הסתיימה", + text_expired: "פג תוקף אימות האנוש", + button_restart: "להתחיל שוב", + text_error: "אימות האנוש נכשל", + button_retry: "לנסות שוב", + text_fetch_error: "נכשל החיבור אל", + rtl: true + }; // Thai + + var LANG_TH = { + text_init: "การเริ่มต้น...", + text_ready: " การตรวจสอบต่อต้านหุ่นยนต์", + button_start: "คลิกเพื่อเริ่มการตรวจสอบ", + text_fetching: "การดึงความท้าทาย", + text_solving: "ยืนยันว่าคุณเป็นมนุษย์...", + text_completed: "ฉันเป็นมนุษย์", + text_completed_sr: "การตรวจสอบสแปมอัตโนมัติเสร็จสมบูรณ์", + text_expired: "การตรวจสอบ ต่อต้านหุ่นยนต์ หมดอายุ", + button_restart: "รีสตาร์ท", + text_error: "การยืนยันล้มเหลว", + button_retry: "ลองใหม่", + text_fetch_error: "ไม่สามารถเชื่อมต่อได้" + }; + var localizations = { + en: LANG_EN, + de: LANG_DE, + nl: LANG_NL, + fr: LANG_FR, + it: LANG_IT, + pt: LANG_PT, + es: LANG_ES, + ca: LANG_CA, + ja: LANG_JA, + da: LANG_DA, + ru: LANG_RU, + sv: LANG_SV, + tr: LANG_TR, + el: LANG_EL, + uk: LANG_UK, + bg: LANG_BG, + cs: LANG_CS, + sk: LANG_SK, + no: LANG_NO, + fi: LANG_FI, + lv: LANG_LV, + lt: LANG_LT, + pl: LANG_PL, + et: LANG_ET, + hr: LANG_HR, + sr: LANG_SR, + sl: LANG_SL, + hu: LANG_HU, + ro: LANG_RO, + zh: LANG_ZH, + zh_tw: LANG_ZH_TW, + vi: LANG_VI, + he: LANG_HE, + th: LANG_TH, + // alternative language codes + nb: LANG_NO + }; + + function createDiagnosticsBuffer(solverID, timeToSolved) { + var arr = new Uint8Array(3); + var view = new DataView(arr.buffer); + view.setUint8(0, solverID); + view.setUint16(1, timeToSolved); + return arr; + } + + var workerString = "!function(){function A(A,r){return function(A){if(Array.isArray(A))return A}(A)||function(A,t){if(\"undefined\"!=typeof Symbol&&Symbol.iterator in Object(A)){var r=[],n=!0,e=!1,o=void 0;try{for(var i,g=A[Symbol.iterator]();!(n=(i=g.next()).done)&&(r.push(i.value),!t||r.length!==t);n=!0);}catch(I){e=!0,o=I}finally{try{n||null==g.return||g.return()}finally{if(e)throw o}}return r}}(A,r)||function(A,r){if(A){if(\"string\"==typeof A)return t(A,r);var n=Object.prototype.toString.call(A).slice(8,-1);return\"Object\"===n&&A.constructor&&(n=A.constructor.name),\"Map\"===n||\"Set\"===n?Array.from(A):\"Arguments\"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?t(A,r):void 0}}(A,r)||function(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}()}function t(A,t){(null==t||t>A.length)&&(t=A.length);for(var r=0,n=new Array(t);r>>31))+a+(((u=I)&c|(u|c)&~(I=u+c))>>>31)),E=(Q=(h=(Q=h^(l=l+(D=C=y^(u=I))+((w&(y=Q)|(w|y)&~(I=w+y))>>>31)))>>>24^(C=E^(w=I))<<8)^(l=l+(D=(Q=D^(s=(s=s+h+((u&(E=C>>>24^Q<<8)|(u|E)&~(I=u+E))>>>31))+f+(((u=I)&B|(u|B)&~(I=u+B))>>>31)))>>>16^(C=y^(u=I))<<16)+((w&(y=C>>>16^Q<<16)|(w|y)&~(I=w+y))>>>31)))>>>31^(C=E^(w=I))<<1,h=C>>>31^Q<<1,A[r]=u,A[r+1]=s,A[n]=E,A[n+1]=h,A[e]=w,A[e+1]=l,A[o]=y,A[o+1]=D}var I,C,Q=[4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225],c=[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6,22,16,24,0,10,4,30,26,20,28,6,12,14,2,18,8,14,18,6,2,26,24,22,28,4,12,10,20,8,0,30,16,18,0,10,14,4,8,20,30,28,2,22,24,12,16,6,26,4,24,12,20,0,22,16,6,8,26,14,10,30,28,2,18,24,10,2,30,28,26,8,20,0,14,12,6,18,4,16,22,26,22,14,28,24,2,6,18,10,0,30,8,16,12,4,20,12,30,28,18,22,6,0,16,24,4,26,14,2,8,20,10,20,4,16,8,14,12,2,10,30,22,18,28,6,24,26,0,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,28,20,8,16,18,30,26,12,2,24,0,4,22,14,10,6];function a(A,t){for(var r=A.v,n=A.m,e=0;e<16;e++)r[e]=A.h[e],r[e+16]=Q[e];r[24]=r[24]^A.t,r[25]=r[25]^A.t/4294967296,t&&(r[28]=~r[28],r[29]=~r[29]);for(var o=0;o<32;o++)n[o]=i(A.b,4*o);for(var I=0;I<12;I++)g(r,n,0,8,16,24,c[16*I+0],c[16*I+1]),g(r,n,2,10,18,26,c[16*I+2],c[16*I+3]),g(r,n,4,12,20,28,c[16*I+4],c[16*I+5]),g(r,n,6,14,22,30,c[16*I+6],c[16*I+7]),g(r,n,0,10,20,30,c[16*I+8],c[16*I+9]),g(r,n,2,12,22,24,c[16*I+10],c[16*I+11]),g(r,n,4,14,16,26,c[16*I+12],c[16*I+13]),g(r,n,6,8,18,28,c[16*I+14],c[16*I+15]);for(var C=0;C<16;C++)A.h[C]=A.h[C]^r[C]^r[C+16]}function B(A,t){for(var r=0;r<16;r++)A.h[r]=Q[r];A.b.set(t),A.h[0]^=16842752^A.outlen}function f(A,t,r){if(128!=A.length)throw Error(\"Invalid input\");var n=A.buffer,e=new DataView(n),i=new o(32);i.t=128;for(var g=e.getUint32(124,!0),I=g+r,C=g;C2&&void 0!==arguments[2]?arguments[2]:4294967295,n=f(A,t,r);return[A,n]}))}))}Uint8Array.prototype.slice||Object.defineProperty(Uint8Array.prototype,\"slice\",{value:function(A,t){return new Uint8Array(Array.prototype.slice.call(this,A,t))}}),self.ASC_TARGET=0;var s=new Promise((function(A){return C=A}));self.onerror=function(A){self.postMessage({type:\"error\",message:JSON.stringify(A)})},self.onmessage=function(t){return new Promise((function(e,o){var i;i=t.data;var g=function(){try{return e()}catch(A){return o(A)}},Q=function(A){try{return setTimeout((function(){throw A})),g()}catch(t){return o(t)}};try{var c=function(){return g()};if(\"solver\"!==i.type){var a,B,f,E,h=function(){return c.call(this)};return\"start\"===i.type?Promise.resolve(s).then(function(t){try{a=t,self.postMessage({type:\"started\"}),B=0;for(var r=0;r<256;r++){i.puzzleSolverInput[123]=r;var n=A(a(i.puzzleSolverInput,i.threshold),2),e=n[0];if(0!==n[1].length){f=e;break}console.warn(\"FC: Internal error or no solution found\"),B+=Math.pow(2,32)-1}return E=new DataView(f.slice(-4).buffer),B+=E.getUint32(0,!0),self.postMessage({type:\"done\",solution:f.slice(-8),h:B,puzzleIndex:i.puzzleIndex,puzzleNumber:i.puzzleNumber}),h.call(this)}catch(o){return Q(o)}}.bind(this),Q):h.call(this)}var w=function(){return self.postMessage({type:\"ready\",solver:I}),c.call(this)};if(i.forceJS)return I=1,Promise.resolve(u()).then(function(A){try{return C(A),w.call(this)}catch(t){return Q(t)}}.bind(this),Q);var l=function(){try{return w.call(this)}catch(A){return Q(A)}}.bind(this),y=function(A){try{return console.log(\"FriendlyCaptcha failed to initialize WebAssembly, falling back to Javascript solver: \"+A.toString()),I=1,Promise.resolve(u()).then((function(A){try{return C(A),l()}catch(t){return Q(t)}}),Q)}catch(t){return Q(t)}};try{var D;return I=2,D=WebAssembly.compile(function(A){var t=A.length,e=3*t>>>2;A.charCodeAt(t-1)===r&&e--,A.charCodeAt(t-2)===r&&e--;for(var o=new Uint8Array(e),i=0,g=0;i>4,o[g++]=(15&C)<<4|Q>>2,o[g++]=(3&Q)<<6|63&c}return o}(\"AGFzbQEAAAABKghgAABgAn9/AGADf39/AX9gAX8AYAR/f39/AGAAAX9gAX8Bf2ACf38BfwINAQNlbnYFYWJvcnQABAMMCwcGAwAAAQIFAQIABQMBAAEGFgR/AUEAC38BQQALfwBBAwt/AEHgDAsHbgkGbWVtb3J5AgAHX19hbGxvYwABCF9fcmV0YWluAAIJX19yZWxlYXNlAAMJX19jb2xsZWN0AAQHX19yZXNldAAFC19fcnR0aV9iYXNlAwMNVWludDhBcnJheV9JRAMCDHNvbHZlQmxha2UyYgAKCAELCvQSC5IBAQV/IABB8P///wNLBEAACyMBQRBqIgQgAEEPakFwcSICQRAgAkEQSxsiBmoiAj8AIgVBEHQiA0sEQCAFIAIgA2tB//8DakGAgHxxQRB2IgMgBSADShtAAEEASARAIANAAEEASARAAAsLCyACJAEgBEEQayICIAY2AgAgAkEBNgIEIAIgATYCCCACIAA2AgwgBAsEACAACwMAAQsDAAELBgAjACQBC7sCAQF/AkAgAUUNACAAQQA6AAAgACABakEEayICQQA6AAMgAUECTQ0AIABBADoAASAAQQA6AAIgAkEAOgACIAJBADoAASABQQZNDQAgAEEAOgADIAJBADoAACABQQhNDQAgAEEAIABrQQNxIgJqIgBBADYCACAAIAEgAmtBfHEiAmpBHGsiAUEANgIYIAJBCE0NACAAQQA2AgQgAEEANgIIIAFBADYCECABQQA2AhQgAkEYTQ0AIABBADYCDCAAQQA2AhAgAEEANgIUIABBADYCGCABQQA2AgAgAUEANgIEIAFBADYCCCABQQA2AgwgACAAQQRxQRhqIgFqIQAgAiABayEBA0AgAUEgTwRAIABCADcDACAAQgA3AwggAEIANwMQIABCADcDGCABQSBrIQEgAEEgaiEADAELCwsLcgACfyAARQRAQQxBAhABIQALIAALQQA2AgAgAEEANgIEIABBADYCCCABQfD///8DIAJ2SwRAQcAKQfAKQRJBORAAAAsgASACdCIBQQAQASICIAEQBiAAKAIAGiAAIAI2AgAgACACNgIEIAAgATYCCCAAC88BAQJ/QaABQQAQASIAQQxBAxABQYABQQAQBzYCACAAQQxBBBABQQhBAxAHNgIEIABCADcDCCAAQQA2AhAgAEIANwMYIABCADcDICAAQgA3AyggAEIANwMwIABCADcDOCAAQgA3A0AgAEIANwNIIABCADcDUCAAQgA3A1ggAEIANwNgIABCADcDaCAAQgA3A3AgAEIANwN4IABCADcDgAEgAEIANwOIASAAQgA3A5ABQYABQQUQASIBQYABEAYgACABNgKYASAAQSA2ApwBIAAL2AkCA38SfiAAKAIEIQIgACgCmAEhAwNAIARBgAFIBEAgAyAEaiABIARqKQMANwMAIARBCGohBAwBCwsgAigCBCkDACEMIAIoAgQpAwghDSACKAIEKQMQIQ4gAigCBCkDGCEPIAIoAgQpAyAhBSACKAIEKQMoIQsgAigCBCkDMCEGIAIoAgQpAzghB0KIkvOd/8z5hOoAIQhCu86qptjQ67O7fyEJQqvw0/Sv7ry3PCEQQvHt9Pilp/2npX8hCiAAKQMIQtGFmu/6z5SH0QCFIRFCn9j52cKR2oKbfyESQpSF+aXAyom+YCETQvnC+JuRo7Pw2wAhFEEAIQQDQCAEQcABSARAIAUgCCARIAwgBSADIARBgAhqIgEtAABBA3RqKQMAfHwiBYVCIIoiDHwiCIVCGIoiESAIIAwgBSARIAMgAS0AAUEDdGopAwB8fCIMhUIQiiIIfCIVhUI/iiEFIAsgCSASIA0gCyADIAEtAAJBA3RqKQMAfHwiDYVCIIoiCXwiEYVCGIohCyAGIBAgEyAOIAYgAyABLQAEQQN0aikDAHx8IgaFQiCKIg58IhCFQhiKIhIgECAOIAYgEiADIAEtAAVBA3RqKQMAfHwiDoVCEIoiE3wiEIVCP4ohBiAHIAogFCAPIAcgAyABLQAGQQN0aikDAHx8IgeFQiCKIg98IgqFQhiKIhIgCiAPIAcgEiADIAEtAAdBA3RqKQMAfHwiD4VCEIoiCnwiEoVCP4ohByAQIAogDCARIAkgDSALIAMgAS0AA0EDdGopAwB8fCINhUIQiiIJfCIWIAuFQj+KIgwgAyABLQAIQQN0aikDAHx8IhCFQiCKIgp8IgsgECALIAyFQhiKIhEgAyABLQAJQQN0aikDAHx8IgwgCoVCEIoiFHwiECARhUI/iiELIAYgEiAIIA0gBiADIAEtAApBA3RqKQMAfHwiDYVCIIoiCHwiCoVCGIoiBiANIAYgAyABLQALQQN0aikDAHx8Ig0gCIVCEIoiESAKfCIKhUI/iiEGIAcgFSAJIA4gByADIAEtAAxBA3RqKQMAfHwiDoVCIIoiCHwiCYVCGIoiByAOIAcgAyABLQANQQN0aikDAHx8Ig4gCIVCEIoiEiAJfCIIhUI/iiEHIAUgFiATIA8gBSADIAEtAA5BA3RqKQMAfHwiD4VCIIoiCXwiFYVCGIoiBSAPIAUgAyABLQAPQQN0aikDAHx8Ig8gCYVCEIoiEyAVfCIJhUI/iiEFIARBEGohBAwBCwsgAigCBCACKAIEKQMAIAggDIWFNwMAIAIoAgQgAigCBCkDCCAJIA2FhTcDCCACKAIEIAIoAgQpAxAgDiAQhYU3AxAgAigCBCACKAIEKQMYIAogD4WFNwMYIAIoAgQgAigCBCkDICAFIBGFhTcDICACKAIEIAIoAgQpAyggCyAShYU3AyggAigCBCACKAIEKQMwIAYgE4WFNwMwIAIoAgQgAigCBCkDOCAHIBSFhTcDOCAAIAw3AxggACANNwMgIAAgDjcDKCAAIA83AzAgACAFNwM4IAAgCzcDQCAAIAY3A0ggACAHNwNQIAAgCDcDWCAAIAk3A2AgACAQNwNoIAAgCjcDcCAAIBE3A3ggACASNwOAASAAIBM3A4gBIAAgFDcDkAEL4QIBBH8gACgCCEGAAUcEQEHQCUGACkEeQQUQAAALIAAoAgAhBBAIIgMoAgQhBSADQoABNwMIIAQoAnwiACACaiEGA0AgACAGSQRAIAQgADYCfCADKAIEIgIoAgQgAygCnAGtQoiS95X/zPmE6gCFNwMAIAIoAgRCu86qptjQ67O7fzcDCCACKAIEQqvw0/Sv7ry3PDcDECACKAIEQvHt9Pilp/2npX83AxggAigCBELRhZrv+s+Uh9EANwMgIAIoAgRCn9j52cKR2oKbfzcDKCACKAIEQuv6htq/tfbBHzcDMCACKAIEQvnC+JuRo7Pw2wA3AzggAyAEEAkgBSgCBCkDAKcgAUkEQEEAIAUoAgAiAUEQaygCDCICSwRAQfALQbAMQc0NQQUQAAALQQxBAxABIgAgATYCACAAIAI2AgggACABNgIEIAAPCyAAQQFqIQAMAQsLQQxBAxABQQBBABAHCwwAQaANJABBoA0kAQsL+gQJAEGBCAu/AQECAwQFBgcICQoLDA0ODw4KBAgJDw0GAQwAAgsHBQMLCAwABQIPDQoOAwYHAQkEBwkDAQ0MCw4CBgUKBAAPCAkABQcCBAoPDgELDAYIAw0CDAYKAAsIAwQNBwUPDgEJDAUBDw4NBAoABwYDCQIICw0LBw4MAQMJBQAPBAgGAgoGDw4JCwMACAwCDQcBBAoFCgIIBAcGAQUPCwkOAwwNAAABAgMEBQYHCAkKCwwNDg8OCgQICQ8NBgEMAAILBwUDAEHACQspGgAAAAEAAAABAAAAGgAAAEkAbgB2AGEAbABpAGQAIABpAG4AcAB1AHQAQfAJCzEiAAAAAQAAAAEAAAAiAAAAcwByAGMALwBzAG8AbAB2AGUAcgBXAGEAcwBtAC4AdABzAEGwCgsrHAAAAAEAAAABAAAAHAAAAEkAbgB2AGEAbABpAGQAIABsAGUAbgBnAHQAaABB4AoLNSYAAAABAAAAAQAAACYAAAB+AGwAaQBiAC8AYQByAHIAYQB5AGIAdQBmAGYAZQByAC4AdABzAEGgCws1JgAAAAEAAAABAAAAJgAAAH4AbABpAGIALwBzAHQAYQB0AGkAYwBhAHIAcgBhAHkALgB0AHMAQeALCzMkAAAAAQAAAAEAAAAkAAAASQBuAGQAZQB4ACAAbwB1AHQAIABvAGYAIAByAGEAbgBnAGUAQaAMCzMkAAAAAQAAAAEAAAAkAAAAfgBsAGkAYgAvAHQAeQBwAGUAZABhAHIAcgBhAHkALgB0AHMAQeAMCy4GAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAYQAAAAIAAAAhAgAAAgAAACQC\")),Promise.resolve(D).then((function(A){try{return Promise.resolve(function(A){return new Promise((function(t,r){var n,e,o;return Promise.resolve(function(A){return new Promise((function(t,r){var n,e;return n={env:{abort:function(){throw Error(\"Wasm aborted\")}}},Promise.resolve(WebAssembly.instantiate(A,n)).then((function(A){try{return e=function(A){var t={},r=A.exports,n=r.memory,e=r.__alloc,o=r.__retain,i=r.__rtti_base||-1;return t.__allocArray=function(A,t){var r=function(A){return new Uint32Array(n.buffer)[(i+4>>>2)+2*A]}(A),g=31-Math.clz32(r>>>6&31),I=t.length,C=e(I<>>2]=o(C),c[Q+4>>>2]=C,c[Q+8>>>2]=I<>>g)+f]=o(t[f]);else B.set(t,C>>>g);return Q},t.__getUint8Array=function(A){var t=new Uint32Array(n.buffer),r=t[A+4>>>2];return new Uint8Array(n.buffer,r,t[r-4>>>2]>>>0)},function(A){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=A.__argumentsLength?function(t){A.__argumentsLength.value=t}:A.__setArgumentsLength||A.__setargc||function(){return{}},n=function(n){if(!Object.prototype.hasOwnProperty.call(A,n))return\"continue\";var e=A[n],o=n.split(\".\")[0];\"function\"==typeof e&&e!==r?(t[o]=function(){return r(arguments.length),e.apply(void 0,arguments)}).original=e:t[o]=e};for(var e in A)n(e);return t}(r,t)}(A),t({exports:e})}catch(n){return r(n)}}),r)}))}(A)).then((function(A){try{return e=(n=A).exports.__retain(n.exports.__allocArray(n.exports.Uint8Array_ID,new Uint8Array(128))),o=n.exports.__getUint8Array(e),t((function(A,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:4294967295;o.set(A);var i=n.exports.solveBlake2b(e,t,r);o=n.exports.__getUint8Array(e);var g=n.exports.__getUint8Array(i);return n.exports.__release(i),[o,g]}))}catch(i){return r(i)}}),r)}))}(A)).then((function(A){try{return C(A),l()}catch(t){return y(t)}}),y)}catch(t){return y(t)}}),y)}catch(v){y(v)}}catch(v){Q(v)}}))}}()}(\"undefined\"==typeof frcWorker?frcWorker={}:frcWorker);"; // Defensive init to make it easier to integrate with Gatsby and friends. + + var URL; + + if (typeof window !== "undefined") { + URL = window.URL || window.webkitURL; + } + + var WorkerGroup = /*#__PURE__*/function () { + function WorkerGroup() { + _classCallCheck(this, WorkerGroup); + + this.workers = []; + this.puzzleNumber = 0; + this.numPuzzles = 0; + this.threshold = 0; + this.startTime = 0; + this.progress = 0; + this.totalHashes = 0; + this.puzzleSolverInputs = []; // The index of the next puzzle + + this.puzzleIndex = 0; + this.solutionBuffer = new Uint8Array(0); // initialize some value, so ts is happy + + this.solverType = 1; + this.readyCount = 0; + this.startCount = 0; + + this.progressCallback = function () { + return 0; + }; + + this.readyCallback = function () { + return 0; + }; + + this.startedCallback = function () { + return 0; + }; + + this.doneCallback = function () { + return 0; + }; + + this.errorCallback = function () { + return 0; + }; + } + + _createClass(WorkerGroup, [{ + key: "init", + value: function init() { + var _this = this; + + this.terminateWorkers(); + this.progress = 0; + this.totalHashes = 0; + this.readyCount = 0; + this.startCount = 0; // Setup four workers for now - later we could calculate this depending on the device + + this.workers = new Array(4); + var workerBlob = new Blob([workerString], { + type: "text/javascript" + }); + + var _loop = function _loop(_i4) { + _this.workers[_i4] = new Worker(URL.createObjectURL(workerBlob)); + + _this.workers[_i4].onerror = function (e) { + return _this.errorCallback(e); + }; + + _this.workers[_i4].onmessage = function (e) { + var data = e.data; + if (!data) return; + + if (data.type === "ready") { + _this.readyCount++; + _this.solverType = data.solver; // We are ready, when all workers are ready + + if (_this.readyCount == _this.workers.length) { + _this.readyCallback(); + } + } else if (data.type === "started") { + _this.startCount++; // We started, when the first worker starts working + + if (_this.startCount == 1) { + _this.startTime = Date.now(); + + _this.startedCallback(); + } + } else if (data.type === "done") { + if (data.puzzleNumber !== _this.puzzleNumber) return; // solution belongs to a previous puzzle + + if (_this.puzzleIndex < _this.puzzleSolverInputs.length) { + _this.workers[_i4].postMessage({ + type: "start", + puzzleSolverInput: _this.puzzleSolverInputs[_this.puzzleIndex], + threshold: _this.threshold, + puzzleIndex: _this.puzzleIndex, + puzzleNumber: _this.puzzleNumber + }); + + _this.puzzleIndex++; + } + + _this.progress++; + _this.totalHashes += data.h; + + _this.progressCallback({ + n: _this.numPuzzles, + h: _this.totalHashes, + t: (Date.now() - _this.startTime) / 1000, + i: _this.progress + }); + + _this.solutionBuffer.set(data.solution, data.puzzleIndex * 8); // We are done, when all puzzles have been solved + + + if (_this.progress == _this.numPuzzles) { + var totalTime = (Date.now() - _this.startTime) / 1000; + + _this.doneCallback({ + solution: _this.solutionBuffer, + h: _this.totalHashes, + t: totalTime, + diagnostics: createDiagnosticsBuffer(_this.solverType, totalTime), + solver: _this.solverType + }); + } + } else if (data.type === "error") { + _this.errorCallback(data); + } + }; + }; + + for (var _i4 = 0; _i4 < this.workers.length; _i4++) { + _loop(_i4); + } + } + }, { + key: "setupSolver", + value: function setupSolver() { + var forceJS = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var msg = { + type: "solver", + forceJS: forceJS + }; + + for (var _i5 = 0; _i5 < this.workers.length; _i5++) { + this.workers[_i5].postMessage(msg); + } + } + }, { + key: "start", + value: function start(puzzle) { + this.puzzleSolverInputs = getPuzzleSolverInputs(puzzle.buffer, puzzle.n); + this.solutionBuffer = new Uint8Array(8 * puzzle.n); + this.numPuzzles = puzzle.n; + this.threshold = puzzle.threshold; + this.puzzleIndex = 0; + this.puzzleNumber++; + + for (var _i6 = 0; _i6 < this.workers.length; _i6++) { + if (this.puzzleIndex === this.puzzleSolverInputs.length) break; + + this.workers[_i6].postMessage({ + type: "start", + puzzleSolverInput: this.puzzleSolverInputs[_i6], + threshold: this.threshold, + puzzleIndex: this.puzzleIndex, + puzzleNumber: this.puzzleNumber + }); + + this.puzzleIndex++; + } + } + }, { + key: "terminateWorkers", + value: function terminateWorkers() { + if (this.workers.length == 0) return; + + for (var _i7 = 0; _i7 < this.workers.length; _i7++) { + this.workers[_i7].terminate(); + } + + this.workers = []; + } + }]); + + return WorkerGroup; + }(); + + var PUZZLE_ENDPOINT_URL = "https://api.friendlycaptcha.com/api/v1/puzzle"; + + var WidgetInstance = /*#__PURE__*/function () { + function WidgetInstance(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, WidgetInstance); + + this.workerGroup = new WorkerGroup(); + /** + * The captcha has been succesfully solved. + */ + + this.valid = false; + /** + * Some errors may cause a need for the (worker) to be reinitialized. If this is + * true `init` will be called again when start is called. + */ + + this.needsReInit = false; + /** + * Start() has been called at least once ever. + */ + + this.hasBeenStarted = false; + this.hasBeenDestroyed = false; + this.opts = Object.assign({ + forceJSFallback: false, + skipStyleInjection: false, + startMode: "focus", + puzzleEndpoint: element.dataset["puzzleEndpoint"] || PUZZLE_ENDPOINT_URL, + startedCallback: function startedCallback() { + return 0; + }, + readyCallback: function readyCallback() { + return 0; + }, + doneCallback: function doneCallback() { + return 0; + }, + errorCallback: function errorCallback() { + return 0; + }, + sitekey: element.dataset["sitekey"] || "", + language: element.dataset["lang"] || "en", + solutionFieldName: element.dataset["solutionFieldName"] || "frc-captcha-solution" + }, options); + this.e = element; + this.e.friendlyChallengeWidget = this; + this.loadLanguage(); // @ts-ignore Ignore is required as TS thinks that `this.lang` is not assigned yet, but it happens in `this.loadLanguage()` above. + + element.innerText = this.lang.text_init; + + if (!this.opts.skipStyleInjection) { + injectStyle(); + } + + this.init(this.opts.startMode === "auto" || this.e.dataset["start"] === "auto"); + } + + _createClass(WidgetInstance, [{ + key: "init", + value: function init(forceStart) { + var _this2 = this; + + if (this.hasBeenDestroyed) { + console.error("FriendlyCaptcha widget has been destroyed using destroy(), it can not be used anymore."); + return; + } + + this.initWorkerGroup(); + + if (forceStart) { + this.start(); + } else if (this.e.dataset["start"] !== "none" && (this.opts.startMode === "focus" || this.e.dataset["start"] === "focus")) { + var form = findParentFormElement(this.e); + + if (form) { + executeOnceOnFocusInEvent(form, function () { + return _this2.start(); + }); + } else { + console.log("FriendlyCaptcha div seems not to be contained in a form, autostart will not work"); + } + } + } + /** + * Loads the configured language, or a language passed to this function. + * Note that only the next update will be in the new language, consider calling `reset()` after switching languages. + */ + + }, { + key: "loadLanguage", + value: function loadLanguage(lang) { + if (lang !== undefined) { + this.opts.language = lang; + } else if (this.e.dataset["lang"]) { + this.opts.language = this.e.dataset["lang"]; + } + + if (typeof this.opts.language === "string") { + var langCode = this.opts.language.toLowerCase(); + var l = localizations[langCode]; + + if (l === undefined && langCode[2] === '-') { + // Language has a locale '-' separator, remove it and try again + langCode = langCode.substring(0, 2); + l = localizations[langCode]; + } + + if (l === undefined) { + console.error('FriendlyCaptcha: language "' + this.opts.language + '" not found.'); // Fall back to English + + l = localizations.en; + } + + this.lang = l; + } else { + // We assign to a copy of the English language localization, so that any missing values will be English + this.lang = Object.assign(Object.assign({}, localizations.en), this.opts.language); + } + } + /** + * Add a listener to the button that calls `this.start` on click. + */ + + }, { + key: "makeButtonStart", + value: function makeButtonStart() { + var _this3 = this; + + var b = this.e.querySelector("button"); + + if (b) { + b.addEventListener("click", function (e) { + return _this3.start(); + }, { + once: true, + passive: true + }); + b.addEventListener("touchstart", function (e) { + return _this3.start(); + }, { + once: true, + passive: true + }); + } + } + }, { + key: "onWorkerError", + value: function onWorkerError(e) { + this.hasBeenStarted = false; + this.needsReInit = true; + if (this.expiryTimeout) clearTimeout(this.expiryTimeout); + console.error("[FRC]", e); + this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Background worker error " + e.message); + this.makeButtonStart(); // Just out of precaution + + this.opts.forceJSFallback = true; + } + }, { + key: "initWorkerGroup", + value: function initWorkerGroup() { + var _this4 = this; + + this.workerGroup.progressCallback = function (progress) { + updateProgressBar(_this4.e, progress); + }; + + this.workerGroup.readyCallback = function () { + _this4.e.innerHTML = getReadyHTML(_this4.opts.solutionFieldName, _this4.lang); + + _this4.makeButtonStart(); + + _this4.opts.readyCallback(); + }; + + this.workerGroup.startedCallback = function () { + _this4.e.innerHTML = getRunningHTML(_this4.opts.solutionFieldName, _this4.lang); + + _this4.opts.startedCallback(); + }; + + this.workerGroup.doneCallback = function (data) { + var solutionPayload = _this4.handleDone(data); + + _this4.opts.doneCallback(solutionPayload); + + var callback = _this4.e.dataset["callback"]; + + if (callback) { + window[callback](solutionPayload); + } + }; + + this.workerGroup.errorCallback = function (e) { + _this4.onWorkerError(e); + }; + + this.workerGroup.init(); + this.workerGroup.setupSolver(this.opts.forceJSFallback); + } + }, { + key: "expire", + value: function expire() { + this.hasBeenStarted = false; // Node.isConnected will be undefined in older browsers + + if (this.e.isConnected !== false) { + this.e.innerHTML = getExpiredHTML(this.opts.solutionFieldName, this.lang); + this.makeButtonStart(); + } + } + }, { + key: "start", + value: function start() { + return new Promise(function ($return, $error) { + var sitekey; + + if (this.hasBeenDestroyed) { + console.error("Can not start FriendlyCaptcha widget which has been destroyed"); + return $return(); + } + + if (this.hasBeenStarted) { + console.warn("Can not start FriendlyCaptcha widget which has already been started"); + return $return(); + } + + sitekey = this.opts.sitekey || this.e.dataset["sitekey"]; + + if (!sitekey) { + console.error("FriendlyCaptcha: sitekey not set on frc-captcha element"); + this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Website problem: sitekey not set", false); + return $return(); + } + + if (isHeadless()) { + this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, "Browser check failed, try a different browser", false, true); + return $return(); + } + + if (this.needsReInit) { + this.needsReInit = false; + this.init(true); + return $return(); + } + + this.hasBeenStarted = true; + + var $Try_3_Post = function () { + try { + this.workerGroup.start(this.puzzle); + return $return(); + } catch ($boundEx) { + return $error($boundEx); + } + }.bind(this); + + var $Try_3_Catch = function (e) { + try { + { + console.error("[FRC]", e); + this.hasBeenStarted = false; + if (this.expiryTimeout) clearTimeout(this.expiryTimeout); + this.e.innerHTML = getErrorHTML(this.opts.solutionFieldName, this.lang, e.message); + this.makeButtonStart(); + var code; + code = "error_getting_puzzle"; + this.opts.errorCallback({ + code: code, + description: e.toString(), + error: e + }); + var callback; + callback = this.e.dataset["callback-error"]; + + if (callback) { + window[callback](this); + } + + return $return(); + } + } catch ($boundEx) { + return $error($boundEx); + } + }.bind(this); + + try { + this.e.innerHTML = getFetchingHTML(this.opts.solutionFieldName, this.lang); + return Promise.resolve(getPuzzle(this.opts.puzzleEndpoint, sitekey, this.lang)).then(function ($await_11) { + var _this5 = this; + + try { + this.puzzle = decodeBase64Puzzle($await_11); + if (this.expiryTimeout) clearTimeout(this.expiryTimeout); + this.expiryTimeout = setTimeout(function () { + return _this5.expire(); + }, this.puzzle.expiry - 30000); // 30s grace + + return $Try_3_Post(); + } catch ($boundEx) { + return $Try_3_Catch($boundEx); + } + }.bind(this), $Try_3_Catch); + } catch (e) { + $Try_3_Catch(e); + } + }.bind(this)); + } + /** + * This is to be called when the puzzle has been succesfully completed. + * Here the hidden field gets updated with the solution. + * @param data message from the webworker + */ + + }, { + key: "handleDone", + value: function handleDone(data) { + this.valid = true; + var puzzleSolutionMessage = "".concat(this.puzzle.signature, ".").concat(this.puzzle.base64, ".").concat(encode(data.solution), ".").concat(encode(data.diagnostics)); + this.e.innerHTML = getDoneHTML(this.opts.solutionFieldName, this.lang, puzzleSolutionMessage, data); // this.worker = null; // This literally crashes very old browsers.. + + this.needsReInit = true; + return puzzleSolutionMessage; + } + /** + * Cleans up the widget entirely, removing any DOM elements and terminating any background workers. + * After it is destroyed it can no longer be used for any purpose. + */ + + }, { + key: "destroy", + value: function destroy() { + this.workerGroup.terminateWorkers(); + this.needsReInit = false; + this.hasBeenStarted = false; + if (this.expiryTimeout) clearTimeout(this.expiryTimeout); + + if (this.e) { + this.e.remove(); // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + + delete this.e; + } + + this.hasBeenDestroyed = true; + } + /** + * Resets the widget to the initial state. + * This is useful in situations where the page does not refresh when you submit and the form may be re-submitted again + */ + + }, { + key: "reset", + value: function reset() { + if (this.hasBeenDestroyed) { + console.error("FriendlyCaptcha widget has been destroyed, it can not be used anymore"); + return; + } + + this.workerGroup.terminateWorkers(); + this.needsReInit = false; + this.hasBeenStarted = false; + if (this.expiryTimeout) clearTimeout(this.expiryTimeout); + this.init(this.opts.startMode === "auto" || this.e.dataset["start"] === "auto"); + } + }]); + + return WidgetInstance; + }(); + + window.friendlyChallenge = { + WidgetInstance: WidgetInstance + }; + + function setup() { + var autoWidget = window.friendlyChallenge.autoWidget; + var elements = findCaptchaElements(); + + for (var index = 0; index < elements.length; index++) { + var hElement = elements[index]; + + if (hElement && !hElement.dataset["attached"]) { + autoWidget = new WidgetInstance(hElement); // We set the "data-attached" attribute so we don't attach to the same element twice. + + hElement.dataset["attached"] = "1"; + } + } + + window.friendlyChallenge.autoWidget = autoWidget; + } + + if (document.readyState !== "loading") { + setup(); + } else { + document.addEventListener("DOMContentLoaded", setup); + } +})();