UNPKG

react-rails-ux-password-field

Version:

A UX forward password field for react-js using react-rails

786 lines (681 loc) 25.8 kB
/*! * React UX Password Field * version: 0.9.22 * * MIT Licensed * github: https://github.com/seethroughtrees/react-ux-password-field/ * demo: https://seethroughtrees.github.io/react-ux-password-field/ * */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("react")); else if(typeof define === 'function' && define.amd) define(["react"], factory); else if(typeof exports === 'object') exports["react-ux-password-field"] = factory(require("react")); else root["react-ux-password-field"] = factory(root["React"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var React = __webpack_require__(1), RP = React.PropTypes, config = __webpack_require__(2), debounce = __webpack_require__(3); var InputPassword = React.createClass({ displayName: 'InputPassword', /*========== VALIDATE ==========*/ propTypes: { infoBar: RP.bool, statusColor: RP.string, statusInactiveColor: RP.string, minScore: RP.number, changeCb: RP.func, toggleMask: RP.bool, unMaskTime: RP.number, minLength: RP.number, strengthLang: RP.array, id: RP.string }, /*========== DEFAULTS ==========*/ getDefaultProps: function getDefaultProps() { return { infoBar: true, statusColor: config.statusColor, statusInactiveColor: config.statusInactiveColor, zxcvbn: config.zxcvbnSrc, minScore: 0, toggleMask: true, unMaskTime: config.unMaskTime, strengthLang: config.strengthLang, id: 'input', name: '', className: 'form-control', placeholder: 'Password' }; }, getInitialState: function getInitialState() { return { value: '', score: 0, entropy: 0, isPassword: true, isValid: false }; }, /*========== STYLES ==========*/ getMeterStyle: function getMeterStyle(score) { var width = this.state.value === '' ? 0 : 24 * score + 4; return { width: this.props.zxcvbn ? width + '%' : '100%', maxWidth: '85%', opacity: this.props.zxcvbn ? width * .01 + .5 : '1', background: this.state.isValid ? this.props.statusColor : this.props.statusInactiveColor, height: 3, transition: 'all 400ms linear', display: 'inline-block', marginRight: '1%', marginLeft: '5px' }; }, unMaskStyle: { color: config.unMaskColor }, infoStyle: { width: '100%', overflow: 'hidden', height: '20px' }, iconStyle: { display: 'inline-block', opacity: .25, position: 'relative', top: 2, width: '3%' }, strengthLangStyle: { fontSize: 12, position: 'relative', top: 2 }, /*========== METHODS ==========*/ addPasswordType: function addPasswordType() { this.setState({ isPassword: true }); }, /*========== HANDLERS ==========*/ handleInputType: function handleInputType() { this.setState({ isPassword: !this.state.isPassword }); }, handleChange: function handleChange(e) { e.preventDefault(); var native_target = e.nativeEvent.target; var val = e.target.value; var score; this.setState({ value: val, isValid: e.target.validity.valid, selectionStart: native_target.selectionStart, selectionEnd: native_target.selectionEnd }); if (this.props.toggleMask) { this.handleToggleMask(); } if (this.props.zxcvbn) { score = this.handleZxcvbn(val); } else { score = this.state.score; } // call onChange prop passed from parent if (this.props.onChange) { this.props.onChange(val, this.state.isValid, score); } if (this.props.minLength) { this.handleMinLength(e.target.value.length); } }, handleToggleMask: function handleToggleMask() { // display password, then this.setState({ isPassword: false }); // debounce remasking password this.maskPassword(); }, handleToggleMaskIcon: function handleToggleMaskIcon() { this.setState({ isPassword: !this.state.isPassword }); }, handleZxcvbn: function handleZxcvbn(val) { if (typeof zxcvbn === 'undefined' && typeof window.zxcvbn === 'undefined') { return; } var stats = zxcvbn(val), currentScore = stats.score; this.setState({ score: currentScore, entropy: stats.entropy }); if (currentScore < this.props.minScore) { this.setState({ isValid: false }); } // if score changed and callback provided if (this.props.changeCb && this.state.score !== currentScore) { this.props.changeCb(this.state.score, currentScore, val); } if (this.props.zxcvbn === 'debug') { console.debug(stats); } return currentScore; }, handleMinLength: function handleMinLength(len) { if (len <= this.props.minLength) { this.setState({ isValid: false }); } }, componentWillMount: function componentWillMount() { var zxcvbnSrc; // Load zxcvbn async if its enabled and doesn't already exist if (this.props.zxcvbn && typeof zxcvbn === 'undefined') { zxcvbnSrc = this.props.zxcvbn !== 'debug' ? this.props.zxcvbn : config.zxcvbnSrc; // snippet to async load zxcvbn if enabled (function () { var a;a = function () { var a, b;b = document.createElement("script");b.src = zxcvbnSrc;b.type = "text/javascript";b.async = !0;a = document.getElementsByTagName("head")[0];return a.parentNode.insertBefore(b, a); };null != window.attachEvent ? window.attachEvent("onload", a) : window.addEventListener("load", a, !1); }).call(this); } // set debouncer for password // if (this.props.toggleMask) { this.maskPassword = debounce(this.addPasswordType, this.props.unMaskTime); // } }, componentWillUnmount: function componentWillUnmount() { // cancel the debouncer when component is not used anymore. This to avoid // setting the state unnecessarily, see issue #24 if (this.maskPassword) { this.maskPassword.cancel(); } }, render: function render() { var infoBar; if (this.props.infoBar) { infoBar = React.createElement( 'div', { className: 'passwordField__info', style: this.infoStyle }, React.createElement( 'span', { style: this.iconStyle, className: 'passwordField__icon' }, React.createElement('img', { src: __webpack_require__(5), height: '10', width: '10' }) ), React.createElement('span', { style: this.getMeterStyle(this.state.score), className: 'passwordField__meter' }), React.createElement( 'span', { style: this.strengthLangStyle, className: 'passwordField__strength' }, this.props.zxcvbn && this.state.value.length > 0 && this.props.strengthLang.length > 0 ? this.props.strengthLang[this.state.score] : null ) ); } // allow onChange to be passed from parent and not override default prop var _props = this.props; var onChange = _props.onChange; var props = _objectWithoutProperties(_props, ['onChange']); // overcome problem with firefox resetting the input selection point var that = this; setTimeout(function () { if (!/Firefox/.test(navigator.userAgent)) return; var elem = that.refs[that.props.id].getDOMNode(); elem.selectionStart = that.state.selectionStart; elem.selectionEnd = that.state.selectionEnd; }, 1); return React.createElement( 'div', { style: { position: 'relative', display: 'block' }, className: 'passwordField', 'data-valid': this.state.isValid, 'data-score': this.state.score, 'data-entropy': this.state.entropy }, React.createElement('input', _extends({ ref: this.props.id, className: this.props.className, type: this.state.isPassword ? 'password' : 'text', name: this.props.name, value: this.state.value, style: this.state.isPassword ? null : this.unMaskStyle, onChange: this.handleChange, placeholder: this.props.placeholder }, props)), React.createElement('img', { src: __webpack_require__(6), className: this.state.isPassword ? 'passwordField__mask-icon' : 'active passwordField__mask-icon', onClick: this.handleToggleMaskIcon }), this.state.value.length > 0 ? React.createElement( 'div', null, infoBar ) : null ); } }); module.exports = InputPassword; /***/ }, /* 1 */ /***/ function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_1__; /***/ }, /* 2 */ /***/ function(module, exports) { 'use strict'; module.exports = { statusColor: '#5CE592', statusInactiveColor: '#FC6F6F', unMaskColor: '#000000', unMaskTime: 1400, zxcvbnSrc: 'https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/1.0/zxcvbn.min.js', strengthLang: ['Weak', 'Okay', 'Good', 'Strong', 'Great'] }; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { /** * lodash 3.1.1 (Custom Build) <https://lodash.com/> * Build: `lodash modern modularize exports="npm" -o ./` * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <https://lodash.com/license> */ 'use strict'; var getNative = __webpack_require__(4); /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; /* Native method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max, nativeNow = getNative(Date, 'now'); /** * Gets the number of milliseconds that have elapsed since the Unix epoch * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @category Date * @example * * _.defer(function(stamp) { * console.log(_.now() - stamp); * }, _.now()); * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function () { return new Date().getTime(); }; /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel * delayed invocations. Provide an options object to indicate that `func` * should be invoked on the leading and/or trailing edge of the `wait` timeout. * Subsequent calls to the debounced function return the result of the last * `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ * @category Function * @param {Function} func The function to debounce. * @param {number} [wait=0] The number of milliseconds to delay. * @param {Object} [options] The options object. * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be * delayed before it is invoked. * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })); * * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * })); * * // cancel a debounced call * var todoChanges = _.debounce(batchLog, 1000); * Object.observe(models.todo, todoChanges); * * Object.observe(models, function(changes) { * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { * todoChanges.cancel(); * } * }, ['delete']); * * // ...at some point `models.todo` is changed * models.todo.completed = true; * * // ...before 1 second has passed `models.todo` is deleted * // which cancels the debounced `todoChanges` call * delete models.todo; */ function debounce(func, wait, options) { var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } wait = wait < 0 ? 0 : +wait || 0; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = !!options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? !!options.trailing : trailing; } function cancel() { if (timeoutId) { clearTimeout(timeoutId); } if (maxTimeoutId) { clearTimeout(maxTimeoutId); } lastCalled = 0; maxTimeoutId = timeoutId = trailingCall = undefined; } function complete(isCalled, id) { if (id) { clearTimeout(id); } maxTimeoutId = timeoutId = trailingCall = undefined; if (isCalled) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = undefined; } } } function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { complete(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { complete(trailing, timeoutId); } function debounced() { args = arguments; stamp = now(); thisArg = this; trailingCall = trailing && (timeoutId || !leading); if (maxWait === false) { var leadingCall = leading && !timeoutId; } else { if (!maxTimeoutId && !leading) { lastCalled = stamp; } var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; if (isCalled) { if (maxTimeoutId) { maxTimeoutId = clearTimeout(maxTimeoutId); } lastCalled = stamp; result = func.apply(thisArg, args); } else if (!maxTimeoutId) { maxTimeoutId = setTimeout(maxDelayed, remaining); } } if (isCalled && timeoutId) { timeoutId = clearTimeout(timeoutId); } else if (!timeoutId && wait !== maxWait) { timeoutId = setTimeout(delayed, wait); } if (leadingCall) { isCalled = true; result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { args = thisArg = undefined; } return result; } debounced.cancel = cancel; return debounced; } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(1); * // => false */ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; return !!value && (type == 'object' || type == 'function'); } module.exports = debounce; /***/ }, /* 4 */ /***/ function(module, exports) { /** * lodash 3.9.1 (Custom Build) <https://lodash.com/> * Build: `lodash modern modularize exports="npm" -o ./` * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <https://lodash.com/license> */ /** `Object#toString` result references. */ 'use strict'; var funcTag = '[object Function]'; /** Used to detect host constructors (Safari > 5). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** * Checks if `value` is object-like. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { return !!value && typeof value == 'object'; } /** Used for native method references. */ var objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'); /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = object == null ? undefined : object[key]; return isNative(value) ? value : undefined; } /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. return isObject(value) && objToString.call(value) == funcTag; } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(1); * // => false */ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is a native function. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, else `false`. * @example * * _.isNative(Array.prototype.push); * // => true * * _.isNative(_); * // => false */ function isNative(value) { if (value == null) { return false; } if (isFunction(value)) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && reIsHostCtor.test(value); } module.exports = getNative; /***/ }, /* 5 */ /***/ function(module, exports) { module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRkNDMzg4M0FFN0IxMUU0OTE2RkY5MzYyMkI3QTVDMiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRkNDMzg4NEFFN0IxMUU0OTE2RkY5MzYyMkI3QTVDMiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJGQ0MzODgxQUU3QjExRTQ5MTZGRjkzNjIyQjdBNUMyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJGQ0MzODgyQUU3QjExRTQ5MTZGRjkzNjIyQjdBNUMyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+NkztvAAAAc9JREFUeNq8lk8oBFEcx2fG5k+0HJRQ/iVy2U1tUsjBzYnI2cUWJyl3XJRSkgOtxEU4keLgQP6kuColoeQgEkXWand8X/3UNM28Z56Z961PO2/fb9535r3f/N7TTdPUnBSLxTSBcsEA6AW1IAw+wD3YAtPg0+1mXdK4DJyAKk7MM+gE506dhuZdleBSYMpUDM5Ah1NnyKOpDnZpWn91C/ZBksZrBhFL/zaopyWQNh4HDZZ2AsQd4kbBFF3ngRnQ8581vgHVdH0M2jgPeWjpz1BePMqscdRiyrQhiF+25VK7bHI12toXgvg9+yTKGpc6TDtPD+DJ0i6RNS6ytZOC+IwtpkA2q1epKLyDb/D2h3uGQQXIBqcyWd1FBeEOZNFM1YEckHYpTGzgKyqbpmWp1kEq9IeCcQRaNP80CZoMQclb8NmUqRys8IxZpenTglHUEOxAhQEZ5/OM01qAMnwah+3Ng2BTpTGr2a1gHnSDCVXGs7Z2QpVxjUNSKjGeo29T+RuHqaRqtOdGVGZ1in6/VH9OYZet01Uhnx5qBLyAIT+MvVQulslLflWuazq+BKFXnvEaWAzI+IA31ezUMEaJE6dDQYb+9yrdMrs7oP9HgAEAXmVa5ulD/g0AAAAASUVORK5CYII=" /***/ }, /* 6 */ /***/ function(module, exports) { module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAMCAYAAACNzvbFAAAAAXNSR0IArs4c6QAAAs5JREFUKBV1UkloFEEU/VXV3bObzShGMi5JEE/J5OItifEiSERFvAgBFVwuiqIXs4GJ6EE06kEUwYN6EQyioOBB48zdDBHcEolG1GQwIVvPdLq66vt7wuDE5R+q/n/136vq/5rBf6LlwtB6pbCdI2ujlhrUGGOczVP+CRCfIBN3k131Y/+isz/BbeffrJbau8YYtEVjJUbWtpknJafaRQDLMAQGAiE3m7U51QMiFD4+eHrTz2IdXly09L4+RIIjpaWVu9ZU14UW5uellt4VU/B4srsxZHIe11JfdnI5XRWvCZSUrdyjc9mPxNtbrJN/KSKy5r6hG0IE9ldUrYuaVhAyX0cWlOt0DnYlrhYT/Lyld+iEsIJ9q6rroq6ThamJLwvak/fo4mP+OTt8E813mfSAGQhtLVu9MQKcgXIXYfrb6Ndkd0M8L3JnLMh+zLTimtIXgwc2OD7WdC49Xr62ttqwAkDzhtnMZ9t17EetnQ3t/P1kut8KxFpjq2ojEhl4moHj2EBmJH2yH3p85jai8dDflxBaGaZy9EpJ/T4vVLkhYgaiu1/0pq8b9OlTSkuUisZObvihUABwMPOFvzCcV8ojs9B3vxCmRg55HhBPa9DKIzmY5amexm4lnVv25OjCovTAJXEtgkRkzS0v0fAV/FkJAVsKM1vCWRMaIRIFcIlnZ8gD6dxP9STO5t1PdSVOoXIuycwHW2bnQHESNcNRLzXUU3jWYEciXcjzOJ1LsGCRRrVIPKXci8nuxBG/Z9l/2tQ33IRa3UerpFyHK8JibtwG5T0GwfpFmfkW59zN2oWTTBg79Yp4BJzpHHNmZ7nQB191ND4rXLpM1Afbbn4Pz0xM9tEcj6IIeaC9CEPJyDjqZRqFBSCsHEibccQbwbDoeX6mnpz9HX+JFo52XBgum3H1Ps5wO2GbkLFyhjhNhPfk49NoLPrg2fG6uUJ/8f4LzjVgGa5Fw28AAAAASUVORK5CYII=" /***/ } /******/ ]) }); ;