diff --git a/Basic/README.md b/Basic/README.md new file mode 100644 index 0000000..c5e358e --- /dev/null +++ b/Basic/README.md @@ -0,0 +1,59 @@ +# Basic Widget + +### Default Configuration + +```html + + + + + + Default Widget Example + + + + + + +``` + +#### Result: +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/settle-widget-card.png) + +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/settle-widget.png) + +### Custom Configuration + +```html + + + + Custom Widget Example + + + + + +
+ + + +``` + +#### Result: +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/custom-settle-widget-card.png) + +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/custom-settle-widget.png) diff --git a/Basic/widget-popup.html b/Basic/widget-popup.html new file mode 100644 index 0000000..378a655 --- /dev/null +++ b/Basic/widget-popup.html @@ -0,0 +1,39 @@ + + + Popup + + + + My Website + + + + + + + + + diff --git a/Basic/widget.js b/Basic/widget.js new file mode 100644 index 0000000..15f0abd --- /dev/null +++ b/Basic/widget.js @@ -0,0 +1,669 @@ +class SettlePopupWidget extends HTMLElement { + defaultTheme = "rgb(1, 89, 79)"; + attributes = { + selector: "", + currency: "₹", + emiTenure: [3], + totalOrderValue: "3000", + productName: "Your Product Name ", + showProductName: true, + theme: this.defaultTheme, + logoPosition: "right", + buttonText: "Interest free monthly payments with", + showModalPreview: false, + }; + + static get observedAttributes() { + return [ + "currency", + "emiTenure", + "totalOrderValue", + "productName", + "showProductName", + "theme", + "logoPosition", + "buttonText", + "showModalPreview", + ]; + } + + constructor(props = {}) { + super(); + this.attributes = { + ...this.attributes, + ...props, + }; + + this.attachShadow({ mode: "open" }); + this.renderAndBindListners(); + } + + connectedCallback() { + this.renderAndBindListners(); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + this.attributes[name] = newValue; + this.renderAndBindListners(); + } + } + + async renderAndBindListners() { + await this.render(); + this.setupEventListeners(); + } + + adjustBrightness(rgb, opacityPercentage) { + // Parse the RGB color code + const regex = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/; + let rgbCodeParts = regex.exec(rgb); + + if (!rgbCodeParts) { + console.error("Invalid RGB color format"); + rgb = this.defaultTheme; // Default theme color + rgbCodeParts = regex.exec(rgb); + } + + const r = parseInt(rgbCodeParts[1]); + const g = parseInt(rgbCodeParts[2]); + const b = parseInt(rgbCodeParts[3]); + + const alpha = Math.min(1, Math.max(0, opacityPercentage / 100)); + const rgbaColor = `rgba(${r}, ${g}, ${b}, ${alpha})`; + + return rgbaColor; + } + + loadAndModifySVG = async (color) => { + const logoUrl = + "https://cdn.pixelbin.io/v2/potlee/original/public/logos/settle-new/settleBranding.svg"; + + try { + const response = await fetch(logoUrl); + const svgText = await response.text(); + + const parser = new DOMParser(); + const svgDoc = parser.parseFromString(svgText, "image/svg+xml"); + const svgElement = svgDoc.querySelector("svg"); + + svgElement.querySelectorAll("path")?.forEach((element) => { + element.setAttribute("fill", color); + element.style.fill = color; + }); + + const modifiedSVG = new XMLSerializer().serializeToString(svgElement); + + const svgBlob = new Blob([modifiedSVG], { type: "image/svg+xml" }); + const urlObject = URL.createObjectURL(svgBlob); + + return urlObject; + } catch (error) { + console.error("Error loading or modifying SVG:", error); + return logoUrl; + } + }; + + async render() { + const buttonText = + this.getAttribute("buttonText") || + this.attributes.buttonText || + "Interest free monthly payments with"; + const currency = + this.getAttribute("currency") || this.attributes.currency || "₹"; + const logoPosition = + this.getAttribute("logoPosition") || + this.attributes.logoPosition || + "right"; + + const totalOrderValue = + this.getAttribute("totalOrderValue") || + this.attributes.totalOrderValue || + "3000"; + + const productName = + this.getAttribute("productName") || this.attributes.productName || "Your Product Name"; + const showProductName = eval( + this.getAttribute("showProductName") || + this.hasAttribute("showProductName") || + this.attributes.showProductName || + false + ); + const showModalPreview = eval( + this.getAttribute("showModalPreview") || + this.hasAttribute("showModalPreview") || + this.attributes.showModalPreview || + false + ); + + const themeRGBColor = + this.getAttribute("theme") || this.attributes.theme || this.defaultTheme; + const lighterThemeColor = this.adjustBrightness(themeRGBColor, 10); + + const formatDate = (monthsAhead) => { + const today = new Date(); + const futureDate = new Date( + today.setMonth(today.getMonth() + monthsAhead) + ); + return futureDate.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }); + }; + + const month1 = formatDate(1); + const month2 = formatDate(2); + const month3 = formatDate(3); + + const emiValue = Math.round(totalOrderValue / 3).toLocaleString("en-IN"); + + const screenWidth = window.innerWidth; + const scale = + screenWidth <= 360 || totalOrderValue.length >= 5 + ? "scale(0.8)" + : "scale(1)"; + + const logo = await this.loadAndModifySVG(themeRGBColor); + const logoSVG = (width = "92") => { + return ` + + + `; + }; + + const css = ` + + + + + `; + + const modalContent = ` + + `; + + const html = ` +
+
+ + + ${logoPosition === "left" ? logoSVG("50") : ""} + ${buttonText} + ${logoPosition !== "left" ? logoSVG("50") : ""} +
+ +
+ ${ + showModalPreview + ? ` +
+ ${modalContent} +
+ ` + : ` + + ` + } + + + `; + + const widgetHtml = css + html; + if (this.attributes.selector) { + const targetElement = document.querySelector(this.attributes.selector); + targetElement.innerHTML = widgetHtml; + } else { + this.shadowRoot.innerHTML = widgetHtml; + } + } + + setupEventListeners() { + let card; + let modal; + let modalCenter; + let closeModalButton; + let body; + + if (this.attributes.selector) { + const targetElement = document.querySelector(this.attributes.selector); + card = targetElement.querySelector(".card"); + modal = targetElement.querySelector(".modal"); + modalCenter = targetElement.querySelector(".modal-center"); + closeModalButton = targetElement.querySelector(".close"); + body = document.querySelector("body"); + + window.addEventListener("click", (event) => { + this.handleModalClose(event, modal, modalCenter, body); + }); + } else { + card = this.shadowRoot.querySelector(".card"); + modal = this.shadowRoot.querySelector(".modal"); + modalCenter = this.shadowRoot.querySelector(".modal-center"); + closeModalButton = this.shadowRoot.querySelector(".close"); + body = document.querySelector("body"); + + this.shadowRoot.addEventListener("click", (event) => { + this.handleModalClose(event, modal, modalCenter, body); + }); + } + + card.addEventListener("click", () => { + if (modal) { + modal.style.display = "block"; + body.style.overflow = "hidden"; + } + }); + + closeModalButton.addEventListener("click", () => { + this.closeModal(modal, body); + }); + + document.addEventListener("keydown", (event) => { + this.OnEscapePressed(event, modal, body); + }); + } + + handleModalClose(event, modal, modalCenter, body) { + if (event.target === modal || event.target === modalCenter) { + this.closeModal(modal, body); + } + } + + OnEscapePressed = (event, modal, body) => { + if (event.key === "Escape" || event.code === "Escape") { + this.closeModal(modal, body); + } + }; + + closeModal = (modal, body) => { + if (modal) { + modal.style.display = "none"; + body.style.overflow = "auto"; + } + }; +} + +customElements.define("settle-widget", SettlePopupWidget); diff --git a/README.md b/README.md index 04ad82c..1ffbed8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,131 @@ -# Settle Widgets +# Widget -Settle Widget for show casing our offerings +Enhancement for your online store with a fully customizable Settle widget that seamlessly integrates with your store’s theme. + +## Features + +- Easy implementation with a single JavaScript file +- Clickable card reveals an informative popup +- Customizable theme colors for card and popup +- Configurable content through various attributes + +To activate the settle widget on your website, follow these steps: + +## Adding the Widget + +Add this script to your HTML file's `` section: + +```html + +``` + +## Implementation + +Choose one of these methods to add the widget to your page: + +### 1. HTML Element + +Simply add this tag where you want the widget to appear: + +```html + +``` + +### 2. JavaScript Object + +Add a container element with the matching selector to your HTML. This element will serve as the placeholder for the widget. + +```html +
+``` + +Create a new instance of the `SettlePopupWidget` in your JavaScript. Make sure this script runs after the DOM has fully loaded. + +```javascript +document.addEventListener("DOMContentLoaded", () => { + setTimeout(() => { + new SettlePopupWidget({ + selector: "#settle-widget-container", + totalOrderValue: "3000", + }); + }, 1000); +}); +``` + +## Customization + +Adjust these attributes to configure your Settle Widget. Each option lets you control the widget's appearance and behavior to best fit your website: (applicable to both implementation methods) + +| Attribute | Description | Default | Options | +| --------------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------- | ------------------- | +| totalOrderValue * `number` | Purchase total amount | 0 | - | +| selector * `string` | Container element selector (for Javascript Object only) | #settle-widget-container | - | +| buttonText `string` | Custom button text | Interest free monthly payments with | - | +| logoPosition `string` | Settle logo position in button | right | "left", "right" | +| theme `string` | Widget color theme | rgb(1, 89, 79) | Any valid RGB color | +| productName `string` | Your Product Name | Your Product Name | - | +| showProductName `boolean` | Flag for showing product name | true | - | +| currency `string` | Currency symbol | ₹ | - | +| emiTenure `number[]` | EMI duration in months | [3] | [3, 6, 9, 12] | + +*Required attribues + +## Examples + +### Default Configuration + +```html + + + + + + Default Widget Example + + + + + + +``` + +#### Result: +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/settle-widget-card.png) + +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/settle-widget.png) + +### Custom Configuration + +```html + + + + Custom Widget Example + + + + + +
+ + + +``` + +#### Result: +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/custom-settle-widget-card.png) + +![Default Widget Preview](https://cdn.pixelbin.io/v2/potlee/original/public/documentation/settle-widget/custom-settle-widget.png)