UNPKG

formiojs

Version:

Common js library for client side interaction with <form.io>

120 lines (112 loc) • 1.24 MB
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./lib/utils/utils.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./lib/utils/jsonlogic/operators.js": /*!******************************************!*\ !*** ./lib/utils/jsonlogic/operators.js ***! \******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n// Use only immutable useful functions from Lodash.\n// Visit https://lodash.com/docs for more info.\nvar lodashOperators = exports.lodashOperators = [\n// Array\n'chunk', 'compact', 'concat', 'difference', 'differenceBy', 'differenceWith', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'findIndex', 'findLastIndex', 'first', 'flatten', 'flattenDeep', 'flattenDepth', 'fromPairs', 'head', 'indexOf', 'initial', 'intersection', 'intersectionBy', 'intersectionWith', 'join', 'last', 'lastIndexOf', 'nth', 'slice', 'sortedIndex', 'sortedIndexBy', 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexBy', 'sortedLastIndexOf', 'sortedUniq', 'sortedUniqBy', 'tail', 'take', 'takeRight', 'takeRightWhile', 'takeWhile', 'union', 'unionBy', 'unionWith', 'uniq', 'uniqBy', 'uniqWith', 'unzip', 'unzipWith', 'without', 'xor', 'xorBy', 'xorWith', 'zip', 'zipObject', 'zipObjectDeep', 'zipWith',\n// Collection\n'countBy', 'every', 'filter', 'find', 'findLast', 'flatMap', 'flatMapDeep', 'flatMapDepth', 'groupBy', 'includes', 'invokeMap', 'keyBy', 'map', 'orderBy', 'partition', 'reduce', 'reduceRight', 'reject', 'sample', 'sampleSize', 'shuffle', 'size', 'some', 'sortBy',\n// Date\n'now',\n// Function\n'flip', 'negate', 'overArgs', 'partial', 'partialRight', 'rearg', 'rest', 'spread',\n// Lang\n'castArray', 'clone', 'cloneDeep', 'cloneDeepWith', 'cloneDeep', 'conformsTo', 'eq', 'gt', 'gte', 'isArguments', 'isArray', 'isArrayBuffer', 'isArrayLike', 'isArrayLikeObject', 'isBoolean', 'isBuffer', 'isDate', 'isElement', 'isEmpty', 'isEqual', 'isEqualWith', 'isError', 'isFinite', 'isFunction', 'isInteger', 'isLength', 'isMap', 'isMatch', 'isMatchWith', 'isNaN', 'isNative', 'isNil', 'isNull', 'isNumber', 'isObject', 'isObjectLike', 'isPlainObject', 'isRegExp', 'isSafeInteger', 'isSet', 'isString', 'isSymbol', 'isTypedArray', 'isUndefined', 'isWeakMap', 'isWeakSet', 'lt', 'lte', 'toArray', 'toFinite', 'toInteger', 'toLength', 'toNumber', 'toPlainObject', 'toSafeInteger', 'toString',\n// Math\n'add', 'ceil', 'divide', 'floor', 'max', 'maxBy', 'mean', 'meanBy', 'min', 'minBy', 'multiply', 'round', 'subtract', 'sum', 'sumBy',\n// Number\n'clamp', 'inRange', 'random',\n// Object\n'at', 'entries', 'entriesIn', 'findKey', 'findLastKey', 'functions', 'functionsIn', 'get', 'has', 'hasIn', 'invert', 'invertBy', 'invoke', 'keys', 'keysIn', 'mapKeys', 'mapValues', 'omit', 'omitBy', 'pick', 'pickBy', 'result', 'toPairs', 'toPairsIn', 'transform', 'values', 'valuesIn',\n// String\n'camelCase', 'capitalize', 'deburr', 'endsWith', 'escape', 'escapeRegExp', 'kebabCase', 'lowerCase', 'lowerFirst', 'pad', 'padEnd', 'padStart', 'parseInt', 'repeat', 'replace', 'snakeCase', 'split', 'startCase', 'startsWith', 'toLower', 'toUpper', 'trim', 'trimEnd', 'trimStart', 'truncate', 'unescape', 'upperCase', 'upperFirst', 'words',\n// Util\n'cond', 'conforms', 'constant', 'defaultTo', 'flow', 'flowRight', 'identity', 'iteratee', 'matches', 'matchesProperty', 'method', 'methodOf', 'nthArg', 'over', 'overEvery', 'overSome', 'property', 'propertyOf', 'range', 'rangeRight', 'stubArray', 'stubFalse', 'stubObject', 'stubString', 'stubTrue', 'times', 'toPath', 'uniqueId'];\n\n//# sourceURL=webpack:///./lib/utils/jsonlogic/operators.js?"); /***/ }), /***/ "./lib/utils/utils.js": /*!****************************!*\ !*** ./lib/utils/utils.js ***! \****************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.jsonLogic = undefined;\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nexports.evaluate = evaluate;\nexports.getRandomComponentId = getRandomComponentId;\nexports.getPropertyValue = getPropertyValue;\nexports.getElementRect = getElementRect;\nexports.boolValue = boolValue;\nexports.isMongoId = isMongoId;\nexports.isLayoutComponent = isLayoutComponent;\nexports.eachComponent = eachComponent;\nexports.matchComponent = matchComponent;\nexports.getComponent = getComponent;\nexports.findComponents = findComponents;\nexports.flattenComponents = flattenComponents;\nexports.hasCondition = hasCondition;\nexports.parseFloatExt = parseFloatExt;\nexports.formatAsCurrency = formatAsCurrency;\nexports.escapeRegExCharacters = escapeRegExCharacters;\nexports.checkCalculated = checkCalculated;\nexports.checkSimpleConditional = checkSimpleConditional;\nexports.checkCustomConditional = checkCustomConditional;\nexports.checkJsonConditional = checkJsonConditional;\nexports.checkCondition = checkCondition;\nexports.checkTrigger = checkTrigger;\nexports.setActionProperty = setActionProperty;\nexports.getValue = getValue;\nexports.interpolate = interpolate;\nexports.uniqueName = uniqueName;\nexports.guid = guid;\nexports.getDateSetting = getDateSetting;\nexports.isValidDate = isValidDate;\nexports.getLocaleDateFormatInfo = getLocaleDateFormatInfo;\nexports.convertFormatToFlatpickr = convertFormatToFlatpickr;\nexports.convertFormatToMoment = convertFormatToMoment;\nexports.getInputMask = getInputMask;\nexports.matchInputMask = matchInputMask;\nexports.getNumberSeparators = getNumberSeparators;\nexports.getNumberDecimalLimit = getNumberDecimalLimit;\nexports.getCurrencyAffixes = getCurrencyAffixes;\nexports.fieldData = fieldData;\n\nvar _lodash = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n\nvar _lodash2 = _interopRequireDefault(_lodash);\n\nvar _jsonLogicJs = __webpack_require__(/*! json-logic-js */ \"./node_modules/json-logic-js/logic.js\");\n\nvar _jsonLogicJs2 = _interopRequireDefault(_jsonLogicJs);\n\nvar _moment = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n\nvar _moment2 = _interopRequireDefault(_moment);\n\nvar _operators = __webpack_require__(/*! ./jsonlogic/operators */ \"./lib/utils/jsonlogic/operators.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Configure JsonLogic\n_operators.lodashOperators.forEach(function (name) {\n return _jsonLogicJs2.default.add_operation('_' + name, _lodash2.default[name]);\n});\n\n// Retrieve Any Date\n_jsonLogicJs2.default.add_operation('getDate', function (date) {\n return (0, _moment2.default)(date).toISOString();\n});\n\n// Set Relative Minimum Date\n_jsonLogicJs2.default.add_operation('relativeMinDate', function (relativeMinDate) {\n return (0, _moment2.default)().subtract(relativeMinDate, 'days').toISOString();\n});\n\n// Set Relative Maximum Date\n_jsonLogicJs2.default.add_operation('relativeMaxDate', function (relativeMaxDate) {\n return (0, _moment2.default)().add(relativeMaxDate, 'days').toISOString();\n});\n\nexports.jsonLogic = _jsonLogicJs2.default;\n\n/**\n * Evaluate a method.\n *\n * @param func\n * @param args\n * @return {*}\n */\n\nfunction evaluate(func, args, ret, tokenize) {\n var returnVal = null;\n var component = args.component ? args.component : { key: 'component' };\n if (!args.form && args.instance) {\n args.form = _lodash2.default.get(args.instance, 'root._form', {});\n }\n if (typeof func === 'string') {\n if (ret) {\n func += ';return ' + ret;\n }\n var params = _lodash2.default.keys(args);\n\n if (tokenize) {\n // Replace all {{ }} references with actual data.\n func = func.replace(/({{\\s+(.*)\\s+}})/, function (match, $1, $2) {\n if ($2.indexOf('data.') === 0) {\n return _lodash2.default.get(args.data, $2.replace('data.', ''));\n } else if ($2.indexOf('row.') === 0) {\n return _lodash2.default.get(args.row, $2.replace('row.', ''));\n }\n\n // Support legacy...\n return _lodash2.default.get(args.data, $2);\n });\n }\n\n try {\n func = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(params), [func])))();\n } catch (err) {\n console.warn('An error occured within the custom function for ' + component.key, err);\n returnVal = null;\n func = false;\n }\n }\n if (typeof func === 'function') {\n var values = _lodash2.default.values(args);\n try {\n returnVal = func.apply(undefined, _toConsumableArray(values));\n } catch (err) {\n returnVal = null;\n console.warn('An error occured within custom function for ' + component.key, err);\n }\n } else if ((typeof func === 'undefined' ? 'undefined' : _typeof(func)) === 'object') {\n try {\n returnVal = _jsonLogicJs2.default.apply(func, args);\n } catch (err) {\n returnVal = null;\n console.warn('An error occured within custom function for ' + component.key, err);\n }\n } else if (func) {\n console.warn('Unknown function type for ' + component.key);\n }\n return returnVal;\n}\n\nfunction getRandomComponentId() {\n return 'e' + Math.random().toString(36).substring(7);\n}\n\n/**\n * Get a property value of an element.\n *\n * @param style\n * @param prop\n * @return {number}\n */\nfunction getPropertyValue(style, prop) {\n var value = style.getPropertyValue(prop);\n value = value ? value.replace(/[^0-9.]/g, '') : '0';\n return parseFloat(value);\n}\n\n/**\n * Get an elements bounding rectagle.\n *\n * @param element\n * @return {{x: string, y: string, width: string, height: string}}\n */\nfunction getElementRect(element) {\n var style = window.getComputedStyle(element, null);\n return {\n x: getPropertyValue(style, 'left'),\n y: getPropertyValue(style, 'top'),\n width: getPropertyValue(style, 'width'),\n height: getPropertyValue(style, 'height')\n };\n}\n\n/**\n * Determines the boolean value of a setting.\n *\n * @param value\n * @return {boolean}\n */\nfunction boolValue(value) {\n if (_lodash2.default.isBoolean(value)) {\n return value;\n } else if (_lodash2.default.isString(value)) {\n return value.toLowerCase() === 'true';\n } else {\n return !!value;\n }\n}\n\n/**\n * Check to see if an ID is a mongoID.\n * @param text\n * @return {Array|{index: number, input: string}|Boolean|*}\n */\nfunction isMongoId(text) {\n return text.toString().match(/^[0-9a-fA-F]{24}$/);\n}\n\n/**\n * Determine if a component is a layout component or not.\n *\n * @param {Object} component\n * The component to check.\n *\n * @returns {Boolean}\n * Whether or not the component is a layout component.\n */\nfunction isLayoutComponent(component) {\n return Boolean(component.columns && Array.isArray(component.columns) || component.rows && Array.isArray(component.rows) || component.components && Array.isArray(component.components));\n}\n\n/**\n * Iterate through each component within a form.\n *\n * @param {Object} components\n * The components to iterate.\n * @param {Function} fn\n * The iteration function to invoke for each component.\n * @param {Boolean} includeAll\n * Whether or not to include layout components.\n * @param {String} path\n * The current data path of the element. Example: data.user.firstName\n * @param {Object} parent\n * The parent object.\n */\nfunction eachComponent(components, fn, includeAll, path, parent) {\n if (!components) return;\n path = path || '';\n components.forEach(function (component) {\n var hasColumns = component.columns && Array.isArray(component.columns);\n var hasRows = component.rows && Array.isArray(component.rows);\n var hasComps = component.components && Array.isArray(component.components);\n var noRecurse = false;\n var newPath = component.key ? path ? path + '.' + component.key : component.key : '';\n\n // Keep track of parent references.\n if (parent) {\n // Ensure we don't create infinite JSON structures.\n component.parent = _lodash2.default.clone(parent);\n delete component.parent.components;\n delete component.parent.componentMap;\n delete component.parent.columns;\n delete component.parent.rows;\n }\n\n if (includeAll || component.tree || !hasColumns && !hasRows && !hasComps) {\n noRecurse = fn(component, newPath);\n }\n\n var subPath = function subPath() {\n if (component.key && (['datagrid', 'container', 'editgrid'].indexOf(component.type) !== -1 || component.tree)) {\n return newPath;\n } else if (component.key && component.type === 'form') {\n return newPath + '.data';\n }\n return path;\n };\n\n if (!noRecurse) {\n if (hasColumns) {\n component.columns.forEach(function (column) {\n return eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null);\n });\n } else if (hasRows) {\n component.rows.forEach(function (row) {\n if (Array.isArray(row)) {\n row.forEach(function (column) {\n return eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null);\n });\n }\n });\n } else if (hasComps) {\n eachComponent(component.components, fn, includeAll, subPath(), parent ? component : null);\n }\n }\n });\n}\n\n/**\n * Matches if a component matches the query.\n *\n * @param component\n * @param query\n * @return {boolean}\n */\nfunction matchComponent(component, query) {\n if (_lodash2.default.isString(query)) {\n return component.key === query;\n } else {\n var matches = false;\n _lodash2.default.forOwn(query, function (value, key) {\n matches = _lodash2.default.get(component, key) === value;\n if (!matches) {\n return false;\n }\n });\n return matches;\n }\n}\n\n/**\n * Get a component by its key\n *\n * @param {Object} components\n * The components to iterate.\n * @param {String|Object} key\n * The key of the component to get, or a query of the component to search.\n *\n * @returns {Object}\n * The component that matches the given key, or undefined if not found.\n */\nfunction getComponent(components, key, includeAll) {\n var result = void 0;\n eachComponent(components, function (component, path) {\n if (matchComponent(component, key)) {\n component.path = path;\n result = component;\n return true;\n }\n }, includeAll);\n return result;\n}\n\n/**\n * Finds a component provided a query of properties of that component.\n *\n * @param components\n * @param query\n * @return {*}\n */\nfunction findComponents(components, query) {\n var results = [];\n eachComponent(components, function (component, path) {\n if (matchComponent(component, query)) {\n component.path = path;\n results.push(component);\n }\n }, true);\n return results;\n}\n\n/**\n * Flatten the form components for data manipulation.\n *\n * @param {Object} components\n * The components to iterate.\n * @param {Boolean} includeAll\n * Whether or not to include layout components.\n *\n * @returns {Object}\n * The flattened components map.\n */\nfunction flattenComponents(components, includeAll) {\n var flattened = {};\n eachComponent(components, function (component, path) {\n flattened[path] = component;\n }, includeAll);\n return flattened;\n}\n\n/**\n * Returns if this component has a conditional statement.\n *\n * @param component - The component JSON schema.\n *\n * @returns {boolean} - TRUE - This component has a conditional, FALSE - No conditional provided.\n */\nfunction hasCondition(component) {\n return Boolean(component.customConditional || component.conditional && component.conditional.when || component.conditional && component.conditional.json);\n}\n\n/**\n * Extension of standard #parseFloat(value) function, that also clears input string.\n *\n * @param {any} value\n * The value to parse.\n *\n * @returns {Number}\n * Parsed value.\n */\nfunction parseFloatExt(value) {\n return parseFloat(_lodash2.default.isString(value) ? value.replace(/[^\\de.+-]/gi, '') : value);\n}\n\n/**\n * Formats provided value in way how Currency component uses it.\n *\n * @param {any} value\n * The value to format.\n *\n * @returns {String}\n * Value formatted for Currency component.\n */\nfunction formatAsCurrency(value) {\n var parsedValue = parseFloatExt(value);\n\n if (_lodash2.default.isNaN(parsedValue)) {\n return '';\n }\n\n var parts = _lodash2.default.round(parsedValue, 2).toString().split('.');\n parts[0] = _lodash2.default.chunk(Array.from(parts[0]).reverse(), 3).reverse().map(function (part) {\n return part.reverse().join('');\n }).join(',');\n parts[1] = _lodash2.default.pad(parts[1], 2, '0');\n return parts.join('.');\n}\n\n/**\n * Escapes RegEx characters in provided String value.\n *\n * @param {String} value\n * String for escaping RegEx characters.\n * @returns {string}\n * String with escaped RegEx characters.\n */\nfunction escapeRegExCharacters(value) {\n return value.replace(/[-[\\]/{}()*+?.\\\\^$|]/g, '\\\\$&');\n}\n\n/**\n * Checks the calculated value for a provided component and data.\n *\n * @param {Object} component\n * The component to check for the calculated value.\n * @param {Object} submission\n * A submission object.\n * @param data\n * The full submission data.\n */\nfunction checkCalculated(component, submission, rowData) {\n // Process calculated value stuff if present.\n if (component.calculateValue) {\n _lodash2.default.set(rowData, component.key, evaluate(component.calculateValue, {\n value: undefined,\n data: submission ? submission.data : rowData,\n row: rowData,\n util: this,\n component: component\n }, 'value'));\n }\n}\n\n/**\n * Check if a simple conditional evaluates to true.\n *\n * @param condition\n * @param condition\n * @param row\n * @param data\n * @returns {boolean}\n */\nfunction checkSimpleConditional(component, condition, row, data) {\n var value = null;\n if (row) {\n value = getValue({ data: row }, condition.when);\n }\n if (data && _lodash2.default.isNil(value)) {\n value = getValue({ data: data }, condition.when);\n }\n // FOR-400 - Fix issue where falsey values were being evaluated as show=true\n if (_lodash2.default.isNil(value)) {\n value = '';\n }\n // Special check for selectboxes component.\n if (_lodash2.default.isObject(value) && _lodash2.default.has(value, condition.eq)) {\n return value[condition.eq].toString() === condition.show.toString();\n }\n // FOR-179 - Check for multiple values.\n if (Array.isArray(value) && value.indexOf(condition.eq) !== -1) {\n return condition.show.toString() === 'true';\n }\n\n return value.toString() === condition.eq.toString() === (condition.show.toString() === 'true');\n}\n\n/**\n * Check custom javascript conditional.\n *\n * @param component\n * @param custom\n * @param row\n * @param data\n * @returns {*}\n */\nfunction checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {\n if (typeof custom === 'string') {\n custom = 'var ' + variable + ' = true; ' + custom + '; return ' + variable + ';';\n }\n var value = instance && instance.evaluate ? instance.evaluate(custom, { row: row, data: data, form: form }) : evaluate(custom, { row: row, data: data, form: form });\n if (value === null) {\n return onError;\n }\n return value;\n}\n\nfunction checkJsonConditional(component, json, row, data, form, onError) {\n try {\n return _jsonLogicJs2.default.apply(json, {\n data: data,\n row: row,\n form: form,\n _: _lodash2.default\n });\n } catch (err) {\n console.warn('An error occurred in jsonLogic advanced condition for ' + component.key, err);\n return onError;\n }\n}\n\n/**\n * Checks the conditions for a provided component and data.\n *\n * @param component\n * The component to check for the condition.\n * @param row\n * The data within a row\n * @param data\n * The full submission data.\n *\n * @returns {boolean}\n */\nfunction checkCondition(component, row, data, form, instance) {\n if (component.customConditional) {\n return checkCustomConditional(component, component.customConditional, row, data, form, 'show', true, instance);\n } else if (component.conditional && component.conditional.when) {\n return checkSimpleConditional(component, component.conditional, row, data, true);\n } else if (component.conditional && component.conditional.json) {\n return checkJsonConditional(component, component.conditional.json, row, data, form, instance);\n }\n\n // Default to show.\n return true;\n}\n\n/**\n * Test a trigger on a component.\n *\n * @param component\n * @param action\n * @param data\n * @param row\n * @returns {mixed}\n */\nfunction checkTrigger(component, trigger, row, data, form, instance) {\n switch (trigger.type) {\n case 'simple':\n return checkSimpleConditional(component, trigger.simple, row, data);\n case 'javascript':\n return checkCustomConditional(component, trigger.javascript, row, data, form, 'result', false, instance);\n case 'json':\n return checkJsonConditional(component, trigger.json, row, data, form, false);\n }\n // If none of the types matched, don't fire the trigger.\n return false;\n}\n\nfunction setActionProperty(component, action, row, data, result, instance) {\n switch (action.property.type) {\n case 'boolean':\n if (_lodash2.default.get(component, action.property.value, false).toString() !== action.state.toString()) {\n _lodash2.default.set(component, action.property.value, action.state.toString() === 'true');\n }\n break;\n case 'string':\n {\n var evalData = {\n data: data,\n row: row,\n component: component,\n result: result\n };\n var newValue = instance && instance.interpolate ? instance.interpolate(action.text, evalData) : interpolate(action.text, evalData);\n if (newValue !== _lodash2.default.get(component, action.property.value, '')) {\n _lodash2.default.set(component, action.property.value, newValue);\n }\n break;\n }\n }\n return component;\n}\n\n/**\n * Get the value for a component key, in the given submission.\n *\n * @param {Object} submission\n * A submission object to search.\n * @param {String} key\n * A for components API key to search for.\n */\nfunction getValue(submission, key) {\n var search = function search(data) {\n if (_lodash2.default.isPlainObject(data)) {\n if (_lodash2.default.has(data, key)) {\n return data[key];\n }\n\n var value = null;\n\n _lodash2.default.forOwn(data, function (prop) {\n var result = search(prop);\n if (!_lodash2.default.isNil(result)) {\n value = result;\n return false;\n }\n });\n\n return value;\n } else {\n return null;\n }\n };\n\n return search(submission.data);\n}\n\n/**\n * Interpolate a string and add data replacements.\n *\n * @param string\n * @param data\n * @returns {XML|string|*|void}\n */\nfunction interpolate(string, data) {\n var templateSettings = {\n evaluate: /\\{%(.+?)%\\}/g,\n interpolate: /\\{\\{(.+?)\\}\\}/g,\n escape: /\\{\\{\\{(.+?)\\}\\}\\}/g\n };\n try {\n return _lodash2.default.template(string, templateSettings)(data);\n } catch (err) {\n console.warn('Error interpolating template', err, string, data);\n }\n}\n\n/**\n * Make a filename guaranteed to be unique.\n * @param name\n * @returns {string}\n */\nfunction uniqueName(name) {\n var parts = name.toLowerCase().replace(/[^0-9a-z.]/g, '').split('.');\n var fileName = parts[0];\n var ext = parts.length > 1 ? '.' + _lodash2.default.last(parts) : '';\n return fileName.substr(0, 10) + '-' + guid() + ext;\n}\n\nfunction guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n var r = Math.random() * 16 | 0;\n var v = c === 'x' ? r : r & 0x3 | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Return a translated date setting.\n *\n * @param date\n * @return {*}\n */\nfunction getDateSetting(date) {\n if (_lodash2.default.isNil(date) || _lodash2.default.isNaN(date) || date === '') {\n return null;\n }\n\n if (date instanceof Date) {\n return date;\n } else if (typeof date.toDate === 'function') {\n return date.isValid() ? date.toDate() : null;\n }\n\n var dateSetting = typeof date !== 'string' || date.indexOf('moment(') === -1 ? (0, _moment2.default)(date) : null;\n if (dateSetting && dateSetting.isValid()) {\n return dateSetting.toDate();\n }\n\n dateSetting = null;\n try {\n var value = new Function('moment', 'return ' + date + ';')(_moment2.default);\n if (typeof value === 'string') {\n dateSetting = (0, _moment2.default)(value);\n } else if (typeof value.toDate === 'function') {\n dateSetting = (0, _moment2.default)(value.toDate().toUTCString());\n } else if (value instanceof Date) {\n dateSetting = (0, _moment2.default)(value);\n }\n } catch (e) {\n return null;\n }\n\n if (!dateSetting) {\n return null;\n }\n\n // Ensure this is a date.\n if (!dateSetting.isValid()) {\n return null;\n }\n\n return dateSetting.toDate();\n}\n\nfunction isValidDate(date) {\n return _lodash2.default.isDate(date) && !_lodash2.default.isNaN(date.getDate());\n}\n\nfunction getLocaleDateFormatInfo(locale) {\n var formatInfo = {};\n\n var day = 21;\n var exampleDate = new Date(2017, 11, day);\n var localDateString = exampleDate.toLocaleDateString(locale);\n\n formatInfo.dayFirst = localDateString.slice(0, 2) === day.toString();\n\n return formatInfo;\n}\n\n/**\n * Convert the format from the angular-datepicker module to flatpickr format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToFlatpickr(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y').replace('YYYY', 'Y').replace('YY', 'y')\n\n // Month conversion.\n .replace('MMMM', 'F').replace(/M/g, 'n').replace('nnn', 'M').replace('nn', 'm')\n\n // Day in month.\n .replace(/d/g, 'j').replace('jj', 'd')\n\n // Day in week.\n .replace('EEEE', 'l').replace('EEE', 'D')\n\n // Hours, minutes, seconds\n .replace('HH', 'H').replace('hh', 'h').replace('mm', 'i').replace('ss', 'S').replace(/a/g, 'K');\n}\n\n/**\n * Convert the format from the angular-datepicker module to moment format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToMoment(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y')\n // Day in month.\n .replace(/d/g, 'D')\n // Day in week.\n .replace(/E/g, 'd')\n // AM/PM marker\n .replace(/a/g, 'A');\n}\n\n/**\n * Returns an input mask that is compatible with the input mask library.\n * @param {string} mask - The Form.io input mask.\n * @returns {Array} - The input mask for the mask library.\n */\nfunction getInputMask(mask) {\n if (mask instanceof Array) {\n return mask;\n }\n var maskArray = [];\n maskArray.numeric = true;\n for (var i = 0; i < mask.length; i++) {\n switch (mask[i]) {\n case '9':\n maskArray.push(/\\d/);\n break;\n case 'A':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z]/);\n break;\n case 'a':\n maskArray.numeric = false;\n maskArray.push(/[a-z]/);\n break;\n case '*':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z0-9]/);\n break;\n default:\n maskArray.push(mask[i]);\n break;\n }\n }\n return maskArray;\n}\n\nfunction matchInputMask(value, inputMask) {\n if (!inputMask) {\n return true;\n }\n for (var i = 0; i < inputMask.length; i++) {\n var char = value[i];\n var charPart = inputMask[i];\n\n if (!(_lodash2.default.isRegExp(charPart) && charPart.test(char) || charPart === char)) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction getNumberSeparators() {\n var lang = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'en';\n\n var formattedNumberString = 12345.6789.toLocaleString(lang);\n return {\n delimiter: formattedNumberString.match(/12(.*)345/)[1],\n decimalSeparator: formattedNumberString.match(/345(.*)67/)[1]\n };\n}\n\nfunction getNumberDecimalLimit(component) {\n // Determine the decimal limit. Defaults to 20 but can be overridden by validate.step or decimalLimit settings.\n var decimalLimit = 20;\n var step = _lodash2.default.get(component, 'validate.step', 'any');\n\n if (step !== 'any') {\n var parts = step.toString().split('.');\n if (parts.length > 1) {\n decimalLimit = parts[1].length;\n }\n }\n\n return decimalLimit;\n}\n\nfunction getCurrencyAffixes(_ref) {\n var _ref$currency = _ref.currency,\n currency = _ref$currency === undefined ? 'USD' : _ref$currency,\n decimalLimit = _ref.decimalLimit,\n decimalSeparator = _ref.decimalSeparator,\n lang = _ref.lang;\n\n // Get the prefix and suffix from the localized string.\n var regex = '(.*)?100';\n if (decimalLimit) {\n regex += (decimalSeparator === '.' ? '\\\\.' : decimalSeparator) + '0{' + decimalLimit + '}';\n }\n regex += '(.*)?';\n var parts = 100 .toLocaleString(lang, {\n style: 'currency',\n currency: currency,\n useGrouping: true,\n maximumFractionDigits: decimalLimit,\n minimumFractionDigits: decimalLimit\n }).replace('.', decimalSeparator).match(new RegExp(regex));\n return {\n prefix: parts[1] || '',\n suffix: parts[2] || ''\n };\n}\n\n/**\n * Fetch the field data provided a component.\n *\n * @param data\n * @param component\n * @return {*}\n */\nfunction fieldData(data, component) {\n if (!data) {\n return '';\n }\n if (!component || !component.key) {\n return data;\n }\n if (component.key.indexOf('.') !== -1) {\n var value = data;\n var parts = component.key.split('.');\n var key = '';\n for (var i = 0; i < parts.length; i++) {\n key = parts[i];\n\n // Handle nested resources\n if (value.hasOwnProperty('_id')) {\n value = value.data;\n }\n\n // Return if the key is not found on the value.\n if (!value.hasOwnProperty(key)) {\n return;\n }\n\n // Convert old single field data in submissions to multiple\n if (key === parts[parts.length - 1] && component.multiple && !Array.isArray(value[key])) {\n value[key] = [value[key]];\n }\n\n // Set the value of this key.\n value = value[key];\n }\n return value;\n } else {\n // Convert old single field data in submissions to multiple\n if (component.multiple && !Array.isArray(data[component.key])) {\n data[component.key] = [data[component.key]];\n }\n return data[component.key];\n }\n}\n\n//# sourceURL=webpack:///./lib/utils/utils.js?"); /***/ }), /***/ "./node_modules/json-logic-js/logic.js": /*!*********************************************!*\ !*** ./node_modules/json-logic-js/logic.js ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* globals define,module */\n/*\nUsing a Universal Module Loader that should be browser, require, and AMD friendly\nhttp://ricostacruz.com/cheatsheets/umdjs.html\n*/\n;(function(root, factory) {\n if (true) {\n !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :\n\t\t\t\t__WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else {}\n}(this, function() {\n \"use strict\";\n /* globals console:false */\n\n if ( ! Array.isArray) {\n Array.isArray = function(arg) {\n return Object.prototype.toString.call(arg) === \"[object Array]\";\n };\n }\n\n /**\n * Return an array that contains no duplicates (original not modified)\n * @param {array} array Original reference array\n * @return {array} New array with no duplicates\n */\n function arrayUnique(array) {\n var a = [];\n for (var i=0, l=array.length; i<l; i++) {\n if (a.indexOf(array[i]) === -1) {\n a.push(array[i]);\n }\n }\n return a;\n }\n\n var jsonLogic = {};\n var operations = {\n \"==\": function(a, b) {\n return a == b;\n },\n \"===\": function(a, b) {\n return a === b;\n },\n \"!=\": function(a, b) {\n return a != b;\n },\n \"!==\": function(a, b) {\n return a !== b;\n },\n \">\": function(a, b) {\n return a > b;\n },\n \">=\": function(a, b) {\n return a >= b;\n },\n \"<\": function(a, b, c) {\n return (c === undefined) ? a < b : (a < b) && (b < c);\n },\n \"<=\": function(a, b, c) {\n return (c === undefined) ? a <= b : (a <= b) && (b <= c);\n },\n \"!!\": function(a) {\n return jsonLogic.truthy(a);\n },\n \"!\": function(a) {\n return !jsonLogic.truthy(a);\n },\n \"%\": function(a, b) {\n return a % b;\n },\n \"log\": function(a) {\n console.log(a); return a;\n },\n \"in\": function(a, b) {\n if(!b || typeof b.indexOf === \"undefined\") return false;\n return (b.indexOf(a) !== -1);\n },\n \"cat\": function() {\n return Array.prototype.join.call(arguments, \"\");\n },\n \"substr\":function(source, start, end) {\n if(end < 0){\n // JavaScript doesn't support negative end, this emulates PHP behavior\n var temp = String(source).substr(start);\n return temp.substr(0, temp.length + end);\n }\n return String(source).substr(start, end);\n },\n \"+\": function() {\n return Array.prototype.reduce.call(arguments, function(a, b) {\n return parseFloat(a, 10) + parseFloat(b, 10);\n }, 0);\n },\n \"*\": function() {\n return Array.prototype.reduce.call(arguments, function(a, b) {\n return parseFloat(a, 10) * parseFloat(b, 10);\n });\n },\n \"-\": function(a, b) {\n if(b === undefined) {\n return -a;\n }else{\n return a - b;\n }\n },\n \"/\": function(a, b) {\n return a / b;\n },\n \"min\": function() {\n return Math.min.apply(this, arguments);\n },\n \"max\": function() {\n return Math.max.apply(this, arguments);\n },\n \"merge\": function() {\n return Array.prototype.reduce.call(arguments, function(a, b) {\n return a.concat(b);\n }, []);\n },\n \"var\": function(a, b) {\n var not_found = (b === undefined) ? null : b;\n var data = this;\n if(typeof a === \"undefined\" || a===\"\" || a===null) {\n return data;\n }\n var sub_props = String(a).split(\".\");\n for(var i = 0; i < sub_props.length; i++) {\n if(data === null) {\n return not_found;\n }\n // Descending into data\n data = data[sub_props[i]];\n if(data === undefined) {\n return not_found;\n }\n }\n return data;\n },\n \"missing\": function() {\n /*\n Missing can receive many keys as many arguments, like {\"missing:[1,2]}\n Missing can also receive *one* argument that is an array of keys,\n which typically happens if it's actually acting on the output of another command\n (like 'if' or 'merge')\n */\n\n var missing = [];\n var keys = Array.isArray(arguments[0]) ? arguments[0] : arguments;\n\n for(var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var value = jsonLogic.apply({\"var\": key}, this);\n if(value === null || value === \"\") {\n missing.push(key);\n }\n }\n\n return missing;\n },\n \"missing_some\": function(need_count, options) {\n // missing_some takes two arguments, how many (minimum) items must be present, and an array of keys (just like 'missing') to check for presence.\n var are_missing = jsonLogic.apply({\"missing\": options}, this);\n\n if(options.length - are_missing.length >= need_count) {\n return [];\n }else{\n return are_missing;\n }\n },\n \"method\": function(obj, method, args) {\n return obj[method].apply(obj, args);\n },\n\n };\n\n jsonLogic.is_logic = function(logic) {\n return (\n typeof logic === \"object\" && // An object\n logic !== null && // but not null\n ! Array.isArray(logic) && // and not an array\n Object.keys(logic).length === 1 // with exactly one key\n );\n };\n\n /*\n This helper will defer to the JsonLogic spec as a tie-breaker when different language interpreters define different behavior for the truthiness of primitives. E.g., PHP considers empty arrays to be falsy, but Javascript considers them to be truthy. JsonLogic, as an ecosystem, needs one consistent answer.\n\n Spec and rationale here: http://jsonlogic.com/truthy\n */\n jsonLogic.truthy = function(value) {\n if(Array.isArray(value) && value.length === 0) {\n return false;\n }\n return !! value;\n };\n\n\n jsonLogic.get_operator = function(logic) {\n return Object.keys(logic)[0];\n };\n\n jsonLogic.get_values = function(logic) {\n return logic[jsonLogic.get_operator(logic)];\n };\n\n jsonLogic.apply = function(logic, data) {\n // Does this array contain logic? Only one way to find out.\n if(Array.isArray(logic)) {\n return logic.map(function(l) {\n return jsonLogic.apply(l, data);\n });\n }\n // You've recursed to a primitive, stop!\n if( ! jsonLogic.is_logic(logic) ) {\n return logic;\n }\n\n data = data || {};\n\n var op = jsonLogic.get_operator(logic);\n var values = logic[op];\n var i;\n var current;\n var scopedLogic, scopedData, filtered, initial;\n\n // easy syntax for unary operators, like {\"var\" : \"x\"} instead of strict {\"var\" : [\"x\"]}\n if( ! Array.isArray(values)) {\n values = [values];\n }\n\n // 'if', 'and', and 'or' violate the normal rule of depth-first calculating consequents, let each manage recursion as needed.\n if(op === \"if\" || op == \"?:\") {\n /* 'if' should be called with a odd number of parameters, 3 or greater\n This works on the pattern:\n if( 0 ){ 1 }else{ 2 };\n if( 0 ){ 1 }else if( 2 ){ 3 }else{ 4 };\n if( 0 ){ 1 }else if( 2 ){ 3 }else if( 4 ){ 5 }else{ 6 };\n\n The implementation is:\n For pairs of values (0,1 then 2,3 then 4,5 etc)\n If the first evaluates truthy, evaluate and return the second\n If the first evaluates falsy, jump to the next pair (e.g, 0,1 to 2,3)\n given one parameter, evaluate and return it. (it's an Else and all the If/ElseIf were false)\n given 0 parameters, return NULL (not great practice, but there was no Else)\n */\n for(i = 0; i < values.length - 1; i += 2) {\n if( jsonLogic.truthy( jsonLogic.apply(values[i], data) ) ) {\n return jsonLogic.apply(values[i+1], data);\n }\n }\n if(values.length === i+1) return jsonLogic.apply(values[i], data);\n return null;\n }else if(op === \"and\") { // Return first falsy, or last\n for(i=0; i < values.length; i+=1) {\n current = jsonLogic.apply(values[i], data);\n if( ! jsonLogic.truthy(current)) {\n return current;\n }\n }\n return current; // Last\n }else if(op === \"or\") {// Return first truthy, or last\n for(i=0; i < values.length; i+=1) {\n current = jsonLogic.apply(values[i], data);\n if( jsonLogic.truthy(current) ) {\n return current;\n }\n }\n return current; // Last\n\n\n\n\n }else if(op === 'filter'){\n scopedData = jsonLogic.apply(values[0], data);\n scopedLogic = values[1];\n\n if ( ! Array.isArray(scopedData)) {\n return [];\n }\n // Return only the elements from the array in the first argument,\n // that return truthy when passed to the logic in the second argument.\n // For parity with JavaScript, reindex the returned array\n return scopedData.filter(function(datum){\n return jsonLogic.truthy( jsonLogic.apply(scopedLogic, datum));\n });\n }else if(op === 'map'){\n scopedData = jsonLogic.apply(values[0], data);\n scopedLogic = values[1];\n\n if ( ! Array.isArray(scopedData)) {\n return [];\n }\n\n return scopedData.map(function(datum){\n return jsonLogic.apply(scopedLogic, datum);\n });\n\n }else if(op === 'reduce'){\n scopedData = jsonLogic.apply(values[0], data);\n scopedLogic = values[1];\n initial = typeof values[2] !== 'undefined' ? values[2] : null;\n\n if ( ! Array.isArray(scopedData)) {\n return initial;\n }\n\n return scopedData.reduce(\n function(accumulator, current){\n return jsonLogic.apply(\n scopedLogic,\n {'current':current, 'accumulator':accumulator}\n );\n },\n initial\n );\n\n }else if(op === \"all\") {\n scopedData = jsonLogic.apply(values[0], data);\n scopedLogic = values[1];\n // All of an empty set is false. Note, some and none have correct fallback after the for loop\n if( ! scopedData.length) {\n return false;\n }\n for(i=0; i < scopedData.length; i+=1) {\n if( ! jsonLogic.truthy( jsonLogic.apply(scopedLogic, scopedData[i]) )) {\n return false; // First falsy, short circuit\n }\n }\n return true; // All were truthy\n }else if(op === \"none\") {\n filtered = jsonLogic.apply({'filter' : values}, data);\n return filtered.length === 0;\n\n }else if(op === \"some\") {\n filtered = jsonLogic.apply({'filter' : values}, data);\n return filtered.length > 0;\n }\n\n // Everyone else gets immediate depth-first recursion\n values = values.map(function(val) {\n return jsonLogic.apply(val, data);\n });\n\n\n // The operation is called with \"data\" bound to its \"this\" and \"values\" passed as arguments.\n // Structured commands like % or > can name formal arguments while flexible commands (like missing or merge) can operate on the pseudo-array arguments\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments\n if(typeof operations[op] === \"function\") {\n return operations[op].apply(data, values);\n }else if(op.indexOf(\".\") > 0) { // Contains a dot, and not in the 0th position\n var sub_ops = String(op).split(\".\");\n var operation = operations;\n for(i = 0; i < sub_ops.length; i++) {\n // Descending into operations\n operation = operation[sub_ops[i]];\n if(operation === undefined) {\n throw new Error(\"Unrecognized operation \" + op +\n \" (failed at \" + sub_ops.slice(0, i+1).join(\".\") + \")\");\n }\n }\n\n return operation.apply(data, values);\n }\n\n throw new Error(\"Unrecognized operation \" + op );\n };\n\n jsonLogic.uses_data = function(logic) {\n var collection = [];\n\n if( jsonLogic.is_logic(logic) ) {\n var op = jsonLogic.get_operator(logic);\n var values = logic[op];\n\n if( ! Array.isArray(values)) {\n values = [values];\n }\n\n if(op === \"var\") {\n // This doesn't cover the case where the arg to var is itself a rule.\n collection.push(values[0]);\n }else{\n // Recursion!\n values.map(function(val) {\n collection.push.apply(collection, jsonLogic.uses_data(val) );\n });\n }\n }\n\n return arrayUnique(collection);\n };\n\n jsonLogic.add_operation = function(name, code) {\n operations[name] = code;\n };\n\n jsonLogic.rm_operation = function(name) {\n delete operations[name];\n };\n\n jsonLogic.rule_like = function(rule, pattern) {\n // console.log(\"Is \". JSON.stringify(rule) . \" like \" . JSON.stringify(pattern) . \"?\");\n if(pattern === rule) {\n return true;\n } // TODO : Deep object equivalency?\n if(pattern === \"@\") {\n return true;\n } // Wildcard!\n if(pattern === \"number\") {\n return (typeof rule === \"number\");\n }\n if(pattern === \"string\") {\n return (typeof rule === \"string\");\n }\n if(pattern === \"array\") {\n // !logic test might be superfluous in JavaScript\n return Array.isArray(rule) && ! jsonLogic.is_logic(rule);\n }\n\n if(jsonLogic.is_logic(pattern)) {\n if(jsonLogic.is_logic(rule)) {\n var pattern_op = jsonLogic.get_operator(pattern);\n var rule_op = jsonLogic.get_operator(rule);\n\n if(pattern_op === \"@\" || pattern_op === rule_op) {\n // echo \"\\nOperators match, go deeper\\n\";\n return jsonLogic.rule_like(\n jsonLogic.get_values(rule, false),\n jsonLogic.get_values(pattern, false)\n );\n }\n }\n return false; // pattern is logic, rule isn't, can't be eq\n }\n\n if(Array.isArray(pattern)) {\n if(Array.isArray(rule)) {\n if(pattern.length !== rule.length) {\n return false;\n }\n /*\n Note, array order MATTERS, because we're using this array test logic to consider arguments, where order can matter. (e.g., + is commutative, but '-' or 'if' or 'var' are NOT)\n */\n for(var i = 0; i < pattern.length; i += 1) {\n // If any fa