यह एक विचार है जो मैं उपयोगकर्ता अनुभव को बेहतर बनाने के लिए काम के दौरान लेकर आया हूं। इसमें एक टेक्स्ट बॉक्स को लागू करना शामिल है जो स्वचालित रूप से यूआरएल का पता लगाता है और उन्हें उपयोगकर्ता प्रकार (स्रोत कोड जीथब/ऑटोलिंकएडिटर) के अनुसार हाइपरलिंक में परिवर्तित करता है। इस शानदार सुविधा को लागू करना कुछ हद तक मुश्किल है, और निम्नलिखित मुद्दों पर ध्यान दिया जाना चाहिए।
... if(target && target.contentEditable){ ... target.contentEditable = true; target.focus(); } ...
रूपांतरण "ऑनकीअप" और "ऑनपेस्ट" घटनाओं द्वारा संचालित होता है। रूपांतरणों की आवृत्ति को कम करने के लिए, "सेटटाइमआउट" के साथ एक विलंब तंत्र लागू किया जाता है, जहां उपयोगकर्ता द्वारा डिफ़ॉल्ट रूप से 1 सेकंड के लिए टाइप करना बंद करने के बाद ही रूपांतरण तर्क चालू हो जाता है।
idle(func, delay = 1000) { ... const idleHandler = function(...args) { if(this[timer]){ clearTimeout(this[timer]); this[timer] = null; } this[timer] = setTimeout(() => { func(...args); this[timer] = null; }, delay); }; return idleHandler.bind(this); }
मेरा मिलान यूआरएल के लिए सही रेगेक्स तैयार करने में समय बर्बाद करने का इरादा नहीं था, इसलिए मुझे एक खोज इंजन के माध्यम से एक उपयोगी रेगेक्स मिला। यदि किसी के पास इससे बेहतर कोई हो, तो बेझिझक मुझे बताएं!
... const URLRegex = /^(https?:\/\/(([a-zA-Z0-9] -?) [a-zA-Z0-9] \.) (([a-zA-Z0-9] -?) [a-zA-Z0-9] ))(:\d )?(\/.*)?(\?.*)?(#.*)?$/; const URLInTextRegex = /(https?:\/\/(([a-zA-Z0-9] -?) [a-zA-Z0-9] \.) (([a-zA-Z0-9] -?) [a-zA-Z0-9] ))(:\d )?(\/.*)?(\?.*)?(#.*)?/; ... if(URLRegex.test(text)){ result = `${escapeHtml(text)}`; }else { // text contains url let textContent = text; let match; while ((match = URLInTextRegex.exec(textContent)) !== null) { const url = match[0]; const beforeUrl = textContent.slice(0, match.index); const afterUrl = textContent.slice(match.index url.length); result = escapeHtml(beforeUrl); result = `${escapeHtml(url)}`; textContent = afterUrl; } result = escapeHtml(textContent); // Append any remaining text }
document.createRange और window.getSelectionfunctions के साथ, नोड के टेक्स्ट के भीतर कर्सर की स्थिति की गणना करें। चूंकि यूआरएल को हाइपरलिंक में परिवर्तित करने से टेक्स्ट सामग्री को संशोधित किए बिना केवल टैग जुड़ते हैं, कर्सर को पहले से रिकॉर्ड की गई स्थिति के आधार पर पुनर्स्थापित किया जा सकता है। अधिक विवरण के लिए, कृपया HTML संशोधित करने के बाद चयन को पुनर्स्थापित नहीं किया जा सकता पढ़ें, भले ही वह वही HTML हो।
हाइपरलिंक संपादित करते समय अपडेट करें या हटाएं
कभी-कभी हम हाइपरलिंक बनाते हैं जहां टेक्स्ट और लक्ष्य यूआरएल समान होते हैं (यहां 'सरल हाइपरलिंक' कहा जाता है)। उदाहरण के लिए, निम्नलिखित HTML इस प्रकार का हाइपरलिंक दिखाता है।
http://www.example.com
ऐसे लिंक के लिए, जब हाइपरलिंक टेक्स्ट को संशोधित किया जाता है, तो उन्हें सिंक में रखने के लिए लक्ष्य URL को भी स्वचालित रूप से अपडेट किया जाना चाहिए। तर्क को और अधिक मजबूत बनाने के लिए, जब हाइपरलिंक टेक्स्ट वैध यूआरएल नहीं रह जाएगा तो लिंक को वापस सादे टेक्स्ट में बदल दिया जाएगा।
handleAnchor: anchor => { ... const text = anchor.textContent; if(URLRegex.test(text)){ return nodeHandler.makePlainAnchor(anchor); }else { return anchor.textContent; } ... } ... makePlainAnchor: target => { ... const result = document.createElement("a"); result.href = target.href; result.textContent = target.textContent; return result; ... }
इस सुविधा को लागू करने के लिए, मैं 'सरल हाइपरलिंक्स' को एक ऑब्जेक्ट में संग्रहीत करता हूं और उन्हें ऑनपेस्ट, ऑनकीअप और ऑनफोकस इवेंट के दौरान वास्तविक समय में अपडेट करता हूं ताकि यह सुनिश्चित हो सके कि उपरोक्त तर्क केवल सरल हाइपरलिंक्स को संभालता है।
target.onpaste = initializer.idle(e => { ... inclusion = contentConvertor.indexAnchors(target); }, 0); const handleKeyup = initializer.idle(e => { ... inclusion = contentConvertor.indexAnchors(target); ... }, 1000); target.onkeyup = handleKeyup; target.onfocus = e => { inclusion = contentConvertor.indexAnchors(target); } ... indexAnchors(target) { const inclusion = {}; ... const anchorTags = target.querySelectorAll('a'); if(anchorTags) { const idPrefix = target.id === "" ? target.dataset.id : target.id; anchorTags.forEach((anchor, index) => { const anchorId = anchor.dataset.id ?? `${idPrefix}-anchor-${index}`; if(anchor.href.replace(/\/ $/, '').toLowerCase() === anchor.textContent.toLowerCase()) { if(!anchor.dataset.id){ anchor.setAttribute('data-id', anchorId); } inclusion[[anchorId]] = anchor.href; } }); } return Object.keys(inclusion).length === 0 ? null : inclusion; ... }
चिपकाए गए रिच टेक्स्ट को संभालते समय, संपादक स्वचालित रूप से संपादक की टेक्स्ट शैलियों के साथ टेक्स्ट को स्टाइल करेगा। फ़ॉर्मेटिंग बनाए रखने के लिए, रिच टेक्स्ट में
टैग और सभी हाइपरलिंक संरक्षित किए जाएंगे। इनपुट टेक्स्ट को संभालना अधिक जटिल है। जब उपयोगकर्ता एक नई लाइन जोड़ने के लिए Enter दबाता है, तो संपादक में एक div तत्व जोड़ा जाता है, जिसे संपादक फ़ॉर्मेटिंग बनाए रखने के लिए
से बदल देता है।
node.childNodes.forEach(child => { if (child.nodeType === 1) { if(child.tagName === 'A') { // anchar element const key = child.id === "" ? child.dataset.id : child.id; if(inclusion && inclusion[key]){ const disposedAnchor = handleAnchor(child); if(disposedAnchor){ if(disposedAnchor instanceof HTMLAnchorElement) { disposedAnchor.href = disposedAnchor.textContent; } result = disposedAnchor.outerHTML ?? disposedAnchor; } }else { result = makePlainAnchor(child)?.outerHTML ?? ""; } }else { result = compensateBR(child) this.extractTextAndAnchor(child, inclusion, nodeHandler); } } }); ... const ElementsOfBR = new Set([ 'block', 'block flex', 'block flow', 'block flow-root', 'block grid', 'list-item', ]); compensateBR: target => { if(target && (target instanceof HTMLBRElement || ElementsOfBR.has(window.getComputedStyle(target).display))){ return "
"; } return ""; }
यह लेख एक साधारण संपादक को लागू करने के लिए उपयोग की जाने वाली कुछ व्यावहारिक तकनीकों का वर्णन करता है, जैसे कि ऑनकीप और ऑनपेस्ट जैसी सामान्य घटनाएं, कर्सर की स्थिति को बहाल करने के लिए चयन और रेंज का उपयोग कैसे करें, और संपादक की स्थिति को प्राप्त करने के लिए किसी तत्व के नोड्स को कैसे संभालना है कार्यक्षमता. हालाँकि नियमित अभिव्यक्तियाँ इस लेख का फोकस नहीं हैं, एक पूर्ण रेगेक्स विशिष्ट स्ट्रिंग्स की पहचान करने में संपादक की मजबूती को बढ़ा सकता है (इस लेख में प्रयुक्त रेगेक्स संशोधन के लिए खुला रहेगा)। यदि यह आपके प्रोजेक्ट के लिए उपयोगी है तो अधिक विवरण प्राप्त करने के लिए आप Github/AutolilnkEditor के माध्यम से स्रोत कोड तक पहुंच सकते हैं।
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3