Last active
November 6, 2025 06:57
-
-
Save niskala5570/989a960411d0f07f5c03b6d15f9a68db to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Kamus DBP | |
| // @namespace https://kamus.dbp.gov.my/ | |
| // @version 1.0 | |
| // @description Membolehkan klik kanan, salin. Tukar hamzah biasa kepada hamzah tiga suku. | |
| // @match *://kamus.dbp.gov.my/* | |
| // @run-at document-start | |
| // ==/UserScript== | |
| (function() { | |
| // --- 1) Block the original copy-protection listeners --- | |
| const realAddEvent = document.addEventListener; | |
| document.addEventListener = function(type, listener, options) { | |
| if ([ | |
| 'contextmenu', | |
| 'keydown', | |
| 'selectstart', | |
| 'copy', | |
| 'dragstart', | |
| 'touchstart' | |
| ].includes(type)) { | |
| console.log(`🚫 Blocked listener for: ${type}`); | |
| return; | |
| } | |
| return realAddEvent.call(this, type, listener, options); | |
| }; | |
| // --- 2) Restore normal addEventListener after page loaded --- | |
| window.addEventListener('DOMContentLoaded', () => { | |
| document.addEventListener = realAddEvent; | |
| }); | |
| // --- 3) Add tooltip + click-to-copy behaviour for Jawi text --- | |
| window.addEventListener('load', () => { | |
| const tooltip = document.createElement('div'); | |
| tooltip.className = 'jawi-copy-tooltip'; | |
| tooltip.textContent = 'Klik untuk salin'; | |
| Object.assign(tooltip.style, { | |
| position: 'absolute', | |
| padding: '4px 8px', | |
| background: 'rgba(30,64,175,0.95)', | |
| color: '#fff', | |
| fontSize: '12px', | |
| borderRadius: '6px', | |
| pointerEvents: 'none', | |
| transition: 'opacity 0.2s, transform 0.2s', | |
| opacity: '0', | |
| transform: 'translateY(-10px)', | |
| zIndex: '9999', | |
| }); | |
| document.documentElement.appendChild(tooltip); | |
| function placeTooltipAt(e) { | |
| const x = e.pageX + 10; | |
| const y = Math.max(10, e.pageY - 28); | |
| tooltip.style.left = x + 'px'; | |
| tooltip.style.top = y + 'px'; | |
| } | |
| function attachCopyHandlers(el) { | |
| if (!el || el.dataset.jawiCopyAttached) return; | |
| el.dataset.jawiCopyAttached = '1'; | |
| el.addEventListener('mouseenter', e => { | |
| tooltip.style.opacity = '1'; | |
| tooltip.style.transform = 'translateY(0)'; | |
| placeTooltipAt(e); | |
| }); | |
| el.addEventListener('mousemove', e => placeTooltipAt(e)); | |
| el.addEventListener('mouseleave', () => { | |
| tooltip.style.opacity = '0'; | |
| tooltip.style.transform = 'translateY(-10px)'; | |
| }); | |
| el.addEventListener('click', async () => { | |
| const text = el.textContent.trim(); | |
| try { | |
| await navigator.clipboard.writeText(text); | |
| tooltip.textContent = 'Disalin!'; | |
| tooltip.style.background = 'rgba(22,163,74,0.95)'; | |
| setTimeout(() => { | |
| tooltip.textContent = 'Klik untuk salin'; | |
| tooltip.style.background = 'rgba(30,64,175,0.95)'; | |
| }, 900); | |
| } catch (err) { | |
| console.error('Clipboard write failed', err); | |
| } | |
| }); | |
| } | |
| // Observe new elements dynamically | |
| const observer = new MutationObserver(() => { | |
| document.querySelectorAll('.font-sakkal-majalla').forEach(attachCopyHandlers); | |
| }); | |
| function start() { | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| document.querySelectorAll('.font-sakkal-majalla').forEach(attachCopyHandlers); | |
| console.log('✅ Jawi tooltip/copy ready'); | |
| } | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', start); | |
| } else { | |
| start(); | |
| } | |
| }); | |
| })(); | |
| // --- Normalize Hamza (ء) to Hamza High (ٴ) in DOM elements --- | |
| function normalizeHamzaInDOM() { | |
| const targets = document.querySelectorAll('.font-sakkal-majalla'); // Jawi text nodes | |
| targets.forEach(el => { | |
| if (!el.dataset.hamzaNormalized) { | |
| el.innerHTML = el.innerHTML.replace(/ء(?=[ينو])/g, 'ٴ'); | |
| el.dataset.hamzaNormalized = '1'; // avoid reprocessing | |
| } | |
| }); | |
| } | |
| // Run once when DOM is ready | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', normalizeHamzaInDOM); | |
| } else { | |
| normalizeHamzaInDOM(); | |
| } | |
| // Also observe for dynamically added Jawi entries | |
| const hamzaObserver = new MutationObserver(() => { | |
| normalizeHamzaInDOM(); | |
| }); | |
| hamzaObserver.observe(document.body, { childList: true, subtree: true }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment