UNPKG

svgedit

Version:

Powerful SVG-Editor for your browser

395 lines (359 loc) 17.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: components/seExplorerButton.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: components/seExplorerButton.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* globals svgEditor */ /** * @class ExplorerButton */ export class ExplorerButton extends HTMLElement { /** * @function constructor */ constructor () { super() // create the shadowDom and insert the template // create the shadowDom and insert the template this.imgPath = svgEditor.configObj.curConfig.imgPath this.template = this.createTemplate(this.imgPath) this._shadowRoot = this.attachShadow({ mode: 'open' }) this._shadowRoot.append(this.template.content.cloneNode(true)) // locate the component this.$button = this._shadowRoot.querySelector('.menu-button') this.$overall = this._shadowRoot.querySelector('.overall') this.$img = this._shadowRoot.querySelector('.menu-button img') this.$menu = this._shadowRoot.querySelector('.menu') this.$handle = this._shadowRoot.querySelector('.handle') this.$lib = this._shadowRoot.querySelector('.image-lib') this.files = [] this.request = new XMLHttpRequest() this.imgPath = svgEditor.configObj.curConfig.imgPath // Closes opened (pressed) lib menu on click on the canvas const workarea = document.getElementById('workarea') workarea.addEventListener('click', (e) => { this.$menu.classList.remove('open') this.$lib.classList.remove('open-lib') }) } /** * @function createTemplate * @param {string} imgPath * @returns {any} template */ createTemplate (imgPath) { const template = document.createElement('template') template.innerHTML = ` &lt;style> :host { position:relative; } .menu-button:hover, se-button:hover, .menu-item:hover { background-color: var(--icon-bg-color-hover); } img { border: none; width: 24px; height: 24px; } .overall.pressed .button-icon, .overall.pressed, .menu-item.pressed { background-color: var(--icon-bg-color-hover) !important; } .overall.pressed .menu-button { background-color: var(--icon-bg-color-hover) !important; } .disabled { opacity: 0.3; cursor: default; } .menu-button { height: 24px; width: 24px; margin: 2px 1px 4px; padding: 3px; background-color: var(--icon-bg-color); cursor: pointer; position: relative; border-radius: 3px; overflow: hidden; } .handle { height: 8px; width: 8px; background-image: url(${imgPath}/handle.svg); position:absolute; bottom: 0px; right: 0px; } .button-icon { } .menu { position: fixed; margin-left: 34px; background: none !important; display:none; top: 30%; left: 171px; } .image-lib { position: fixed; left: 34px; top: 30%; background: #E8E8E8; display: none; flex-wrap: wrap; flex-direction: row; width: 170px; } .menu-item { line-height: 1em; padding: 0.5em; border: 1px solid #5a6162; background: #E8E8E8; margin-bottom: -1px; white-space: nowrap; } .open-lib { display: inline-flex; } .open { display: block; } .overall { background: none !important; } &lt;/style> &lt;div class="overall"> &lt;div class="menu-button"> &lt;img class="button-icon" src="explorer.svg" alt="icon"> &lt;div class="handle">&lt;/div> &lt;/div> &lt;div class="image-lib""> &lt;se-button>&lt;/se-button> &lt;/div> &lt;div class="menu"> &lt;div class="menu-item">menu&lt;/div> &lt;/div> &lt;/div>` return template } /** * @function observedAttributes * @returns {any} observed */ static get observedAttributes () { return ['title', 'pressed', 'disabled', 'lib', 'src'] } /** * @function attributeChangedCallback * @param {string} name * @param {string} oldValue * @param {string} newValue * @returns {void} */ async attributeChangedCallback (name, oldValue, newValue) { if (oldValue === newValue) return switch (name) { case 'title': { const shortcut = this.getAttribute('shortcut') this.$button.setAttribute('title', `${newValue} [${shortcut}]`) } break case 'pressed': if (newValue) { this.$overall.classList.add('pressed') } else { this.$overall.classList.remove('pressed') } break case 'disabled': if (newValue) { this.$overall.classList.add('disabled') } else { this.$overall.classList.remove('disabled') } break case 'lib': try { const response = await fetch(`${newValue}index.json`) const json = await response.json() const { lib } = json this.$menu.innerHTML = lib.map((menu, i) => ( `&lt;div data-menu="${menu}" class="menu-item ${(i === 0) ? 'pressed' : ''} ">${menu}&lt;/div>` )).join('') await this.updateLib(lib[0]) } catch (error) { console.error(error) } break case 'src': this.$img.setAttribute('src', this.imgPath + '/' + newValue) break default: console.error(`unknown attribute: ${name}`) break } } /** * @function get * @returns {any} */ get title () { return this.getAttribute('title') } /** * @function set * @returns {void} */ set title (value) { this.setAttribute('title', value) } /** * @function get * @returns {any} */ get pressed () { return this.hasAttribute('pressed') } /** * @function set * @returns {void} */ set pressed (value) { // boolean value => existence = true if (value) { this.setAttribute('pressed', 'true') } else { this.removeAttribute('pressed', '') } } /** * @function get * @returns {any} */ get disabled () { return this.hasAttribute('disabled') } /** * @function set * @returns {void} */ set disabled (value) { // boolean value => existence = true if (value) { this.setAttribute('disabled', 'true') } else { this.removeAttribute('disabled', '') } } /** * @function connectedCallback * @returns {void} */ connectedCallback () { // capture click event on the button to manage the logic const onClickHandler = (ev) => { ev.stopPropagation() switch (ev.target.nodeName) { case 'SE-EXPLORERBUTTON': this.$menu.classList.toggle('open') this.$lib.classList.toggle('open-lib') break case 'SE-BUTTON': // change to the current action this.currentAction = ev.target this.$img.setAttribute('src', this.currentAction.getAttribute('src')) this.dataset.draw = this.data[this.currentAction.dataset.shape] this._shadowRoot.querySelectorAll('.image-lib [pressed]').forEach((b) => { b.pressed = false }) this.currentAction.setAttribute('pressed', 'pressed') // and close the menu this.$menu.classList.remove('open') this.$lib.classList.remove('open-lib') break case 'DIV': if (ev.target.classList[0] === 'handle') { // this is a click on the handle so let's open/close the menu. this.$menu.classList.toggle('open') this.$lib.classList.toggle('open-lib') } else { this._shadowRoot.querySelectorAll('.menu > .pressed').forEach((b) => { b.classList.remove('pressed') }) ev.target.classList.add('pressed') this.updateLib(ev.target.dataset.menu) } break default: console.error('unknown nodeName for:', ev.target, ev.target.className) } } // capture event from slots svgEditor.$click(this, onClickHandler) svgEditor.$click(this.$menu, onClickHandler) svgEditor.$click(this.$lib, onClickHandler) svgEditor.$click(this.$handle, onClickHandler) } /** * @function updateLib * @param {string} lib * @returns {void} */ async updateLib (lib) { const libDir = this.getAttribute('lib') try { // initialize buttons for all shapes defined for this library const response = await fetch(`${libDir}${lib}.json`) const json = await response.json() this.data = json.data const size = json.size ?? 300 const fill = json.fill ? '#333' : 'none' const off = size * 0.05 const vb = [-off, -off, size + off * 2, size + off * 2].join(' ') const stroke = json.fill ? 0 : (size / 30) this.$lib.innerHTML = Object.entries(this.data).map(([key, path]) => { const encoded = btoa(` &lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> &lt;svg viewBox="${vb}">&lt;path fill="${fill}" stroke="#f8bb00" stroke-width="${stroke}" d="${path}">&lt;/path>&lt;/svg> &lt;/svg>`) return `&lt;se-button data-shape="${key}"src="data:image/svg+xml;base64,${encoded}">&lt;/se-button>` }).join('') } catch (error) { console.error(`could not read file:${libDir}${lib}.json`, error) } } } // Register customElements.define('se-explorerbutton', ExplorerButton) </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-SVGEditor.html">SVGEditor</a></li><li><a href="module-contextmenu.html">contextmenu</a></li><li><a href="module-jGraduate.html">jGraduate</a></li><li><a href="module-jPicker.html">jPicker</a></li><li><a href="module-locale.html">locale</a></li></ul><h3>Externals</h3><ul><li><a href="external-JamilihArray.html">JamilihArray</a></li><li><a href="external-Math.html">Math</a></li><li><a href="external-Window.html">Window</a></li><li><a href="external-jQuery.html">jQuery</a></li></ul><h3>Namespaces</h3><ul><li><a href="external-jQuery.fn.html">fn</a></li><li><a href="external-jQuery.fn.$.fn.jPicker.defaults.html">defaults</a></li><li><a href="external-jQuery.fn.exports.jPickerMethod.html">exports.jPickerMethod</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.html">jGraduateDefaults</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.images.html">images</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.window.html">window</a></li><li><a href="external-jQuery.jGraduate.html">jGraduate</a></li><li><a href="external-jQuery.jPicker.html">jPicker</a></li><li><a href="external-jQuery.jPicker.ColorMethods.html">ColorMethods</a></li></ul><h3>Classes</h3><ul><li><a href="BottomPanel.html">BottomPanel</a></li><li><a href="Dropdown.html">Dropdown</a></li><li><a href="EditorStartup.html">EditorStartup</a></li><li><a href="ElixMenuButton.html">ElixMenuButton</a></li><li><a href="ElixNumberSpinBox.html">ElixNumberSpinBox</a></li><li><a href="ExplorerButton.html">ExplorerButton</a></li><li><a href="FlyingButton.html">FlyingButton</a></li><li><a href="LayersPanel.html">LayersPanel</a></li><li><a href="LeftPanel.html">LeftPanel</a></li><li><a href="MainMenu.html">MainMenu</a></li><li><a href="NumberSpinBox.html">NumberSpinBox</a></li><li><a href="PaintBox.html">PaintBox</a></li><li><a href="PlainNumberSpinBox.html">PlainNumberSpinBox</a></li><li><a href="Rulers.html">Rulers</a></li><li><a href="SEInput.html">SEInput</a></li><li><a href="SEPalette.html">SEPalette</a></li><li><a href="SESpinInput.html">SESpinInput</a></li><li><a href="SeCMenuDialog.html">SeCMenuDialog</a></li><li><a href="SeCMenuLayerDialog.html">SeCMenuLayerDialog</a></li><li><a href="SeColorPicker.html">SeColorPicker</a></li><li><a href="SeEditPrefsDialog.html">SeEditPrefsDialog</a></li><li><a href="SeExportDialog.html">SeExportDialog</a></li><li><a href="SeImgPropDialog.html">SeImgPropDialog</a></li><li><a href="SeList.html">SeList</a></li><li><a href="SeMenu.html">SeMenu</a></li><li><a href="SeMenuItem.html">SeMenuItem</a></li><li><a href="SePlainAlertDialog.html">SePlainAlertDialog</a></li><li><a href="SePlainBorderButton.html">SePlainBorderButton</a></li><li><a href="SePromptDialog.html">SePromptDialog</a></li><li><a href="SeStorageDialog.html">SeStorageDialog</a></li><li><a href="SeSvgSourceEditorDialog.html">SeSvgSourceEditorDialog</a></li><li><a href="SeText.html">SeText</a></li><li><a href="ToolButton.html">ToolButton</a></li><li><a href="TopPanel.html">TopPanel</a></li><li><a href="configObj.html">configObj</a></li><li><a href="external-jQuery.jGraduate.Paint.html">Paint</a></li><li><a href="external-jQuery.jPicker.Color.html">Color</a></li><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li><li><a href="module-SVGEditor-Editor.html">Editor</a></li><li><a href="module-jPicker.module.exports.html">module.exports</a></li></ul><h3>Interfaces</h3><ul><li><a href="module-SVGEditor.Config.html">Config</a></li><li><a href="module-SVGEditor.Prefs.html">Prefs</a></li><li><a href="module-SVGthis.CustomHandler.html">CustomHandler</a></li><li><a href="module-locale.LocaleEditorInit.html">LocaleEditorInit</a></li></ul><h3>Events</h3><ul><li><a href="module-SVGEditor.html#event:event:svgEditorReadyEvent">svgEditorReadyEvent</a></li></ul><h3>Tutorials</h3><ul><li><a href="tutorial-CanvasAPI.html">CanvasAPI</a></li><li><a href="tutorial-Editor.html">Editor</a></li><li><a href="tutorial-EditorAPI.html">EditorAPI</a></li><li><a href="tutorial-Events.html">Events</a></li><li><a href="tutorial-FrequentlyAskedQuestions.html">Frequently Asked Questions (FAQ)</a></li></ul><h3>Global</h3><ul><li><a href="global.html#attributeChangedCallback">attributeChangedCallback</a></li><li><a href="global.html#connectedCallback">connectedCallback</a></li><li><a href="global.html#constructor">constructor</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#decrement">decrement</a></li><li><a href="global.html#expireCookie">expireCookie</a></li><li><a href="global.html#formatValueFormatthenumericvalueasastring.Thisisusedafterincrementing/decrementingthevaluetoreformatthevalueasastring.">formatValue Format the numeric value as a string. This is used after incrementing/decrementing the value to reformat the value as a string.</a></li><li><a href="global.html#get">get</a></li><li><a href="global.html#handleClick">handleClick</a></li><li><a href="global.html#handleClose">handleClose</a></li><li><a href="global.html#handleInput">handleInput</a></li><li><a href="global.html#handleKeyDown">handleKeyDown</a></li><li><a href="global.html#handleMouseDown">handleMouseDown</a></li><li><a href="global.html#handleMouseUp">handleMouseUp</a></li><li><a href="global.html#handleOptionsChange">handleOptionsChange</a></li><li><a href="global.html#handleSelect">handleSelect</a></li><li><a href="global.html#handleShow">handleShow</a></li><li><a href="global.html#increment">increment</a></li><li><a href="global.html#init">init</a></li><li><a href="global.html#inputsize">inputsize</a></li><li><a href="global.html#isNullish">isNullish</a></li><li><a href="global.html#loadloadConfig">load load Config</a></li><li><a href="global.html#loadFromURLLoadconfig/datafromURLifgiven">loadFromURL Load config/data from URL if given</a></li><li><a href="global.html#name">name</a></li><li><a href="global.html#observedAttributes">observedAttributes</a></li><li><a href="global.html#parseValue">parseValue</a></li><li><a href="global.html#pref">pref</a></li><li><a href="global.html#readySignal">readySignal</a></li><li><a href="global.html#regexEscape">regexEscape</a></li><li><a href="global.html#removeStoragePrefCookie">removeStoragePrefCookie</a></li><li><a href="global.html#replaceStoragePrompt">replaceStoragePrompt</a></li><li><a href="global.html#set">set</a></li><li><a href="global.html#setupCurConfig">setupCurConfig</a></li><li><a href="global.html#setupCurPrefs">setupCurPrefs</a></li><li><a href="global.html#src">src</a></li><li><a href="global.html#stateEffects">stateEffects</a></li><li><a href="global.html#stepDown">stepDown</a></li><li><a href="global.html#stepUp">stepUp</a></li><li><a href="global.html#triggerInputChanged">triggerInputChanged</a></li><li><a href="global.html#updateLib">updateLib</a></li><li><a href="global.html#value">value</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Mon Jun 09 2025 17:03:26 GMT+0200 (Central European Summer Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>