UNPKG

@mopinion/survey

Version:

Collect customer feedback with the Mopinion survey library

632 lines (631 loc) 27.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.EventObserver = void 0; var _preact = require("preact"); var _components = require("../../../components"); var _form = require("../../form"); var _utils = require("../../../utils"); var _constants = require("../../../constants"); 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 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 _objectSpread(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 _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } 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 _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } 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 _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 _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 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), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), 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 _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 _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } 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 _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 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); } var USER_TOUCHING = false; var dimmerText = (0, _preact.createRef)(); var findFirstFocusableElement = function findFirstFocusableElement() { return (0, _utils.nodeListToArray)(document.getElementsByTagName('*')).filter(isFocusable)[0]; }; var elementVisible = function elementVisible(element) { var _element$getBoundingC, _element$getBoundingC2; if (!element) { return false; } return ((_element$getBoundingC = element.getBoundingClientRect()) === null || _element$getBoundingC === void 0 ? void 0 : _element$getBoundingC.x) > 0 && ((_element$getBoundingC2 = element.getBoundingClientRect()) === null || _element$getBoundingC2 === void 0 ? void 0 : _element$getBoundingC2.y) > 0; }; var isFocusable = function isFocusable(element) { if (element.tabIndex < 0 || element.offsetParent === null || elementVisible(element) === false) { return false; } switch (element.tagName) { case 'DIV': return true; case 'A': return !!element.href; case 'INPUT': return element.type !== 'hidden' && !element.disabled; case 'SELECT': case 'TEXTAREA': case 'BUTTON': return !element.disabled; default: return false; } }; var EventObserver = exports.EventObserver = function (_Component) { function EventObserver() { var _this; _classCallCheck(this, EventObserver); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, EventObserver, [].concat(args)); _defineProperty(_this, "onMouseMove", function (e) { if (_this.props.showCapture) _this.props.onMouseMove(e); }); _defineProperty(_this, "onClick", function (e) { if (_this.props.showCapture && !USER_TOUCHING) _this.props.onClick(e); }); _defineProperty(_this, "onKeyDown", function (e) { if (_this.props.showCapture && !USER_TOUCHING) _this.props.onKeyDown(e); }); _defineProperty(_this, "onKeyUp", function (e) { e.stopPropagation(); if (_this.props.showCapture && !USER_TOUCHING) _this.props.onKeyUp(e); }); _defineProperty(_this, "onScroll", function (e) { _this.props.onScroll(e); }); _defineProperty(_this, "onTouchEnd", function (e) { USER_TOUCHING = true; if (_this.props.showCapture && typeof _this.props.onClick === 'function') _this.props.onClick(e); }); return _this; } _inherits(EventObserver, _Component); return _createClass(EventObserver, [{ key: "componentDidMount", value: function componentDidMount() { var _this2 = this; try { dimmerText.current.focus(); } catch (e) {} typeof this.props.onMouseMove === 'function' && window.addEventListener('mousemove', this.onMouseMove); typeof this.props.onScroll === 'function' && window.addEventListener('scroll', this.onScroll); typeof this.props.onClick === 'function' && setTimeout(function () { window.addEventListener('mousedown', _this2.onClick); window.addEventListener('click', _this2.onClick); }); typeof this.props.onKeyDown === 'function' && setTimeout(function () { window.addEventListener('keydown', _this2.onKeyDown); }); typeof this.props.onKeyUp === 'function' && setTimeout(function () { window.addEventListener('keyup', _this2.onKeyUp); }); window.addEventListener('touchend', this.onTouchEnd); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { window.removeEventListener('mousemove', this.onMouseMove); window.removeEventListener('scroll', this.onScroll); window.removeEventListener('mousedown', this.onClick); window.removeEventListener('click', this.onClick); window.removeEventListener('touchstart', this.onTouchEnd); window.removeEventListener('keydown', this.onKeyDown); window.removeEventListener('keyup', this.onKeyUp); } }, { key: "render", value: function render(_ref) { var children = _ref.children; return children; } }]); }(_preact.Component); var initialState = { dimTop: {}, dimRight: {}, dimLeft: {}, dimBottom: {}, dimHighlight: {}, selectedTarget: false, dom: {}, selector: {} }; var Capture = exports["default"] = function (_Component2) { function Capture(props) { var _this3; _classCallCheck(this, Capture); _this3 = _callSuper(this, Capture, [props]); _this3.state = initialState; return _this3; } _inherits(Capture, _Component2); return _createClass(Capture, [{ key: "mouseMove", value: function mouseMove(e) { if (!this.state.selectedTarget && !USER_TOUCHING) { this.setDim(e.target); } } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { if (!prevProps.screenshotActive && this.props.screenshotActive) { this.setState({ dimTop: {}, dimRight: {}, dimLeft: {}, dimBottom: {}, dimHighlight: {}, selectedTarget: false }); } } }, { key: "anonymizeDOM", value: function anonymizeDOM(doc) { var html = doc.querySelector('html'); (0, _utils.nodeListToArray)(html.querySelectorAll('script')).forEach(function (node) { try { node.parentNode.removeChild(node); } catch (e) {} }); var replaceCharactersInAttributesRegex = /(<|>|%3C|%3E|\\u003C|\\u003E)/gi; (0, _utils.nodeListToArray)(html.querySelectorAll('*')).forEach(function (node) { try { if (!node.hasAttributes()) { return; } var _iterator = _createForOfIteratorHelper(node.attributes), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var attr = _step.value; if (replaceCharactersInAttributesRegex.test(attr.value)) { attr.value = attr.value.replace(replaceCharactersInAttributesRegex, ''); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } catch (e) { (0, _utils.log)(e); } }); var dimmer = html.querySelector('#mopinion_dimmer_overlay'); if (dimmer) { dimmer.parentNode.removeChild(dimmer); } var maskArray = ['[data-mop-supress]']; if (this.props.block.properties.hasOwnProperty('maskedSelectors')) { maskArray = [].concat(_toConsumableArray(maskArray), [this.props.block.properties.maskedSelectors]); } (0, _utils.nodeListToArray)(html.querySelectorAll('input, select, textarea')).forEach(function (el) { try { (0, _utils.anonymizeValue)(el); } catch (e) {} try { el.checked = false; } catch (e) {} try { el.setAttribute('data-mopinion-mask-input', ''); } catch (e) {} }); maskArray.forEach(function (selector) { try { (0, _utils.nodeListToArray)(html.querySelectorAll(selector)).forEach(function (elementToMask) { elementToMask.setAttribute('data-mopinion-mask-extra', ''); }); } catch (e) {} }); var base = html.querySelector('base'); if (!base) { var newBase = doc.createElement('base'); newBase.href = window.location.origin; (0, _utils.prependChild)(doc.querySelector('head'), newBase); } else if (base) { var newBaseHref = base.href.indexOf(window.location.origin) === -1 ? "".concat(window.location.origin).concat(base.href.charAt(0) === '/' ? base.href : '/' + base.href) : base.href; base.href = newBaseHref; } return (0, _utils.encodeQuotes)(html.outerHTML.replace(/(\r\n|\n|\r|\u2028|\u2029)/gm, '').trim()); } }, { key: "anonymizeSelector", value: function anonymizeSelector(target) { var block = this.props.block; var maskArray = ['[data-mop-supress]']; if (block.properties.hasOwnProperty('maskedSelectors') && (0, _utils.isArray)(block.properties.maskedSelectors)) { maskArray = [].concat(_toConsumableArray(maskArray), _toConsumableArray(block.properties.maskedSelectors)); } try { if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(target.tagName) > -1) { (0, _utils.anonymizeValue)(target); } } catch (e) {} (0, _utils.nodeListToArray)(target.querySelectorAll('input, select, textarea')).forEach(function (el) { try { (0, _utils.anonymizeValue)(el); } catch (e) {} try { el.checked = false; } catch (e) {} try { el.setAttribute('data-mopinion-mask-input', ''); } catch (e) {} }); maskArray.forEach(function (selector) { if (typeof selector === 'string') { var selectorEl = document.querySelector(selector); if (selectorEl && target.isEqualNode(selectorEl)) { target.innerHTML = '***'; } else { (0, _utils.nodeListToArray)(target.querySelectorAll(selector)).forEach(function (element) { element.innerHTML = '***'; }); } } }); return target.outerHTML.replace(/(\r\n|\n|\r)/gm, ' ').trim(); } }, { key: "onClick", value: function onClick(e) { var _this$dimmer, _this$props$contentDi, _this4 = this; var fromTouchButton = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (!this.props.showCapture) { return; } if (this.props.formType === 'embed' && this.state.selectedTarget) { return; } if (e.type !== 'mousedown') { e.preventDefault(); } e.stopPropagation(); if (!this.state.selectedTarget && !((_this$dimmer = this.dimmer) !== null && _this$dimmer !== void 0 && _this$dimmer.contains(e.target)) || USER_TOUCHING || (_this$props$contentDi = this.props.contentDivRef) !== null && _this$props$contentDi !== void 0 && (_this$props$contentDi = _this$props$contentDi.current) !== null && _this$props$contentDi !== void 0 && _this$props$contentDi.contains(e.selectedTarget)) { var target = e.target; if (USER_TOUCHING && !(0, _utils.hasClass)(e.target, 'btn-select-touch')) { return this.setDim(e.target, true); } else if (USER_TOUCHING && (0, _utils.hasClass)(e.target, 'btn-select-touch')) { target = this.state.selectedTarget; } try { document.querySelector('[data-mopinion-screen-capture]').removeAttribute('[data-mopinion-screen-capture]'); } catch (e) {} target.setAttribute('data-mopinion-screen-capture', ''); var selector = this.anonymizeSelector(target.cloneNode(true)); var documentWithCss = this.applyCollectedCss(document.cloneNode(true)); var dom = this.anonymizeDOM(documentWithCss); return this.setState(function () { return { dom: dom, selector: selector }; }, function () { _this4.setDim(target, true); _this4.props.setScreenshot({ dom: _this4.state.dom, selector: _this4.state.selector, value: _constants.screenshotIsRendering }); _this4.props.toggleCapture(false); }); } } }, { key: "applyCollectedCss", value: function applyCollectedCss(clonedDoc) { var styles = ''; var _iterator2 = _createForOfIteratorHelper(document.styleSheets), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var sheet = _step2.value; try { var _iterator4 = _createForOfIteratorHelper(sheet.cssRules), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var rule = _step4.value; styles += rule.cssText; } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } var ownerNode = sheet.ownerNode; var _iterator5 = _createForOfIteratorHelper(clonedDoc.querySelectorAll(ownerNode.nodeName)), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var matchingNode = _step5.value; if (ownerNode.isEqualNode(matchingNode)) { matchingNode.parentNode.removeChild(matchingNode); } } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } } catch (e) { (0, _utils.log)({ e: e, sheet: sheet }); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } var _iterator3 = _createForOfIteratorHelper(clonedDoc.querySelectorAll('style')), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var inlineStyleNode = _step3.value; try { inlineStyleNode.parentNode.removeChild(inlineStyleNode); } catch (e) { (0, _utils.log)(e); } } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } var styleNode = clonedDoc.createElement('style'); styleNode.appendChild(document.createTextNode(styles)); clonedDoc.head.appendChild(styleNode); return clonedDoc; } }, { key: "onKeyDown", value: function onKeyDown(e) { if (e.key === 'Escape') { this.props.toggleCapture(false); this.props.setScreenshot({ dom: '', selector: '', value: '' }); this.setState(initialState); } if (['Enter', 'Space'].indexOf(e.code) > -1) { e.stopPropagation(); this.onClick(e); } } }, { key: "onKeyUp", value: function onKeyUp(e) { if (e.key === 'Tab') { this.setDim(e.target); } } }, { key: "onScroll", value: function onScroll(e) { if (this.state.selectedTarget) { this.setDim(this.state.selectedTarget, true); } } }, { key: "setDim", value: function setDim(target, selected) { var _this5 = this; var position = target.getBoundingClientRect(); var borderWidth = 3; var dimStyle = { position: 'fixed', background: 'rgba(0,0,0,.3)', pointerEvents: 'none' }; this.setState(function () { var newState = { dimTop: Object.assign({}, dimStyle, { top: 0, height: position.top, left: 0, right: 0 }), dimRight: Object.assign({}, dimStyle, { top: position.top, height: position.height, width: window.innerWidth - position.right, right: 0 }), dimBottom: Object.assign({}, dimStyle, { top: position.bottom, bottom: 0, left: 0, right: 0 }), dimLeft: Object.assign({}, dimStyle, { top: position.top, height: position.height, left: 0, width: position.left }) }; if (target && selected) { newState.dimHighlight = { position: 'fixed', top: position.top - borderWidth, left: position.left - borderWidth, height: position.height + borderWidth * 2, width: position.width + borderWidth * 2 }; newState.selectedTarget = target; } else { newState.dimHighlight = {}; newState.tempHighlight = { position: 'fixed', top: position.top - borderWidth, left: position.left - borderWidth, height: position.height + borderWidth * 2, width: position.width + borderWidth * 2 }; if (_this5.props.formType === 'embed') { newState.tempHighlight.borderColor = '#B6B6B6'; } } return _objectSpread({}, newState); }); } }, { key: "render", value: function render(props, state, context) { var _this6 = this; if (!props.showCapture) { return null; } return (0, _preact.h)("div", null, (0, _preact.h)(_components.Portal, { into: document.body }, (0, _preact.h)(EventObserver, { onMouseMove: function onMouseMove(e) { _this6.mouseMove(e); }, onClick: function onClick(e) { _this6.onClick(e); }, onKeyDown: function onKeyDown(e) { _this6.onKeyDown(e); }, onKeyUp: function onKeyUp(e) { _this6.onKeyUp(e); }, onScroll: function onScroll(e) { _this6.onScroll(e); }, showCapture: props.screenshotActive, dimmerRef: this.dimmerNode }, (0, _preact.h)("div", { style: { zIndex: 1999999998 }, id: "mopinion_dimmer_overlay", "data-dimmer-for": props.formKey, "class": props.themeClass + ' mopinion-dimmer wcag', ref: function ref(node) { return _this6.dimmer = node; } }, (0, _preact.h)("div", { "class": "dimmer-border" }), (0, _preact.h)("div", { "class": "dimmer-actions" }, Object.keys(state.dimHighlight).length === 0 && (0, _preact.h)("div", { "class": "dimmer-text", id: "dimmer-text", tabIndex: 0, ref: dimmerText }, (0, _preact.h)(_form.SvgIcon, { key: "mouse", icon: "mouse-pointer", style: { marginRight: '10px' }, alt: "mouse-pointer icon" }), props.text.screenCaptureText), Object.keys(state.dimHighlight).length > 0 && (0, _preact.h)("div", null, (0, _preact.h)(_form.SvgIcon, { key: "check", icon: "check", style: { marginRight: '10px' }, alt: "check icon" }), props.text.screenCaptureSelected), (0, _preact.h)("button", { "class": "dimmer-cancel", onClick: function onClick() { _this6.props.toggleCapture(false); _this6.props.setScreenshot({ dom: '', selector: '', value: '' }); _this6.setState(initialState); }, onKeyDown: function onKeyDown(e) { if (['Enter', 'Space'].indexOf(e.key) > -1) { e.stopPropagation(); _this6.props.toggleCapture(false); _this6.props.setScreenshot({ dom: '', selector: '', value: '' }); _this6.setState(initialState); } if (e.key === 'Tab' && !e.shiftKey) { var _findFirstFocusableEl; e.preventDefault(); document.activeElement.blur(); (_findFirstFocusableEl = findFirstFocusableElement()) === null || _findFirstFocusableEl === void 0 || _findFirstFocusableEl.focus(); } }, "aria-label": "Cancel" }, "\xD7")), Object.keys(state.dimTop).length > 0 && (0, _preact.h)("div", null, !props.hideBackdrop && (0, _preact.h)("div", null, (0, _preact.h)("div", { style: state.dimTop }), (0, _preact.h)("div", { style: state.dimRight }), (0, _preact.h)("div", { style: state.dimBottom }), (0, _preact.h)("div", { style: state.dimLeft })), Object.keys(state.dimHighlight).length ? (0, _preact.h)("div", { "class": "dimmer-highlight dimmer-selected", style: state.dimHighlight, onClick: function onClick(e) { e.preventDefault(); e.stopPropagation(); } }, USER_TOUCHING ? (0, _preact.h)("button", { type: "button", "class": "btn-select-touch" }, props.text.screenCaptureTouchBtnText) : null) : Object.keys(state.tempHighlight).length > 0 ? (0, _preact.h)("div", { "class": "dimmer-highlight", style: state.tempHighlight, onClick: function onClick(e) { e.preventDefault(); e.stopPropagation(); } }) : null), Object.keys(state.dimTop).length === 0 && (0, _preact.h)("div", null, (0, _preact.h)("div", { style: { position: 'fixed', top: 0, right: 0, bottom: 0, left: 0, background: 'rgba(0,0,0,.3)' } }), (0, _preact.h)("div", { "class": "capture-hint" }, !USER_TOUCHING ? (0, _preact.h)(_form.SvgIcon, { icon: "mouse-pointer", alt: "mouse pointer icon" }) : (0, _preact.h)(_form.SvgIcon, { icon: "hand-pointer-o", alt: "hand pointer icon" }), (0, _preact.h)("div", null, props.text.screenCaptureHint))))))); } }]); }(_preact.Component); //# sourceMappingURL=Capture.js.map