UNPKG

@nguyenmv2/buy-button

Version:

BuyButton.js allows merchants to build Shopify interfaces into any website

378 lines (306 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _morphdom = _interopRequireDefault(require("morphdom")); var _template = _interopRequireDefault(require("./template")); var _iframe = _interopRequireDefault(require("./iframe")); var _all = _interopRequireDefault(require("./styles/embeds/all")); var _elementClass = require("./utils/element-class"); var _focus = require("./utils/focus"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var delegateEventSplitter = /^(\S+)\s*(.*)$/; var ESC_KEY = 27; var View = /*#__PURE__*/ function () { function View(component) { this.component = component; this.iframe = null; this.node = this.component.node; this.template = new _template.default(this.component.options.templates, this.component.options.contents, this.component.options.order); this.eventsBound = false; } var _proto = View.prototype; _proto.init = function init() { this.component.node.className += " shopify-buy-frame shopify-buy-frame--".concat(this.component.typeKey); if (this.iframe || !this.component.options.iframe) { return Promise.resolve(this.iframe); } this.iframe = new _iframe.default(this.component.node, { classes: this.component.classes, customStyles: this.component.styles, stylesheet: _all.default[this.component.typeKey], browserFeatures: this.component.props.browserFeatures, googleFonts: this.component.googleFonts, name: this.component.name, width: this.component.options.layout === 'vertical' ? this.component.options.width : null }); this.iframe.addClass(this.className); return this.iframe.load(); } /** * renders string template using viewData to wrapper element. */ ; _proto.render = function render() { var _this = this; this.component._userEvent('beforeRender'); var html = this.template.render({ data: this.component.viewData }, function (data) { return _this.wrapTemplate(data); }); if (!this.wrapper) { this.wrapper = this._createWrapper(); } this.updateNode(this.wrapper, html); this.resize(); this.component._userEvent('afterRender'); } /** * delegates DOM events to event listeners. */ ; _proto.delegateEvents = function delegateEvents() { var _this2 = this; if (this.eventsBound) { return; } this.closeComponentsOnEsc(); Object.keys(this.component.DOMEvents).forEach(function (key) { var _key$match = key.match(delegateEventSplitter), _key$match2 = _slicedToArray(_key$match, 3), eventName = _key$match2[1], selectorString = _key$match2[2]; if (selectorString) { _this2._on(eventName, selectorString, function (evt, target) { _this2.component.DOMEvents[key].call(_this2, evt, target); }); } else { _this2.wrapper.addEventListener('click', function (evt) { _this2.component.DOMEvents[key].call(_this2, evt); }); } }); if (this.iframe) { this.iframe.el.onload = function () { _this2.iframe.el.onload = null; _this2.reloadIframe(); }; } this.eventsBound = true; }; _proto.reloadIframe = function reloadIframe() { this.node.removeChild(this.iframe.el); this.wrapper = null; this.iframe = null; this.component.init(); }; _proto.append = function append(wrapper) { if (this.iframe) { this.document.body.appendChild(wrapper); } else { this.component.node.appendChild(wrapper); } }; _proto.addClass = function addClass(className) { if (this.iframe) { this.iframe.addClass(className); } else { (0, _elementClass.addClassToElement)(className, this.component.node); } }; _proto.removeClass = function removeClass(className) { if (this.iframe) { this.iframe.removeClass(className); } else { (0, _elementClass.removeClassFromElement)(className, this.component.node); } }; _proto.destroy = function destroy() { this.node.parentNode.removeChild(this.node); } /** * update the contents of a DOM node with template * @param {String} className - class name to select node. * @param {Object} template - template to be rendered. */ ; _proto.renderChild = function renderChild(className, template) { var selector = ".".concat(className.split(' ').join('.')); var node = this.wrapper.querySelector(selector); var html = template.render({ data: this.component.viewData }); this.updateNode(node, html); } /** * call morpdom on a node with new HTML * @param {Object} node - DOM node to be updated. * @param {String} html - HTML to update DOM node with. */ ; _proto.updateNode = function updateNode(node, html) { var div = document.createElement('div'); div.innerHTML = html; (0, _morphdom.default)(node, div.firstElementChild); } /** * wrap HTML string in containing elements. * May be defined in subclass. * @param {String} html - HTML string. * @return {String} wrapped string. */ ; _proto.wrapTemplate = function wrapTemplate(html) { return "<div class=\"".concat(this.component.classes[this.component.typeKey][this.component.typeKey], "\">").concat(html, "</div>"); } /** * resize iframe if necessary. */ ; _proto.resize = function resize() { if (!this.iframe || !this.wrapper) { return; } if (this.shouldResizeX) { this._resizeX(); } if (this.shouldResizeY) { this._resizeY(); } } /** * get total height of iframe contents * @return {String} value in pixels. */ ; /** * Trap focus in the wrapper. */ _proto.setFocus = function setFocus() { (0, _focus.trapFocus)(this.wrapper); } /** * determines if iframe will require horizontal resizing to contain its children. * May be defined in subclass. * @return {Boolean} */ ; _proto.closeComponentsOnEsc = function closeComponentsOnEsc() { var _this3 = this; if (!this.iframe) { return; } this.document.addEventListener('keydown', function (evt) { if (evt.keyCode !== ESC_KEY) { return; } _this3.component.props.closeModal(); _this3.component.props.closeCart(); }); }; _proto.animateRemoveNode = function animateRemoveNode(id) { var _this4 = this; var el = this.document.getElementById(id); (0, _elementClass.addClassToElement)('is-hidden', el); if (this.component.props.browserFeatures.animation) { el.addEventListener('animationend', function () { if (!el.parentNode) { return; } _this4.removeNode(el); }); } else { this.removeNode(el); } }; _proto.removeNode = function removeNode(el) { el.parentNode.removeChild(el); this.render(); }; _proto._createWrapper = function _createWrapper() { var wrapper = document.createElement('div'); wrapper.className = this.component.classes[this.component.typeKey][this.component.typeKey]; this.append(wrapper); return wrapper; }; _proto._resizeX = function _resizeX() { this.iframe.el.style.width = "".concat(this.document.body.clientWidth, "px"); }; _proto._resizeY = function _resizeY(value) { var newHeight = value || this.outerHeight; this.iframe.el.style.height = newHeight; }; _proto._on = function _on(eventName, selector, fn) { var _this5 = this; this.wrapper.addEventListener(eventName, function (evt) { var possibleTargets = Array.prototype.slice.call(_this5.wrapper.querySelectorAll(selector)); var target = evt.target; possibleTargets.forEach(function (possibleTarget) { var el = target; while (el && el !== _this5.wrapper) { if (el === possibleTarget) { return fn.call(possibleTarget, evt, possibleTarget); } el = el.parentNode; } return el; }); }, eventName === 'blur'); }; _createClass(View, [{ key: "outerHeight", get: function get() { var style = window.getComputedStyle(this.wrapper, ''); if (!style) { return "".concat(this.wrapper.clientHeight, "px"); } var height = style.getPropertyValue('height'); if (!height || height === '0px' || height === 'auto') { var clientHeight = this.wrapper.clientHeight; height = style.getPropertyValue('height') || "".concat(clientHeight, "px"); } return height; } }, { key: "className", get: function get() { return ''; } }, { key: "shouldResizeX", get: function get() { return false; } /** * determines if iframe will require vertical resizing to contain its children. * May be defined in subclass. * @return {Boolean} */ }, { key: "shouldResizeY", get: function get() { return false; } /** * get reference to document object. * @return {Objcet} instance of Document. */ }, { key: "document", get: function get() { return this.iframe ? this.iframe.document : window.document; } }]); return View; }(); exports.default = View;