diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 2d7fd34..e3a2a57 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,71 +1,71 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
-name: "CodeQL"
-
-on:
- push:
- branches: [ master ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [ master ]
- schedule:
- - cron: '38 20 * * 0'
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- strategy:
- fail-fast: false
- matrix:
- language: [ 'javascript' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more:
- # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v1
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v1
-
- # âšī¸ Command-line programs to run using the OS shell.
- # đ https://git.io/JvXDl
-
- # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '38 20 * * 0'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+ # Learn more:
+ # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ # âšī¸ Command-line programs to run using the OS shell.
+ # đ https://git.io/JvXDl
+
+ # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.gitignore b/.gitignore
index 21cbec3..1e52bdd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-.vscode
-**/*.Identifier
-.idea
+.vscode
+**/*.Identifier
+.idea
.**/*.DS_Store
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 983aab6..f8bebd8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,21 @@
-MIT License
-
-Copyright (c) 2019-2022 Mansur
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+MIT License
+
+Copyright (c) 2019-2022 Mansur
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 9b327f9..81aa198 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,28 @@
-# PricyMorph đđ
-
-#### đĨ A powerful Chrome Extension that lets you convert currencies effortlessly on any website! Simply select an element in the DOM, and it does the rest. đđą
-
-![Demo](assets/img/demo.gif)
-
-## đĸ Notice
-### đ Found a bug?
Please open an issue! Your help is greatly appreciated! đđ§
-
-### [Download](https://github.com/AydievMansur/price_parse_chrome/archive/master.zip) âĄī¸ **WIP**
-
-##### đ Features:
-
-- Easy & friendly UI
-- A multi site selector support
-- Any chrome based browser support
-- No metric collection
-- Open source
-- Regular updates
-- Lifetime free
-
-
-đ You can also:
-
-- Create a pull request to help develop this plugin
-- All contributors will be mentioned in this repository
-
-[Download](https://github.com/AydievMansur/price_parse_chrome/archive/master.zip)
+# PricyMorph đđ
+
+#### đĨ A powerful Chrome Extension that lets you convert currencies effortlessly on any website! Simply select an element in the DOM, and it does the rest. đđą
+
+![Demo](assets/img/demo.gif)
+
+## đĸ Notice
+### đ Found a bug?
Please open an issue! Your help is greatly appreciated! đđ§
+
+### [Download](https://github.com/AydievMansur/price_parse_chrome/archive/master.zip) âĄī¸ **WIP**
+
+##### đ Features:
+
+- Easy & friendly UI
+- A multi site selector support
+- Any chrome based browser support
+- No metric collection
+- Open source
+- Regular updates
+- Lifetime free
+
+
+đ You can also:
+
+- Create a pull request to help develop this plugin
+- All contributors will be mentioned in this repository
+
+[Download](https://github.com/AydievMansur/price_parse_chrome/archive/master.zip)
diff --git a/assets/img/icon.png b/assets/img/icon.png
new file mode 100644
index 0000000..f6ff5a5
Binary files /dev/null and b/assets/img/icon.png differ
diff --git a/assets/js/app.js b/assets/js/app.js
index 70ef5cb..e3cad1f 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -7,15 +7,34 @@ class DOMCurrencyConverter {
this.convertedElements = new Map();
this.selectionMode = false;
this.highlightOverlay = null;
+ this.currentDropdownType = null;
+ this.observer = null;
+ this.updateTimeout = null;
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleCurrencyChange = this.handleCurrencyChange.bind(this);
this.handleSwitchCurrencies = this.handleSwitchCurrencies.bind(this);
+ this.toggleSelectionMode = this.toggleSelectionMode.bind(this);
+
+ this.debouncedHandleMouseMove = this.debounce(this.handleMouseMove, 16);
+ this.debouncedUpdatePrices = this.debounce(this.updateAllPrices.bind(this), 100);
this.initialize();
}
+ debounce(func, wait) {
+ let timeout;
+ return function executedFunction(...args) {
+ const later = () => {
+ clearTimeout(timeout);
+ func(...args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ }
+
async initialize() {
try {
await this.loadPreferences();
@@ -28,7 +47,7 @@ class DOMCurrencyConverter {
this.initializePopup();
}
- console.log('DOMCurrencyConverter initialized with:', {
+ console.debug('DOMCurrencyConverter initialized with:', {
fromCurrency: this.fromCurrency,
toCurrency: this.toCurrency
});
@@ -48,13 +67,17 @@ class DOMCurrencyConverter {
this.fromBox?.addEventListener('click', () => this.showDropdown('from'));
this.toBox?.addEventListener('click', () => this.showDropdown('to'));
this.switchButton?.addEventListener('click', this.handleSwitchCurrencies);
- this.selectModeButton?.addEventListener('click', () => this.toggleSelectionMode());
+ this.selectModeButton?.addEventListener('click', () => {
+ this.selectionMode = !this.selectionMode;
+ this.toggleSelectionMode(this.selectionMode);
+ });
document.addEventListener('click', (e) => {
if (this.dropdown && !this.dropdown.contains(e.target) &&
!this.fromBox.contains(e.target) &&
!this.toBox.contains(e.target)) {
this.dropdown.style.display = 'none';
+ this.currentDropdownType = null;
}
});
@@ -102,6 +125,11 @@ class DOMCurrencyConverter {
if (message.action === 'toggleSelection') {
this.toggleSelectionMode(message.selectionMode);
sendResponse({ success: true });
+ } else if (message.action === 'currencyUpdated') {
+ this.fromCurrency = message.fromCurrency;
+ this.toCurrency = message.toCurrency;
+ this.debouncedUpdatePrices();
+ sendResponse({ success: true });
}
return true;
});
@@ -131,13 +159,13 @@ class DOMCurrencyConverter {
}
if (enabled) {
- document.addEventListener('mousemove', this.handleMouseMove);
+ document.addEventListener('mousemove', this.debouncedHandleMouseMove);
document.addEventListener('click', this.handleClick);
} else {
if (this.highlightOverlay) {
this.highlightOverlay.style.display = 'none';
}
- document.removeEventListener('mousemove', this.handleMouseMove);
+ document.removeEventListener('mousemove', this.debouncedHandleMouseMove);
document.removeEventListener('click', this.handleClick);
}
@@ -187,8 +215,11 @@ class DOMCurrencyConverter {
if (this.highlightOverlay) {
this.highlightOverlay.style.display = 'none';
}
-
+
+ this.selectionMode = false;
this.toggleSelectionMode(false);
+
+ this.updateSelectionButton();
}
}
@@ -205,26 +236,44 @@ class DOMCurrencyConverter {
}
setupMutationObserver() {
- if (!document.body) return;
+ if (this.observer) {
+ this.observer.disconnect();
+ }
- const observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
+ this.observer = new MutationObserver(mutations => {
+ let shouldUpdate = false;
+ for (const mutation of mutations) {
if (mutation.type === 'childList' || mutation.type === 'characterData') {
- this.convertedElements.forEach((originalData, element) => {
- if (document.contains(element)) {
- this.updateConvertedPrice(element, originalData);
- } else {
- this.convertedElements.delete(element);
- }
+ const affectedElement = [...this.convertedElements.keys()].some(element => {
+ return mutation.target.contains(element) || element.contains(mutation.target);
});
+ if (affectedElement) {
+ shouldUpdate = true;
+ break;
+ }
}
- });
+ }
+ if (shouldUpdate) {
+ this.debouncedUpdatePrices();
+ }
});
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- characterData: true
+ if (document.body) {
+ this.observer.observe(document.body, {
+ childList: true,
+ subtree: true,
+ characterData: true
+ });
+ }
+ }
+
+ updateAllPrices() {
+ this.convertedElements.forEach((originalData, element) => {
+ if (document.contains(element)) {
+ this.updateConvertedPrice(element, originalData);
+ } else {
+ this.convertedElements.delete(element);
+ }
});
}
@@ -275,21 +324,34 @@ class DOMCurrencyConverter {
showDropdown(type) {
if (!this.dropdown || !this.rates) return;
+ if (this.currentDropdownType === type) {
+ this.dropdown.style.display = 'none';
+ this.currentDropdownType = null;
+ return;
+ }
+
const box = type === 'from' ? this.fromBox : this.toBox;
const rect = box.getBoundingClientRect();
this.dropdown.style.top = `${rect.bottom}px`;
this.dropdown.style.left = `${rect.left}px`;
this.dropdown.style.display = 'block';
+ this.currentDropdownType = type;
- this.dropdown.innerHTML = Object.keys(this.rates).map(currency => `
-