diff --git a/package.json b/package.json index c1aac194e6..a62dd41924 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "eslint-plugin-vue": "8.5.0", "eslint-plugin-you-dont-need-lodash-underscore": "6.12.0", "eventemitter3": "1.2.0", - "exports-loader": "0.7.0", "express": "4.13.1", "file-saver": "2.0.5", "git-rev-sync": "3.0.2", @@ -74,8 +73,7 @@ "webpack-cli": "4.9.2", "webpack-dev-middleware": "5.3.3", "webpack-hot-middleware": "2.25.1", - "webpack-merge": "5.8.0", - "zepto": "1.2.0" + "webpack-merge": "5.8.0" }, "scripts": { "clean": "rm -rf ./dist ./node_modules ./package-lock.json", diff --git a/src/api/indicators/SimpleIndicator.js b/src/api/indicators/SimpleIndicator.js index 1ef99e6888..31ce745a52 100644 --- a/src/api/indicators/SimpleIndicator.js +++ b/src/api/indicators/SimpleIndicator.js @@ -22,6 +22,7 @@ import EventEmitter from 'EventEmitter'; import indicatorTemplate from './res/indicator-template.html'; +import { convertTemplateToHTML } from '@/utils/template/templateHelpers'; const DEFAULT_ICON_CLASS = 'icon-info'; @@ -30,7 +31,7 @@ class SimpleIndicator extends EventEmitter { super(); this.openmct = openmct; - this.element = compileTemplate(indicatorTemplate)[0]; + this.element = convertTemplateToHTML(indicatorTemplate)[0]; this.priority = openmct.priority.DEFAULT; this.textElement = this.element.querySelector('.js-indicator-text'); @@ -116,11 +117,4 @@ class SimpleIndicator extends EventEmitter { } } -function compileTemplate(htmlTemplate) { - const templateNode = document.createElement('template'); - templateNode.innerHTML = htmlTemplate; - - return templateNode.content.cloneNode(true).children; -} - export default SimpleIndicator; diff --git a/src/plugins/URLIndicatorPlugin/URLIndicator.js b/src/plugins/URLIndicatorPlugin/URLIndicator.js index 1bc83450e9..5a6785e54b 100644 --- a/src/plugins/URLIndicatorPlugin/URLIndicator.js +++ b/src/plugins/URLIndicatorPlugin/URLIndicator.js @@ -20,10 +20,8 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define( - ['zepto'], - function ($) { - +define([], + function () { // Set of connection states; changing among these states will be // reflected in the indicator's appearance. // CONNECTED: Everything nominal, expect to be able to read/write. @@ -75,12 +73,17 @@ define( }; URLIndicator.prototype.fetchUrl = function () { - $.ajax({ - type: 'GET', - url: this.URLpath, - success: this.handleSuccess, - error: this.handleError - }); + fetch(this.URLpath) + .then(response => { + if (response.ok) { + this.handleSuccess(); + } else { + this.handleError(); + } + }) + .catch(error => { + this.handleError(); + }); }; URLIndicator.prototype.handleError = function (e) { diff --git a/src/plugins/URLIndicatorPlugin/URLIndicatorSpec.js b/src/plugins/URLIndicatorPlugin/URLIndicatorSpec.js index 408a98cd09..cf6cd39ff6 100644 --- a/src/plugins/URLIndicatorPlugin/URLIndicatorSpec.js +++ b/src/plugins/URLIndicatorPlugin/URLIndicatorSpec.js @@ -25,37 +25,35 @@ define( "utils/testing", "./URLIndicator", "./URLIndicatorPlugin", - "../../MCT", - "zepto" + "../../MCT" ], function ( testingUtils, URLIndicator, URLIndicatorPlugin, - MCT, - $ + MCT ) { - const defaultAjaxFunction = $.ajax; - describe("The URLIndicator", function () { let openmct; let indicatorElement; let pluginOptions; - let ajaxOptions; let urlIndicator; // eslint-disable-line + let fetchSpy; beforeEach(function () { jasmine.clock().install(); openmct = new testingUtils.createOpenMct(); spyOn(openmct.indicators, 'add'); - spyOn($, 'ajax'); - $.ajax.and.callFake(function (options) { - ajaxOptions = options; - }); + fetchSpy = spyOn(window, 'fetch').and.callFake(() => Promise.resolve({ + ok: true + })); }); afterEach(function () { - $.ajax = defaultAjaxFunction; + if (window.fetch.restore) { + window.fetch.restore(); + } + jasmine.clock().uninstall(); return testingUtils.resetApplicationState(openmct); @@ -96,11 +94,11 @@ define( expect(indicatorElement.classList.contains('iconClass-checked')).toBe(true); }); it("uses custom interval", function () { - expect($.ajax.calls.count()).toEqual(1); + expect(window.fetch).toHaveBeenCalledTimes(1); jasmine.clock().tick(1); - expect($.ajax.calls.count()).toEqual(1); + expect(window.fetch).toHaveBeenCalledTimes(1); jasmine.clock().tick(pluginOptions.interval + 1); - expect($.ajax.calls.count()).toEqual(2); + expect(window.fetch).toHaveBeenCalledTimes(2); }); it("uses custom label if supplied in initialization", function () { expect(indicatorElement.textContent.indexOf(pluginOptions.label) >= 0).toBe(true); @@ -120,18 +118,21 @@ define( it("requests the provided URL", function () { jasmine.clock().tick(pluginOptions.interval + 1); - expect(ajaxOptions.url).toEqual(pluginOptions.url); + expect(window.fetch).toHaveBeenCalledWith(pluginOptions.url); }); - it("indicates success if connection is nominal", function () { + it("indicates success if connection is nominal", async function () { jasmine.clock().tick(pluginOptions.interval + 1); - ajaxOptions.success(); + await urlIndicator.fetchUrl(); expect(indicatorElement.classList.contains('s-status-on')).toBe(true); }); - it("indicates an error when the server cannot be reached", function () { + it("indicates an error when the server cannot be reached", async function () { + fetchSpy.and.callFake(() => Promise.resolve({ + ok: false + })); jasmine.clock().tick(pluginOptions.interval + 1); - ajaxOptions.error(); + await urlIndicator.fetchUrl(); expect(indicatorElement.classList.contains('s-status-warning-hi')).toBe(true); }); }); diff --git a/src/plugins/autoflow/AutoflowTabularPluginSpec.js b/src/plugins/autoflow/AutoflowTabularPluginSpec.js index ce20cab1d6..5e5d49489d 100644 --- a/src/plugins/autoflow/AutoflowTabularPluginSpec.js +++ b/src/plugins/autoflow/AutoflowTabularPluginSpec.js @@ -21,7 +21,6 @@ *****************************************************************************/ import AutoflowTabularPlugin from './AutoflowTabularPlugin'; import AutoflowTabularConstants from './AutoflowTabularConstants'; -import $ from 'zepto'; import DOMObserver from './dom-observer'; import { createOpenMct, @@ -122,7 +121,7 @@ xdescribe("AutoflowTabularPlugin", () => { name: "Object " + key }; }); - testContainer = $('
')[0]; + testContainer = document.createElement('div'); domObserver = new DOMObserver(testContainer); testHistories = testKeys.reduce((histories, key, index) => { @@ -195,7 +194,7 @@ xdescribe("AutoflowTabularPlugin", () => { describe("when rows have been populated", () => { function rowsMatch() { - const rows = $(testContainer).find(".l-autoflow-row").length; + const rows = testContainer.querySelectorAll(".l-autoflow-row").length; return rows === testChildren.length; } @@ -241,20 +240,20 @@ xdescribe("AutoflowTabularPlugin", () => { const nextWidth = initialWidth + AutoflowTabularConstants.COLUMN_WIDTH_STEP; - expect($(testContainer).find('.l-autoflow-col').css('width')) + expect(testContainer.querySelector('.l-autoflow-col').css('width')) .toEqual(initialWidth + 'px'); - $(testContainer).find('.change-column-width').click(); + testContainer.querySelector('.change-column-width').click(); function widthHasChanged() { - const width = $(testContainer).find('.l-autoflow-col').css('width'); + const width = testContainer.querySelector('.l-autoflow-col').css('width'); return width !== initialWidth + 'px'; } return domObserver.when(widthHasChanged) .then(() => { - expect($(testContainer).find('.l-autoflow-col').css('width')) + expect(testContainer.querySelector('.l-autoflow-col').css('width')) .toEqual(nextWidth + 'px'); }); }); @@ -267,13 +266,13 @@ xdescribe("AutoflowTabularPlugin", () => { it("displays historical telemetry", () => { function rowTextDefined() { - return $(testContainer).find(".l-autoflow-item").filter(".r").text() !== ""; + return testContainer.querySelector(".l-autoflow-item").filter(".r").text() !== ""; } return domObserver.when(rowTextDefined).then(() => { testKeys.forEach((key, index) => { const datum = testHistories[key]; - const $cell = $(testContainer).find(".l-autoflow-row").eq(index).find(".r"); + const $cell = testContainer.querySelector(".l-autoflow-row").eq(index).find(".r"); expect($cell.text()).toEqual(String(datum.range)); }); }); @@ -294,7 +293,7 @@ xdescribe("AutoflowTabularPlugin", () => { return waitsForChange().then(() => { testData.forEach((datum, index) => { - const $cell = $(testContainer).find(".l-autoflow-row").eq(index).find(".r"); + const $cell = testContainer.querySelector(".l-autoflow-row").eq(index).find(".r"); expect($cell.text()).toEqual(String(datum.range)); }); }); @@ -312,7 +311,7 @@ xdescribe("AutoflowTabularPlugin", () => { return waitsForChange().then(() => { testKeys.forEach((datum, index) => { - const $cell = $(testContainer).find(".l-autoflow-row").eq(index).find(".r"); + const $cell = testContainer.querySelector(".l-autoflow-row").eq(index).find(".r"); expect($cell.hasClass(testClass)).toBe(true); }); }); @@ -322,16 +321,16 @@ xdescribe("AutoflowTabularPlugin", () => { const rowHeight = AutoflowTabularConstants.ROW_HEIGHT; const sliderHeight = AutoflowTabularConstants.SLIDER_HEIGHT; const count = testKeys.length; - const $container = $(testContainer); + const $container = testContainer; let promiseChain = Promise.resolve(); function columnsHaveAutoflowed() { - const itemsHeight = $container.find('.l-autoflow-items').height(); + const itemsHeight = $container.querySelector('.l-autoflow-items').height(); const availableHeight = itemsHeight - sliderHeight; const availableRows = Math.max(Math.floor(availableHeight / rowHeight), 1); const columns = Math.ceil(count / availableRows); - return $container.find('.l-autoflow-col').length === columns; + return $container.querySelector('.l-autoflow-col').length === columns; } $container.find('.abs').css({ diff --git a/src/plugins/licenses/third-party-licenses.json b/src/plugins/licenses/third-party-licenses.json index 184024eb41..c139298ce1 100644 --- a/src/plugins/licenses/third-party-licenses.json +++ b/src/plugins/licenses/third-party-licenses.json @@ -256,13 +256,6 @@ "licenseFile": "/Users/akhenry/Code/licenses/node_modules/vue/LICENSE", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2013-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", "copyright": "Copyright (c) 2013-present, Yuxi (Evan) You" - }, - "zepto@1.2.0": { - "licenses": "MIT", - "repository": "https://github.com/madrobby/zepto", - "path": "/Users/akhenry/Code/licenses/node_modules/zepto", - "licenseFile": "/Users/akhenry/Code/licenses/node_modules/zepto/README.md", - "licenseText": "Copyright (c) 2010-2018 Thomas Fuchs\nhttp://zeptojs.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." } } diff --git a/src/plugins/summaryWidget/src/Condition.js b/src/plugins/summaryWidget/src/Condition.js index 997ad67b4f..66f9ecbeb2 100644 --- a/src/plugins/summaryWidget/src/Condition.js +++ b/src/plugins/summaryWidget/src/Condition.js @@ -4,16 +4,16 @@ define([ './input/KeySelect', './input/OperationSelect', './eventHelpers', - 'EventEmitter', - 'zepto' + '../../../utils/template/templateHelpers', + 'EventEmitter' ], function ( conditionTemplate, ObjectSelect, KeySelect, OperationSelect, eventHelpers, - EventEmitter, - $ + templateHelpers, + EventEmitter ) { /** * Represents an individual condition for a summary widget rule. Manages the @@ -31,12 +31,13 @@ define([ this.index = index; this.conditionManager = conditionManager; - this.domElement = $(conditionTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(conditionTemplate)[0]; + this.eventEmitter = new EventEmitter(); this.supportedCallbacks = ['remove', 'duplicate', 'change']; - this.deleteButton = $('.t-delete', this.domElement); - this.duplicateButton = $('.t-duplicate', this.domElement); + this.deleteButton = this.domElement.querySelector('.t-delete'); + this.duplicateButton = this.domElement.querySelector('.t-duplicate'); this.selects = {}; this.valueInputs = []; @@ -105,9 +106,10 @@ define([ }); Object.values(this.selects).forEach(function (select) { - $('.t-configuration', self.domElement).append(select.getDOM()); + self.domElement.querySelector('.t-configuration').append(select.getDOM()); }); - this.listenTo($('.t-value-inputs', this.domElement), 'input', onValueInput); + + this.listenTo(this.domElement.querySelector('.t-value-inputs'), 'input', onValueInput); } Condition.prototype.getDOM = function (container) { @@ -132,7 +134,7 @@ define([ * Hide the appropriate inputs when this is the only condition */ Condition.prototype.hideButtons = function () { - this.deleteButton.hide(); + this.deleteButton.style.display = 'none'; }; /** @@ -172,14 +174,14 @@ define([ */ Condition.prototype.generateValueInputs = function (operation) { const evaluator = this.conditionManager.getEvaluator(); - const inputArea = $('.t-value-inputs', this.domElement); + const inputArea = this.domElement.querySelector('.t-value-inputs'); let inputCount; let inputType; let newInput; let index = 0; let emitChange = false; - inputArea.html(''); + inputArea.innerHTML = ''; this.valueInputs = []; this.config.values = this.config.values || []; @@ -189,17 +191,24 @@ define([ while (index < inputCount) { if (inputType === 'select') { - newInput = $(''); + const options = this.generateSelectOptions(); + + newInput = document.createElement("select"); + newInput.innerHTML = options; + emitChange = true; } else { const defaultValue = inputType === 'number' ? 0 : ''; const value = this.config.values[index] || defaultValue; this.config.values[index] = value; - newInput = $(''); + + newInput = document.createElement("input"); + newInput.type = `${inputType}`; + newInput.value = `${value}`; } - this.valueInputs.push(newInput.get(0)); - inputArea.append(newInput); + this.valueInputs.push(newInput); + inputArea.appendChild(newInput); index += 1; } diff --git a/src/plugins/summaryWidget/src/ConditionManager.js b/src/plugins/summaryWidget/src/ConditionManager.js index ff90bc7bc7..e502649030 100644 --- a/src/plugins/summaryWidget/src/ConditionManager.js +++ b/src/plugins/summaryWidget/src/ConditionManager.js @@ -2,13 +2,11 @@ define ([ './ConditionEvaluator', 'objectUtils', 'EventEmitter', - 'zepto', 'lodash' ], function ( ConditionEvaluator, objectUtils, EventEmitter, - $, _ ) { @@ -232,7 +230,10 @@ define ([ self.eventEmitter.emit('add', obj); - $('.w-summary-widget').removeClass('s-status-no-data'); + const summaryWidget = document.querySelector('.w-summary-widget'); + if (summaryWidget) { + summaryWidget.classList.remove('s-status-no-data'); + } } }; @@ -256,7 +257,10 @@ define ([ this.eventEmitter.emit('remove', identifier); if (_.isEmpty(this.compositionObjs)) { - $('.w-summary-widget').addClass('s-status-no-data'); + const summaryWidget = document.querySelector('.w-summary-widget'); + if (summaryWidget) { + summaryWidget.classList.add('s-status-no-data'); + } } }; diff --git a/src/plugins/summaryWidget/src/Rule.js b/src/plugins/summaryWidget/src/Rule.js index d9217f0e0c..0b8f28804f 100644 --- a/src/plugins/summaryWidget/src/Rule.js +++ b/src/plugins/summaryWidget/src/Rule.js @@ -4,18 +4,18 @@ define([ './input/ColorPalette', './input/IconPalette', './eventHelpers', + '../../../utils/template/templateHelpers', 'EventEmitter', - 'lodash', - 'zepto' + 'lodash' ], function ( ruleTemplate, Condition, ColorPalette, IconPalette, eventHelpers, + templateHelpers, EventEmitter, - _, - $ + _ ) { /** * An object representing a summary widget rule. Maintains a set of text @@ -41,7 +41,7 @@ define([ this.widgetDnD = widgetDnD; this.container = container; - this.domElement = $(ruleTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(ruleTemplate)[0]; this.eventEmitter = new EventEmitter(); this.supportedCallbacks = ['remove', 'duplicate', 'change', 'conditionChange']; this.conditions = []; @@ -50,31 +50,32 @@ define([ this.remove = this.remove.bind(this); this.duplicate = this.duplicate.bind(this); - this.thumbnail = $('.t-widget-thumb', this.domElement); - this.thumbnailIcon = $('.js-sw__icon', this.domElement); - this.thumbnailLabel = $('.c-sw__label', this.domElement); - this.title = $('.rule-title', this.domElement); - this.description = $('.rule-description', this.domElement); - this.trigger = $('.t-trigger', this.domElement); - this.toggleConfigButton = $('.js-disclosure', this.domElement); - this.configArea = $('.widget-rule-content', this.domElement); - this.grippy = $('.t-grippy', this.domElement); - this.conditionArea = $('.t-widget-rule-config', this.domElement); - this.jsConditionArea = $('.t-rule-js-condition-input-holder', this.domElement); - this.deleteButton = $('.t-delete', this.domElement); - this.duplicateButton = $('.t-duplicate', this.domElement); - this.addConditionButton = $('.add-condition', this.domElement); + this.thumbnail = this.domElement.querySelector('.t-widget-thumb'); + this.thumbnailIcon = this.domElement.querySelector('.js-sw__icon'); + this.thumbnailLabel = this.domElement.querySelector('.c-sw__label'); + this.title = this.domElement.querySelector('.rule-title'); + this.description = this.domElement.querySelector('.rule-description'); + this.trigger = this.domElement.querySelector('.t-trigger'); + this.toggleConfigButton = this.domElement.querySelector('.js-disclosure'); + this.configArea = this.domElement.querySelector('.widget-rule-content'); + this.grippy = this.domElement.querySelector('.t-grippy'); + this.conditionArea = this.domElement.querySelector('.t-widget-rule-config'); + this.jsConditionArea = this.domElement.querySelector('.t-rule-js-condition-input-holder'); + this.deleteButton = this.domElement.querySelector('.t-delete'); + this.duplicateButton = this.domElement.querySelector('.t-duplicate'); + this.addConditionButton = this.domElement.querySelector('.add-condition'); /** * The text inputs for this rule: any input included in this object will * have the appropriate event handlers registered to it, and it's corresponding * field in the domain object will be updated with its value */ + this.textInputs = { - name: $('.t-rule-name-input', this.domElement), - label: $('.t-rule-label-input', this.domElement), - message: $('.t-rule-message-input', this.domElement), - jsCondition: $('.t-rule-js-condition-input', this.domElement) + name: this.domElement.querySelector('.t-rule-name-input'), + label: this.domElement.querySelector('.t-rule-label-input'), + message: this.domElement.querySelector('.t-rule-message-input'), + jsCondition: this.domElement.querySelector('.t-rule-js-condition-input') }; this.iconInput = new IconPalette('', container); @@ -94,7 +95,7 @@ define([ function onIconInput(icon) { self.config.icon = icon; self.updateDomainObject('icon', icon); - self.thumbnailIcon.removeClass().addClass(THUMB_ICON_CLASS + ' ' + icon); + self.thumbnailIcon.className = `${THUMB_ICON_CLASS + ' ' + icon}`; self.eventEmitter.emit('change'); } @@ -106,7 +107,7 @@ define([ */ function onColorInput(color, property) { self.config.style[property] = color; - self.thumbnail.css(property, color); + self.thumbnail.style[property] = color; self.eventEmitter.emit('change'); } @@ -116,7 +117,10 @@ define([ * @private */ function encodeMsg(msg) { - return $('
').text(msg).html(); + const div = document.createElement('div'); + div.innerText = msg; + + return div.innerText; } /** @@ -144,9 +148,9 @@ define([ self.config[inputKey] = text; self.updateDomainObject(); if (inputKey === 'name') { - self.title.html(text); + self.title.innerText = text; } else if (inputKey === 'label') { - self.thumbnailLabel.html(text); + self.thumbnailLabel.innerText = text; } self.eventEmitter.emit('change'); @@ -158,13 +162,14 @@ define([ * @private */ function onDragStart(event) { - $('.t-drag-indicator').each(function () { + document.querySelectorAll('.t-drag-indicator').forEach(indicator => { // eslint-disable-next-line no-invalid-this - $(this).html($('.widget-rule-header', self.domElement).clone().get(0)); + const ruleHeader = self.domElement.querySelectorAll('.widget-rule-header')[0].cloneNode(true); + indicator.innerHTML = ruleHeader; }); - self.widgetDnD.setDragImage($('.widget-rule-header', self.domElement).clone().get(0)); + self.widgetDnD.setDragImage(self.domElement.querySelectorAll('.widget-rule-header')[0].cloneNode(true)); self.widgetDnD.dragStart(self.config.id); - self.domElement.hide(); + self.domElement.style.display = 'none'; } /** @@ -172,20 +177,31 @@ define([ * @private */ function toggleConfig() { - self.configArea.toggleClass('expanded'); - self.toggleConfigButton.toggleClass('c-disclosure-triangle--expanded'); + if (self.configArea.classList.contains('expanded')) { + self.configArea.classList.remove('expanded'); + } else { + self.configArea.classList.add('expanded'); + } + + if (self.toggleConfigButton.classList.contains('c-disclosure-triangle--expanded')) { + self.toggleConfigButton.classList.remove('c-disclosure-triangle--expanded'); + } else { + self.toggleConfigButton.classList.add('c-disclosure-triangle--expanded'); + } + self.config.expanded = !self.config.expanded; } - $('.t-rule-label-input', this.domElement).before(this.iconInput.getDOM()); + const labelInput = this.domElement.querySelector('.t-rule-label-input'); + labelInput.parentNode.insertBefore(this.iconInput.getDOM(), labelInput); this.iconInput.set(self.config.icon); this.iconInput.on('change', function (value) { onIconInput(value); }); // Initialize thumbs when first loading - this.thumbnailIcon.removeClass().addClass(THUMB_ICON_CLASS + ' ' + self.config.icon); - this.thumbnailLabel.html(self.config.label); + this.thumbnailIcon.className = `${THUMB_ICON_CLASS + ' ' + self.config.icon}`; + this.thumbnailLabel.innerText = self.config.label; Object.keys(this.colorInputs).forEach(function (inputKey) { const input = self.colorInputs[inputKey]; @@ -198,15 +214,17 @@ define([ self.updateDomainObject(); }); - $('.t-style-input', self.domElement).append(input.getDOM()); + self.domElement.querySelector('.t-style-input').append(input.getDOM()); }); Object.keys(this.textInputs).forEach(function (inputKey) { - self.textInputs[inputKey].prop('value', self.config[inputKey] || ''); - self.listenTo(self.textInputs[inputKey], 'input', function () { - // eslint-disable-next-line no-invalid-this - onTextInput(this, inputKey); - }); + if (self.textInputs[inputKey]) { + self.textInputs[inputKey].value = self.config[inputKey] || ''; + self.listenTo(self.textInputs[inputKey], 'input', function () { + // eslint-disable-next-line no-invalid-this + onTextInput(this, inputKey); + }); + } }); this.listenTo(this.deleteButton, 'click', this.remove); @@ -217,15 +235,15 @@ define([ this.listenTo(this.toggleConfigButton, 'click', toggleConfig); this.listenTo(this.trigger, 'change', onTriggerInput); - this.title.html(self.config.name); - this.description.html(self.config.description); - this.trigger.prop('value', self.config.trigger); + this.title.innerHTML = self.config.name; + this.description.innerHTML = self.config.description; + this.trigger.value = self.config.trigger; this.listenTo(this.grippy, 'mousedown', onDragStart); this.widgetDnD.on('drop', function () { // eslint-disable-next-line no-invalid-this this.domElement.show(); - $('.t-drag-indicator').hide(); + document.querySelector('.t-drag-indicator').style.display = 'none'; }, this); if (!this.conditionManager.loadCompleted()) { @@ -233,21 +251,21 @@ define([ } if (!this.config.expanded) { - this.configArea.removeClass('expanded'); - this.toggleConfigButton.removeClass('c-disclosure-triangle--expanded'); + this.configArea.classList.remove('expanded'); + this.toggleConfigButton.classList.remove('c-disclosure-triangle--expanded'); } if (this.domainObject.configuration.ruleOrder.length === 2) { - $('.t-grippy', this.domElement).hide(); + this.domElement.querySelector('.t-grippy').style.display = 'none'; } this.refreshConditions(); //if this is the default rule, hide elements that don't apply if (this.config.id === 'default') { - $('.t-delete', this.domElement).hide(); - $('.t-widget-rule-config', this.domElement).hide(); - $('.t-grippy', this.domElement).hide(); + this.domElement.querySelector('.t-delete').style.display = 'none'; + this.domElement.querySelector('.t-widget-rule-config').style.display = 'none'; + this.domElement.querySelector('.t-grippy').style.display = 'none'; } } @@ -304,8 +322,8 @@ define([ * During a rule drag event, show the placeholder element after this rule */ Rule.prototype.showDragIndicator = function () { - $('.t-drag-indicator').hide(); - $('.t-drag-indicator', this.domElement).show(); + document.querySelector('.t-drag-indicator').style.display = 'none'; + this.domElement.querySelector('.t-drag-indicator').style.display = ''; }; /** @@ -397,7 +415,10 @@ define([ const triggerContextStr = self.config.trigger === 'any' ? ' or ' : ' and '; self.conditions = []; - $('.t-condition', this.domElement).remove(); + + this.domElement.querySelectorAll('.t-condition').forEach(condition => { + condition.remove(); + }); this.config.conditions.forEach(function (condition, index) { const newCondition = new Condition(condition, index, self.conditionManager); @@ -408,16 +429,23 @@ define([ }); if (this.config.trigger === 'js') { - this.jsConditionArea.show(); - this.addConditionButton.hide(); + if (this.jsConditionArea) { + this.jsConditionArea.style.display = ''; + } + + this.addConditionButton.style.display = 'none'; } else { - this.jsConditionArea.hide(); - this.addConditionButton.show(); + if (this.jsConditionArea) { + this.jsConditionArea.style.display = 'none'; + } + + this.addConditionButton.style.display = ''; self.conditions.forEach(function (condition) { $condition = condition.getDOM(); - $('li:last-of-type', self.conditionArea).before($condition); + const lastOfType = self.conditionArea.querySelector('li:last-of-type'); + lastOfType.parentNode.insertBefore($condition, lastOfType); if (loopCnt > 0) { - $('.t-condition-context', $condition).html(triggerContextStr + ' when'); + $condition.querySelector('.t-condition-context').innerHTML = triggerContextStr + ' when'; } loopCnt++; @@ -489,7 +517,7 @@ define([ } description = (description === '' ? this.config.description : description); - this.description.html(description); + this.description.innerHTML = self.config.description; this.config.description = description; }; diff --git a/src/plugins/summaryWidget/src/SummaryWidget.js b/src/plugins/summaryWidget/src/SummaryWidget.js index 1a5c1ceba0..e9c1442bf2 100644 --- a/src/plugins/summaryWidget/src/SummaryWidget.js +++ b/src/plugins/summaryWidget/src/SummaryWidget.js @@ -5,9 +5,9 @@ define([ './TestDataManager', './WidgetDnD', './eventHelpers', + '../../../utils/template/templateHelpers', 'objectUtils', 'lodash', - 'zepto', '@braintree/sanitize-url' ], function ( widgetTemplate, @@ -16,9 +16,9 @@ define([ TestDataManager, WidgetDnD, eventHelpers, + templateHelpers, objectUtils, _, - $, urlSanitizeLib ) { @@ -54,20 +54,22 @@ define([ this.activeId = 'default'; this.rulesById = {}; - this.domElement = $(widgetTemplate); - this.toggleRulesControl = $('.t-view-control-rules', this.domElement); - this.toggleTestDataControl = $('.t-view-control-test-data', this.domElement); - this.widgetButton = this.domElement.children('#widget'); + this.domElement = templateHelpers.convertTemplateToHTML(widgetTemplate)[0]; + this.toggleRulesControl = this.domElement.querySelector('.t-view-control-rules'); + this.toggleTestDataControl = this.domElement.querySelector('.t-view-control-test-data'); + + this.widgetButton = this.domElement.querySelector(':scope > #widget'); + this.editing = false; this.container = ''; - this.editListenerUnsubscribe = $.noop; + this.editListenerUnsubscribe = () => {}; - this.outerWrapper = $('.widget-edit-holder', this.domElement); - this.ruleArea = $('#ruleArea', this.domElement); - this.configAreaRules = $('.widget-rules-wrapper', this.domElement); + this.outerWrapper = this.domElement.querySelector('.widget-edit-holder'); + this.ruleArea = this.domElement.querySelector('#ruleArea'); + this.configAreaRules = this.domElement.querySelector('.widget-rules-wrapper'); - this.testDataArea = $('.widget-test-data', this.domElement); - this.addRuleButton = $('#addRule', this.domElement); + this.testDataArea = this.domElement.querySelector('.widget-test-data'); + this.addRuleButton = this.domElement.querySelector('#addRule'); this.conditionManager = new ConditionManager(this.domainObject, this.openmct); this.testDataManager = new TestDataManager(this.domainObject, this.conditionManager, this.openmct); @@ -87,8 +89,17 @@ define([ * @private */ function toggleTestData() { - self.outerWrapper.toggleClass('expanded-widget-test-data'); - self.toggleTestDataControl.toggleClass('c-disclosure-triangle--expanded'); + if (self.outerWrapper.classList.contains('expanded-widget-test-data')) { + self.outerWrapper.classList.remove('expanded-widget-test-data'); + } else { + self.outerWrapper.classList.add('expanded-widget-test-data'); + } + + if (self.toggleTestDataControl.classList.contains('c-disclosure-triangle--expanded')) { + self.toggleTestDataControl.classList.remove('c-disclosure-triangle--expanded'); + } else { + self.toggleTestDataControl.classList.add('c-disclosure-triangle--expanded'); + } } this.listenTo(this.toggleTestDataControl, 'click', toggleTestData); @@ -98,8 +109,8 @@ define([ * @private */ function toggleRules() { - self.outerWrapper.toggleClass('expanded-widget-rules'); - self.toggleRulesControl.toggleClass('c-disclosure-triangle--expanded'); + templateHelpers.toggleClass(self.outerWrapper, 'expanded-widget-rules'); + templateHelpers.toggleClass(self.toggleRulesControl, 'c-disclosure-triangle--expanded'); } this.listenTo(this.toggleRulesControl, 'click', toggleRules); @@ -113,15 +124,15 @@ define([ */ SummaryWidget.prototype.addHyperlink = function (url, openNewTab) { if (url) { - this.widgetButton.attr('href', urlSanitizeLib.sanitizeUrl(url)); + this.widgetButton.href = urlSanitizeLib.sanitizeUrl(url); } else { - this.widgetButton.removeAttr('href'); + this.widgetButton.removeAttribute('href'); } if (openNewTab === 'newTab') { - this.widgetButton.attr('target', '_blank'); + this.widgetButton.target = '_blank'; } else { - this.widgetButton.removeAttr('target'); + this.widgetButton.removeAttribute('target'); } }; @@ -149,8 +160,8 @@ define([ SummaryWidget.prototype.show = function (container) { const self = this; this.container = container; - $(container).append(this.domElement); - $('.widget-test-data', this.domElement).append(this.testDataManager.getDOM()); + this.container.append(this.domElement); + this.domElement.querySelector('.widget-test-data').append(this.testDataManager.getDOM()); this.widgetDnD = new WidgetDnD(this.domElement, this.domainObject.configuration.ruleOrder, this.rulesById); this.initRule('default', 'Default'); this.domainObject.configuration.ruleOrder.forEach(function (ruleId) { @@ -190,7 +201,7 @@ define([ const self = this; const ruleOrder = self.domainObject.configuration.ruleOrder; const rules = self.rulesById; - self.ruleArea.html(''); + self.ruleArea.innerHTML = ''; Object.values(ruleOrder).forEach(function (ruleId) { self.ruleArea.append(rules[ruleId].getDOM()); }); @@ -205,9 +216,9 @@ define([ rules.forEach(function (ruleKey, index, array) { if (array.length > 2 && index > 0) { - $('.t-grippy', rulesById[ruleKey].domElement).show(); + rulesById[ruleKey].domElement.querySelector('.t-grippy').style.display = ''; } else { - $('.t-grippy', rulesById[ruleKey].domElement).hide(); + rulesById[ruleKey].domElement.querySelector('.t-grippy').style.display = 'none'; } }); }; @@ -218,10 +229,10 @@ define([ SummaryWidget.prototype.updateWidget = function () { const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon'; const activeRule = this.rulesById[this.activeId]; - this.applyStyle($('#widget', this.domElement), activeRule.getProperty('style')); - $('#widget', this.domElement).prop('title', activeRule.getProperty('message')); - $('#widgetLabel', this.domElement).html(activeRule.getProperty('label')); - $('#widgetIcon', this.domElement).removeClass().addClass(WIDGET_ICON_CLASS + ' ' + activeRule.getProperty('icon')); + this.applyStyle(this.domElement.querySelector('#widget'), activeRule.getProperty('style')); + this.domElement.querySelector('#widget').title = activeRule.getProperty('message'); + this.domElement.querySelector('#widgetLabel').innerHTML = activeRule.getProperty('label'); + this.domElement.querySelector('#widgetIcon').classList = WIDGET_ICON_CLASS + ' ' + activeRule.getProperty('icon'); }; /** @@ -356,7 +367,7 @@ define([ */ SummaryWidget.prototype.applyStyle = function (elem, style) { Object.keys(style).forEach(function (propId) { - elem.css(propId, style[propId]); + elem.style[propId] = style[propId]; }); }; diff --git a/src/plugins/summaryWidget/src/TestDataItem.js b/src/plugins/summaryWidget/src/TestDataItem.js index 32b737a90e..ae005c46d0 100644 --- a/src/plugins/summaryWidget/src/TestDataItem.js +++ b/src/plugins/summaryWidget/src/TestDataItem.js @@ -3,15 +3,15 @@ define([ './input/ObjectSelect', './input/KeySelect', './eventHelpers', - 'EventEmitter', - 'zepto' + '../../../utils/template/templateHelpers', + 'EventEmitter' ], function ( itemTemplate, ObjectSelect, KeySelect, eventHelpers, - EventEmitter, - $ + templateHelpers, + EventEmitter ) { /** @@ -31,12 +31,12 @@ define([ this.index = index; this.conditionManager = conditionManager; - this.domElement = $(itemTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(itemTemplate)[0]; this.eventEmitter = new EventEmitter(); this.supportedCallbacks = ['remove', 'duplicate', 'change']; - this.deleteButton = $('.t-delete', this.domElement); - this.duplicateButton = $('.t-duplicate', this.domElement); + this.deleteButton = this.domElement.querySelector('.t-delete'); + this.duplicateButton = this.domElement.querySelector('.t-duplicate'); this.selects = {}; this.valueInputs = []; @@ -101,7 +101,7 @@ define([ }); Object.values(this.selects).forEach(function (select) { - $('.t-configuration', self.domElement).append(select.getDOM()); + self.domElement.querySelector('.t-configuration').append(select.getDOM()); }); this.listenTo(this.domElement, 'input', onValueInput); } @@ -139,7 +139,7 @@ define([ * Hide the appropriate inputs when this is the only item */ TestDataItem.prototype.hideButtons = function () { - this.deleteButton.hide(); + this.deleteButton.style.display = 'none'; }; /** @@ -177,17 +177,21 @@ define([ */ TestDataItem.prototype.generateValueInput = function (key) { const evaluator = this.conditionManager.getEvaluator(); - const inputArea = $('.t-value-inputs', this.domElement); + const inputArea = this.domElement.querySelector('.t-value-inputs'); const dataType = this.conditionManager.getTelemetryPropertyType(this.config.object, key); const inputType = evaluator.getInputTypeById(dataType); - inputArea.html(''); + inputArea.innerHTML = ''; if (inputType) { if (!this.config.value) { this.config.value = (inputType === 'number' ? 0 : ''); } - this.valueInput = $(' ').get(0); + const newInput = document.createElement("input"); + newInput.type = `${inputType}`; + newInput.value = `${this.config.value}`; + + this.valueInput = newInput; inputArea.append(this.valueInput); } }; diff --git a/src/plugins/summaryWidget/src/TestDataManager.js b/src/plugins/summaryWidget/src/TestDataManager.js index 819cc5ee3f..70240453d6 100644 --- a/src/plugins/summaryWidget/src/TestDataManager.js +++ b/src/plugins/summaryWidget/src/TestDataManager.js @@ -2,13 +2,13 @@ define([ './eventHelpers', '../res/testDataTemplate.html', './TestDataItem', - 'zepto', + '../../../utils/template/templateHelpers', 'lodash' ], function ( eventHelpers, testDataTemplate, TestDataItem, - $, + templateHelpers, _ ) { @@ -28,13 +28,13 @@ define([ this.openmct = openmct; this.evaluator = this.manager.getEvaluator(); - this.domElement = $(testDataTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(testDataTemplate)[0]; this.config = this.domainObject.configuration.testDataConfig; this.testCache = {}; - this.itemArea = $('.t-test-data-config', this.domElement); - this.addItemButton = $('.add-test-condition', this.domElement); - this.testDataInput = $('.t-test-data-checkbox', this.domElement); + this.itemArea = this.domElement.querySelector('.t-test-data-config'); + this.addItemButton = this.domElement.querySelector('.add-test-condition'); + this.testDataInput = this.domElement.querySelector('.t-test-data-checkbox'); /** * Toggles whether the associated {ConditionEvaluator} uses the actual @@ -139,7 +139,10 @@ define([ } self.items = []; - $('.t-test-data-item', this.domElement).remove(); + + this.domElement.querySelectorAll('.t-test-data-item').forEach(item => { + item.remove(); + }); this.config.forEach(function (item, index) { const newItem = new TestDataItem(item, index, self.manager); @@ -150,7 +153,6 @@ define([ }); self.items.forEach(function (item) { - // $('li:last-of-type', self.itemArea).before(item.getDOM()); self.itemArea.prepend(item.getDOM()); }); diff --git a/src/plugins/summaryWidget/src/WidgetDnD.js b/src/plugins/summaryWidget/src/WidgetDnD.js index e9ee2f0400..90cd3b6971 100644 --- a/src/plugins/summaryWidget/src/WidgetDnD.js +++ b/src/plugins/summaryWidget/src/WidgetDnD.js @@ -1,11 +1,11 @@ define([ '../res/ruleImageTemplate.html', 'EventEmitter', - 'zepto' + '../../../utils/template/templateHelpers' ], function ( ruleImageTemplate, EventEmitter, - $ + templateHelpers ) { /** @@ -19,8 +19,8 @@ define([ this.ruleOrder = ruleOrder; this.rulesById = rulesById; - this.imageContainer = $(ruleImageTemplate); - this.image = $('.t-drag-rule-image', this.imageContainer); + this.imageContainer = templateHelpers.convertTemplateToHTML(ruleImageTemplate)[0]; + this.image = this.imageContainer.querySelector('.t-drag-rule-image'); this.draggingId = ''; this.draggingRulePrevious = ''; this.eventEmitter = new EventEmitter(); @@ -29,18 +29,18 @@ define([ this.drag = this.drag.bind(this); this.drop = this.drop.bind(this); - $(this.container).on('mousemove', this.drag); - $(document).on('mouseup', this.drop); - $(this.container).before(this.imageContainer); - $(this.imageContainer).hide(); + this.container.addEventListener('mousemove', this.drag); + document.addEventListener('mouseup', this.drop); + this.container.parentNode.insertBefore(this.imageContainer, this.container); + this.imageContainer.style.display = 'none'; } /** * Remove event listeners registered to elements external to the widget */ WidgetDnD.prototype.destroy = function () { - $(this.container).off('mousemove', this.drag); - $(document).off('mouseup', this.drop); + this.container.removeEventListener('mousemove', this.drag); + document.removeEventListener('mouseup', this.drop); }; /** @@ -81,7 +81,8 @@ define([ let target = ''; ruleOrder.forEach(function (ruleId, index) { - offset = rulesById[ruleId].getDOM().offset(); + const ruleDOM = rulesById[ruleId].getDOM(); + offset = window.innerWidth - (ruleDOM.offsetLeft + ruleDOM.offsetWidth); y = offset.top; height = offset.height; if (index === 0) { @@ -114,7 +115,7 @@ define([ this.imageContainer.show(); this.imageContainer.offset({ top: event.pageY - this.image.height() / 2, - left: event.pageX - $('.t-grippy', this.image).width() + left: event.pageX - this.image.querySelector('.t-grippy').style.width }); }; @@ -129,7 +130,7 @@ define([ dragTarget = this.getDropLocation(event); this.imageContainer.offset({ top: event.pageY - this.image.height() / 2, - left: event.pageX - $('.t-grippy', this.image).width() + left: event.pageX - this.image.querySelector('.t-grippy').style.width }); if (this.rulesById[dragTarget]) { this.rulesById[dragTarget].showDragIndicator(); diff --git a/src/plugins/summaryWidget/src/input/ColorPalette.js b/src/plugins/summaryWidget/src/input/ColorPalette.js index 0bbe236419..2319f98304 100644 --- a/src/plugins/summaryWidget/src/input/ColorPalette.js +++ b/src/plugins/summaryWidget/src/input/ColorPalette.js @@ -1,10 +1,8 @@ define([ - './Palette', - 'zepto' + './Palette' ], function ( - Palette, - $ + Palette ) { //The colors that will be used to instantiate this palette if none are provided @@ -33,17 +31,16 @@ function ( this.palette.setNullOption('rgba(0,0,0,0)'); - const domElement = $(this.palette.getDOM()); + const domElement = this.palette.getDOM(); const self = this; - $('.c-button--menu', domElement).addClass('c-button--swatched'); - $('.t-swatch', domElement).addClass('color-swatch'); - $('.c-palette', domElement).addClass('c-palette--color'); + domElement.querySelector('.c-button--menu').classList.add('c-button--swatched'); + domElement.querySelector('.t-swatch').classList.add('color-swatch'); + domElement.querySelector('.c-palette').classList.add('c-palette--color'); - $('.c-palette__item', domElement).each(function () { + domElement.querySelectorAll('.c-palette__item').forEach(item => { // eslint-disable-next-line no-invalid-this - const elem = this; - $(elem).css('background-color', elem.dataset.item); + item.style.backgroundColor = item.dataset.item; }); /** @@ -53,7 +50,7 @@ function ( */ function updateSwatch() { const color = self.palette.getCurrent(); - $('.color-swatch', domElement).css('background-color', color); + domElement.querySelector('.color-swatch').style.backgroundColor = color; } this.palette.on('change', updateSwatch); diff --git a/src/plugins/summaryWidget/src/input/IconPalette.js b/src/plugins/summaryWidget/src/input/IconPalette.js index cdc011d5da..557cc4d958 100644 --- a/src/plugins/summaryWidget/src/input/IconPalette.js +++ b/src/plugins/summaryWidget/src/input/IconPalette.js @@ -1,9 +1,7 @@ define([ - './Palette', - 'zepto' + './Palette' ], function ( - Palette, - $ + Palette ) { //The icons that will be used to instantiate this palette if none are provided const DEFAULT_ICONS = [ @@ -45,20 +43,19 @@ define([ this.icons = icons || DEFAULT_ICONS; this.palette = new Palette(cssClass, container, this.icons); - this.palette.setNullOption(' '); - this.oldIcon = this.palette.current || ' '; + this.palette.setNullOption(''); + this.oldIcon = this.palette.current || ''; - const domElement = $(this.palette.getDOM()); + const domElement = this.palette.getDOM(); const self = this; - $('.c-button--menu', domElement).addClass('c-button--swatched'); - $('.t-swatch', domElement).addClass('icon-swatch'); - $('.c-palette', domElement).addClass('c-palette--icon'); + domElement.querySelector('.c-button--menu').classList.add('c-button--swatched'); + domElement.querySelector('.t-swatch').classList.add('icon-swatch'); + domElement.querySelector('.c-palette').classList.add('c-palette--icon'); - $('.c-palette-item', domElement).each(function () { + domElement.querySelectorAll('.c-palette-item').forEach(item => { // eslint-disable-next-line no-invalid-this - const elem = this; - $(elem).addClass(elem.dataset.item); + item.classList.add(item.dataset.item); }); /** @@ -67,8 +64,11 @@ define([ * @private */ function updateSwatch() { - $('.icon-swatch', domElement).removeClass(self.oldIcon) - .addClass(self.palette.getCurrent()); + if (self.oldIcon) { + domElement.querySelector('.icon-swatch').classList.remove(self.oldIcon); + } + + domElement.querySelector('.icon-swatch').classList.add(self.palette.getCurrent()); self.oldIcon = self.palette.getCurrent(); } diff --git a/src/plugins/summaryWidget/src/input/Palette.js b/src/plugins/summaryWidget/src/input/Palette.js index ff1d3b5500..96df813de2 100644 --- a/src/plugins/summaryWidget/src/input/Palette.js +++ b/src/plugins/summaryWidget/src/input/Palette.js @@ -1,13 +1,13 @@ define([ '../eventHelpers', '../../res/input/paletteTemplate.html', - 'EventEmitter', - 'zepto' + '../../../../utils/template/templateHelpers', + 'EventEmitter' ], function ( eventHelpers, paletteTemplate, - EventEmitter, - $ + templateHelpers, + EventEmitter ) { /** * Instantiates a new Open MCT Color Palette input @@ -28,36 +28,41 @@ define([ this.items = items; this.container = container; - this.domElement = $(paletteTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(paletteTemplate)[0]; + this.itemElements = { - nullOption: $('.c-palette__item-none .c-palette__item', this.domElement) + nullOption: this.domElement.querySelector('.c-palette__item-none .c-palette__item') }; this.eventEmitter = new EventEmitter(); this.supportedCallbacks = ['change']; this.value = this.items[0]; this.nullOption = ' '; - this.button = $('.js-button', this.domElement); - this.menu = $('.c-menu', this.domElement); + this.button = this.domElement.querySelector('.js-button'); + this.menu = this.domElement.querySelector('.c-menu'); this.hideMenu = this.hideMenu.bind(this); - self.button.addClass(this.cssClass); + if (this.cssClass) { + self.button.classList.add(this.cssClass); + } + self.setNullOption(this.nullOption); self.items.forEach(function (item) { - const itemElement = $('
'); - $('.c-palette__items', self.domElement).append(itemElement); - self.itemElements[item] = itemElement; + const itemElement = `
`; + const temp = document.createElement('div'); + temp.innerHTML = itemElement; + self.itemElements[item] = temp.firstChild; + self.domElement.querySelector('.c-palette__items').appendChild(temp.firstChild); }); - $('.c-menu', self.domElement).hide(); + self.domElement.querySelector('.c-menu').style.display = 'none'; - this.listenTo($(document), 'click', this.hideMenu); - this.listenTo($('.js-button', self.domElement), 'click', function (event) { + this.listenTo(window.document, 'click', this.hideMenu); + this.listenTo(self.domElement.querySelector('.js-button'), 'click', function (event) { event.stopPropagation(); - $('.c-menu', self.container).hide(); - $('.c-menu', self.domElement).show(); + self.container.querySelector('.c-menu').style.display = 'none'; + self.domElement.querySelector('.c-menu').style.display = ''; }); /** @@ -70,10 +75,12 @@ define([ const elem = event.currentTarget; const item = elem.dataset.item; self.set(item); - $('.c-menu', self.domElement).hide(); + self.domElement.querySelector('.c-menu').style.display = 'none'; } - this.listenTo($('.c-palette__item', self.domElement), 'click', handleItemClick); + self.domElement.querySelectorAll('.c-palette__item').forEach(item => { + this.listenTo(item, 'click', handleItemClick); + }); } /** @@ -91,7 +98,7 @@ define([ }; Palette.prototype.hideMenu = function () { - $('.c-menu', this.domElement).hide(); + this.domElement.querySelector('.c-menu').style.display = 'none'; }; /** @@ -141,12 +148,16 @@ define([ * Update the view assoicated with the currently selected item */ Palette.prototype.updateSelected = function (item) { - $('.c-palette__item', this.domElement).removeClass('is-selected'); - this.itemElements[item].addClass('is-selected'); + this.domElement.querySelectorAll('.c-palette__item').forEach(paletteItem => { + if (paletteItem.classList.contains('is-selected')) { + paletteItem.classList.remove('is-selected'); + } + }); + this.itemElements[item].classList.add('is-selected'); if (item === 'nullOption') { - $('.t-swatch', this.domElement).addClass('no-selection'); + this.domElement.querySelector('.t-swatch').classList.add('no-selection'); } else { - $('.t-swatch', this.domElement).removeClass('no-selection'); + this.domElement.querySelector('.t-swatch').classList.remove('no-selection'); } }; @@ -157,14 +168,20 @@ define([ */ Palette.prototype.setNullOption = function (item) { this.nullOption = item; - this.itemElements.nullOption.data('item', item); + this.itemElements.nullOption.data = { item: item }; }; /** * Hides the 'no selection' option to be hidden in the view if it doesn't apply */ Palette.prototype.toggleNullOption = function () { - $('.c-palette__item-none', this.domElement).toggle(); + const elem = this.domElement.querySelector('.c-palette__item-none'); + + if (elem.style.display === 'none') { + this.domElement.querySelector('.c-palette__item-none').style.display = 'flex'; + } else { + this.domElement.querySelector('.c-palette__item-none').style.display = 'none'; + } }; return Palette; diff --git a/src/plugins/summaryWidget/src/input/Select.js b/src/plugins/summaryWidget/src/input/Select.js index 3f89034caf..676a9791b2 100644 --- a/src/plugins/summaryWidget/src/input/Select.js +++ b/src/plugins/summaryWidget/src/input/Select.js @@ -1,13 +1,13 @@ define([ '../eventHelpers', '../../res/input/selectTemplate.html', - 'EventEmitter', - 'zepto' + '../../../../utils/template/templateHelpers', + 'EventEmitter' ], function ( eventHelpers, selectTemplate, - EventEmitter, - $ + templateHelpers, + EventEmitter ) { /** @@ -20,7 +20,8 @@ define([ const self = this; - this.domElement = $(selectTemplate); + this.domElement = templateHelpers.convertTemplateToHTML(selectTemplate)[0]; + this.options = []; this.eventEmitter = new EventEmitter(); this.supportedCallbacks = ['change']; @@ -35,12 +36,12 @@ define([ */ function onChange(event) { const elem = event.target; - const value = self.options[$(elem).prop('selectedIndex')]; + const value = self.options[elem.selectedIndex]; self.eventEmitter.emit('change', value[0]); } - this.listenTo($('select', this.domElement), 'change', onChange, this); + this.listenTo(this.domElement.querySelector('select'), 'change', onChange, this); } /** @@ -74,16 +75,19 @@ define([ const self = this; let selectedIndex = 0; - selectedIndex = $('select', this.domElement).prop('selectedIndex'); - $('option', this.domElement).remove(); + selectedIndex = this.domElement.querySelector('select').selectedIndex; - self.options.forEach(function (option, index) { - $('select', self.domElement) - .append(''); + this.domElement.querySelector('select').innerHTML = ''; + + self.options.forEach(function (option) { + const optionElement = document.createElement('option'); + optionElement.value = option[0]; + optionElement.innerText = `+ ${option[1]}`; + + self.domElement.querySelector('select').appendChild(optionElement); }); - $('select', this.domElement).prop('selectedIndex', selectedIndex); + this.domElement.querySelector('select').selectedIndex = selectedIndex; }; /** @@ -120,7 +124,7 @@ define([ selectedIndex = index; } }); - $('select', this.domElement).prop('selectedIndex', selectedIndex); + this.domElement.querySelector('select').selectedIndex = selectedIndex; selectedOption = this.options[selectedIndex]; this.eventEmitter.emit('change', selectedOption[0]); @@ -131,17 +135,21 @@ define([ * @return {string} */ Select.prototype.getSelected = function () { - return $('select', this.domElement).prop('value'); + return this.domElement.querySelector('select').value; }; Select.prototype.hide = function () { - $(this.domElement).addClass('hidden'); - $('.equal-to').addClass('hidden'); + this.domElement.classList.add('hidden'); + if (this.domElement.querySelector('.equal-to')) { + this.domElement.querySelector('.equal-to').classList.add('hidden'); + } }; Select.prototype.show = function () { - $(this.domElement).removeClass('hidden'); - $('.equal-to').removeClass('hidden'); + this.domElement.classList.remove('hidden'); + if (this.domElement.querySelector('.equal-to')) { + this.domElement.querySelector('.equal-to').classList.remove('hidden'); + } }; Select.prototype.destroy = function () { diff --git a/src/plugins/summaryWidget/test/ConditionSpec.js b/src/plugins/summaryWidget/test/ConditionSpec.js index a69742065b..8b166bf872 100644 --- a/src/plugins/summaryWidget/test/ConditionSpec.js +++ b/src/plugins/summaryWidget/test/ConditionSpec.js @@ -20,7 +20,7 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define(['../src/Condition', 'zepto'], function (Condition, $) { +define(['../src/Condition'], function (Condition) { xdescribe('A summary widget condition', function () { let testCondition; let mockConfig; @@ -33,7 +33,7 @@ define(['../src/Condition', 'zepto'], function (Condition, $) { let generateValuesSpy; beforeEach(function () { - mockContainer = $(document.createElement('div')); + mockContainer = document.createElement('div'); mockConfig = { object: 'object1', @@ -78,7 +78,7 @@ define(['../src/Condition', 'zepto'], function (Condition, $) { it('exposes a DOM element to represent itself in the view', function () { mockContainer.append(testCondition.getDOM()); - expect($('.t-condition', mockContainer).get().length).toEqual(1); + expect(mockContainer.querySelectorAll('.t-condition').length).toEqual(1); }); it('responds to a change in its object select', function () { @@ -111,41 +111,59 @@ define(['../src/Condition', 'zepto'], function (Condition, $) { }); it('generates value inputs of the appropriate type and quantity', function () { + let inputs; + mockContainer.append(testCondition.getDOM()); mockEvaluator.getInputType.and.returnValue('number'); mockEvaluator.getInputCount.and.returnValue(3); testCondition.generateValueInputs(''); - expect($('input', mockContainer).filter('[type=number]').get().length).toEqual(3); - expect($('input', mockContainer).eq(0).prop('valueAsNumber')).toEqual(1); - expect($('input', mockContainer).eq(1).prop('valueAsNumber')).toEqual(2); - expect($('input', mockContainer).eq(2).prop('valueAsNumber')).toEqual(3); + + inputs = mockContainer.querySelectorAll('input'); + const numberInputs = Array.from(inputs).filter(input => input.type === 'number'); + + expect(numberInputs.length).toEqual(3); + expect(numberInputs[0].valueAsNumber).toEqual(1); + expect(numberInputs[1].valueAsNumber).toEqual(2); + expect(numberInputs[2].valueAsNumber).toEqual(3); mockEvaluator.getInputType.and.returnValue('text'); mockEvaluator.getInputCount.and.returnValue(2); testCondition.config.values = ['Text I Am', 'Text It Is']; testCondition.generateValueInputs(''); - expect($('input', mockContainer).filter('[type=text]').get().length).toEqual(2); - expect($('input', mockContainer).eq(0).prop('value')).toEqual('Text I Am'); - expect($('input', mockContainer).eq(1).prop('value')).toEqual('Text It Is'); + + inputs = mockContainer.querySelectorAll('input'); + const textInputs = Array.from(inputs).filter(input => input.type === 'text'); + + expect(textInputs.length).toEqual(2); + expect(textInputs[0].value).toEqual('Text I Am'); + expect(textInputs[1].value).toEqual('Text It Is'); }); it('ensures reasonable defaults on values if none are provided', function () { + let inputs; + mockContainer.append(testCondition.getDOM()); mockEvaluator.getInputType.and.returnValue('number'); mockEvaluator.getInputCount.and.returnValue(3); testCondition.config.values = []; testCondition.generateValueInputs(''); - expect($('input', mockContainer).eq(0).prop('valueAsNumber')).toEqual(0); - expect($('input', mockContainer).eq(1).prop('valueAsNumber')).toEqual(0); - expect($('input', mockContainer).eq(2).prop('valueAsNumber')).toEqual(0); + + inputs = Array.from(mockContainer.querySelectorAll('input')); + + expect(inputs[0].valueAsNumber).toEqual(0); + expect(inputs[1].valueAsNumber).toEqual(0); + expect(inputs[2].valueAsNumber).toEqual(0); expect(testCondition.config.values).toEqual([0, 0, 0]); mockEvaluator.getInputType.and.returnValue('text'); mockEvaluator.getInputCount.and.returnValue(2); testCondition.config.values = []; testCondition.generateValueInputs(''); - expect($('input', mockContainer).eq(0).prop('value')).toEqual(''); - expect($('input', mockContainer).eq(1).prop('value')).toEqual(''); + + inputs = Array.from(mockContainer.querySelectorAll('input')); + + expect(inputs[0].value).toEqual(''); + expect(inputs[1].value).toEqual(''); expect(testCondition.config.values).toEqual(['', '']); }); @@ -154,8 +172,16 @@ define(['../src/Condition', 'zepto'], function (Condition, $) { mockEvaluator.getInputType.and.returnValue('number'); mockEvaluator.getInputCount.and.returnValue(3); testCondition.generateValueInputs(''); - $('input', mockContainer).eq(1).prop('value', 9001); - $('input', mockContainer).eq(1).trigger('input'); + + const event = new Event('input', { + bubbles: true, + cancelable: true + }); + const inputs = mockContainer.querySelectorAll('input'); + + inputs[1].value = 9001; + inputs[1].dispatchEvent(event); + expect(changeSpy).toHaveBeenCalledWith({ value: 9001, property: 'values[1]', diff --git a/src/plugins/summaryWidget/test/RuleSpec.js b/src/plugins/summaryWidget/test/RuleSpec.js index 4d6c5b7149..df5108f7ae 100644 --- a/src/plugins/summaryWidget/test/RuleSpec.js +++ b/src/plugins/summaryWidget/test/RuleSpec.js @@ -1,4 +1,4 @@ -define(['../src/Rule', 'zepto'], function (Rule, $) { +define(['../src/Rule'], function (Rule) { describe('A Summary Widget Rule', function () { let mockRuleConfig; let mockDomainObject; @@ -78,7 +78,7 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { 'dragStart' ]); - mockContainer = $(document.createElement('div')); + mockContainer = document.createElement('div'); removeSpy = jasmine.createSpy('removeCallback'); duplicateSpy = jasmine.createSpy('duplicateCallback'); @@ -99,7 +99,7 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { it('gets its DOM element', function () { mockContainer.append(testRule.getDOM()); - expect($('.l-widget-rule', mockContainer).get().length).toBeGreaterThan(0); + expect(mockContainer.querySelectorAll('.l-widget-rule').length).toBeGreaterThan(0); }); it('gets its configuration properties', function () { @@ -185,7 +185,7 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { it('builds condition view from condition configuration', function () { mockContainer.append(testRule.getDOM()); - expect($('.t-condition', mockContainer).get().length).toEqual(2); + expect(mockContainer.querySelectorAll('.t-condition').length).toEqual(2); }); it('responds to input of style properties, and updates the preview', function () { @@ -196,9 +196,9 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { testRule.colorInputs.color.set('#999999'); expect(mockRuleConfig.style.color).toEqual('#999999'); - expect(testRule.thumbnail.css('background-color')).toEqual('rgb(67, 67, 67)'); - expect(testRule.thumbnail.css('border-color')).toEqual('rgb(102, 102, 102)'); - expect(testRule.thumbnail.css('color')).toEqual('rgb(153, 153, 153)'); + expect(testRule.thumbnail.style['background-color']).toEqual('rgb(67, 67, 67)'); + expect(testRule.thumbnail.style['border-color']).toEqual('rgb(102, 102, 102)'); + expect(testRule.thumbnail.style.color).toEqual('rgb(153, 153, 153)'); expect(changeSpy).toHaveBeenCalled(); }); @@ -228,8 +228,12 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { // }); it('allows input for when the rule triggers', function () { - testRule.trigger.prop('value', 'all'); - testRule.trigger.trigger('change'); + testRule.trigger.value = 'all'; + const event = new Event('change', { + bubbles: true, + cancelable: true + }); + testRule.trigger.dispatchEvent(event); expect(testRule.config.trigger).toEqual('all'); expect(conditionChangeSpy).toHaveBeenCalled(); }); @@ -247,7 +251,12 @@ define(['../src/Rule', 'zepto'], function (Rule, $) { }); it('initiates a drag event when its grippy is clicked', function () { - testRule.grippy.trigger('mousedown'); + const event = new Event('mousedown', { + bubbles: true, + cancelable: true + }); + testRule.grippy.dispatchEvent(event); + expect(mockWidgetDnD.setDragImage).toHaveBeenCalled(); expect(mockWidgetDnD.dragStart).toHaveBeenCalledWith('mockRule'); }); diff --git a/src/plugins/summaryWidget/test/SummaryWidgetSpec.js b/src/plugins/summaryWidget/test/SummaryWidgetSpec.js index 1bee993e2d..877b1b366d 100644 --- a/src/plugins/summaryWidget/test/SummaryWidgetSpec.js +++ b/src/plugins/summaryWidget/test/SummaryWidgetSpec.js @@ -20,7 +20,7 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define(['../src/SummaryWidget', 'zepto'], function (SummaryWidget, $) { +define(['../src/SummaryWidget'], function (SummaryWidget) { xdescribe('The Summary Widget', function () { let summaryWidget; let mockDomainObject; @@ -111,7 +111,7 @@ define(['../src/SummaryWidget', 'zepto'], function (SummaryWidget, $) { }); it('builds rules and rule placeholders in view from configuration', function () { - expect($('.l-widget-rule', summaryWidget.ruleArea).get().length).toEqual(2); + expect(summaryWidget.ruleArea.querySelectorAll('.l-widget-rule').length).toEqual(2); }); it('allows initializing a new rule with a particular identifier', function () { @@ -130,7 +130,7 @@ define(['../src/SummaryWidget', 'zepto'], function (SummaryWidget, $) { mockDomainObject.configuration.ruleOrder.forEach(function (ruleId) { expect(mockDomainObject.configuration.ruleConfigById[ruleId]).toBeDefined(); }); - expect($('.l-widget-rule', summaryWidget.ruleArea).get().length).toEqual(6); + expect(summaryWidget.ruleArea.querySelectorAll('.l-widget-rule').length).toEqual(6); }); it('allows duplicating a rule from source configuration', function () { @@ -186,10 +186,10 @@ define(['../src/SummaryWidget', 'zepto'], function (SummaryWidget, $) { it('adds hyperlink to the widget button and sets newTab preference', function () { summaryWidget.addHyperlink('https://www.nasa.gov', 'newTab'); - const widgetButton = $('#widget', mockContainer); + const widgetButton = mockContainer.querySelector('#widget'); - expect(widgetButton.attr('href')).toEqual('https://www.nasa.gov'); - expect(widgetButton.attr('target')).toEqual('_blank'); + expect(widgetButton.href).toEqual('https://www.nasa.gov/'); + expect(widgetButton.target).toEqual('_blank'); }); }); }); diff --git a/src/plugins/summaryWidget/test/TestDataItemSpec.js b/src/plugins/summaryWidget/test/TestDataItemSpec.js index dffa6c6f22..171753efe4 100644 --- a/src/plugins/summaryWidget/test/TestDataItemSpec.js +++ b/src/plugins/summaryWidget/test/TestDataItemSpec.js @@ -1,4 +1,4 @@ -define(['../src/TestDataItem', 'zepto'], function (TestDataItem, $) { +define(['../src/TestDataItem'], function (TestDataItem) { describe('A summary widget test data item', function () { let testDataItem; let mockConfig; @@ -11,7 +11,7 @@ define(['../src/TestDataItem', 'zepto'], function (TestDataItem, $) { let generateValueSpy; beforeEach(function () { - mockContainer = $(document.createElement('div')); + mockContainer = document.createElement('div'); mockConfig = { object: 'object1', @@ -56,7 +56,7 @@ define(['../src/TestDataItem', 'zepto'], function (TestDataItem, $) { it('exposes a DOM element to represent itself in the view', function () { mockContainer.append(testDataItem.getDOM()); - expect($('.t-test-data-item', mockContainer).get().length).toEqual(1); + expect(mockContainer.querySelectorAll('.t-test-data-item').length).toEqual(1); }); it('responds to a change in its object select', function () { @@ -80,34 +80,54 @@ define(['../src/TestDataItem', 'zepto'], function (TestDataItem, $) { }); it('generates a value input of the appropriate type', function () { + let inputs; + mockContainer.append(testDataItem.getDOM()); mockEvaluator.getInputTypeById.and.returnValue('number'); testDataItem.generateValueInput(''); - expect($('input', mockContainer).filter('[type=number]').get().length).toEqual(1); - expect($('input', mockContainer).prop('valueAsNumber')).toEqual(1); + + inputs = mockContainer.querySelectorAll('input'); + const numberInputs = Array.from(inputs).filter(input => input.type === 'number'); + + expect(numberInputs.length).toEqual(1); + expect(inputs[0].valueAsNumber).toEqual(1); mockEvaluator.getInputTypeById.and.returnValue('text'); testDataItem.config.value = 'Text I Am'; testDataItem.generateValueInput(''); - expect($('input', mockContainer).filter('[type=text]').get().length).toEqual(1); - expect($('input', mockContainer).prop('value')).toEqual('Text I Am'); + + inputs = mockContainer.querySelectorAll('input'); + const textInputs = Array.from(inputs).filter(input => input.type === 'text'); + + expect(textInputs.length).toEqual(1); + expect(inputs[0].value).toEqual('Text I Am'); }); it('ensures reasonable defaults on values if none are provided', function () { + let inputs; + mockContainer.append(testDataItem.getDOM()); mockEvaluator.getInputTypeById.and.returnValue('number'); testDataItem.config.value = undefined; testDataItem.generateValueInput(''); - expect($('input', mockContainer).filter('[type=number]').get().length).toEqual(1); - expect($('input', mockContainer).prop('valueAsNumber')).toEqual(0); + + inputs = mockContainer.querySelectorAll('input'); + const numberInputs = Array.from(inputs).filter(input => input.type === 'number'); + + expect(numberInputs.length).toEqual(1); + expect(inputs[0].valueAsNumber).toEqual(0); expect(testDataItem.config.value).toEqual(0); mockEvaluator.getInputTypeById.and.returnValue('text'); testDataItem.config.value = undefined; testDataItem.generateValueInput(''); - expect($('input', mockContainer).filter('[type=text]').get().length).toEqual(1); - expect($('input', mockContainer).prop('value')).toEqual(''); + + inputs = mockContainer.querySelectorAll('input'); + const textInputs = Array.from(inputs).filter(input => input.type === 'text'); + + expect(textInputs.length).toEqual(1); + expect(inputs[0].value).toEqual(''); expect(testDataItem.config.value).toEqual(''); }); @@ -115,8 +135,15 @@ define(['../src/TestDataItem', 'zepto'], function (TestDataItem, $) { mockContainer.append(testDataItem.getDOM()); mockEvaluator.getInputTypeById.and.returnValue('number'); testDataItem.generateValueInput(''); - $('input', mockContainer).prop('value', 9001); - $('input', mockContainer).trigger('input'); + + const event = new Event('input', { + bubbles: true, + cancelable: true + }); + + mockContainer.querySelector('input').value = 9001; + mockContainer.querySelector('input').dispatchEvent(event); + expect(changeSpy).toHaveBeenCalledWith({ value: 9001, property: 'value', diff --git a/src/plugins/summaryWidget/test/TestDataManagerSpec.js b/src/plugins/summaryWidget/test/TestDataManagerSpec.js index 70042250d3..59ce37d92c 100644 --- a/src/plugins/summaryWidget/test/TestDataManagerSpec.js +++ b/src/plugins/summaryWidget/test/TestDataManagerSpec.js @@ -1,4 +1,4 @@ -define(['../src/TestDataManager', 'zepto'], function (TestDataManager, $) { +define(['../src/TestDataManager'], function (TestDataManager) { describe('A Summary Widget Rule', function () { let mockDomainObject; let mockOpenMCT; @@ -103,7 +103,7 @@ define(['../src/TestDataManager', 'zepto'], function (TestDataManager, $) { mockConditionManager.getObjectName.and.returnValue('Object Name'); mockConditionManager.getTelemetryPropertyName.and.returnValue('Property Name'); - mockContainer = $(document.createElement('div')); + mockContainer = document.createElement('div'); testDataManager = new TestDataManager(mockDomainObject, mockConditionManager, mockOpenMCT); }); @@ -114,7 +114,7 @@ define(['../src/TestDataManager', 'zepto'], function (TestDataManager, $) { it('exposes a DOM element to represent itself in the view', function () { mockContainer.append(testDataManager.getDOM()); - expect($('.t-widget-test-data-content', mockContainer).get().length).toBeGreaterThan(0); + expect(mockContainer.querySelectorAll('.t-widget-test-data-content').length).toBeGreaterThan(0); }); it('generates a test cache in the format expected by a condition evaluator', function () { @@ -207,7 +207,7 @@ define(['../src/TestDataManager', 'zepto'], function (TestDataManager, $) { it('builds item view from item configuration', function () { mockContainer.append(testDataManager.getDOM()); - expect($('.t-test-data-item', mockContainer).get().length).toEqual(3); + expect(mockContainer.querySelectorAll('.t-test-data-item').length).toEqual(3); }); it('can remove a item from its configuration', function () { diff --git a/src/utils/template/templateHelpers.js b/src/utils/template/templateHelpers.js new file mode 100644 index 0000000000..70d381ce7d --- /dev/null +++ b/src/utils/template/templateHelpers.js @@ -0,0 +1,14 @@ +export function convertTemplateToHTML(templateString) { + const template = document.createElement('template'); + template.innerHTML = templateString; + + return template.content.cloneNode(true).children; +} + +export function toggleClass(element, className) { + if (element.classList.contains(className)) { + element.classList.remove(className); + } else { + element.classList.add(className); + } +} diff --git a/webpack.common.js b/webpack.common.js index 5b1de5da4f..20f9705f48 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -101,13 +101,6 @@ const config = { test: /\.html$/, type: 'asset/source' }, - { - test: /zepto/, - use: [ - "imports-loader?this=>window", - "exports-loader?Zepto" - ] - }, { test: /\.(jpg|jpeg|png|svg)$/, type: 'asset/resource',