मैं एक हजार टैब से कैसे छुटकारा पा गया ...

... और 3 साल की देर थी। आदर्श रूप से, यह इस तरह होना चाहिए: उपयोगकर्ता ब्राउज़र लॉन्च करता है, और ब्राउज़र दिखाता है कि उपयोगकर्ता को क्या चाहिए। लेकिन जब यह लागू नहीं होता है, तो आपको खोज इंजन का उपयोग करना होगा। आदर्श रूप में, यह इस तरह होना चाहिए: उपयोगकर्ता एक खोज इंजन खोलता है, एक खोज क्वेरी में प्रवेश करता है, और यह दिखाता है कि उपयोगकर्ता को क्या चाहिए। लेकिन जब "मुझे भाग्यशाली महसूस होता है " बटन इतनी अच्छी तरह से काम नहीं करता है (हालांकि हाल ही में इस दिशा में एक ध्यान देने योग्य आंदोलन हुआ है), कभी-कभी आपको खोज परिणाम पृष्ठ से कई पते पर जाना पड़ता है।

खोज इंजनों का उपयोग करने का परिदृश्य, जाहिरा तौर पर, ऐतिहासिक रूप से तय किया गया था (जब इंटरनेट धीमा था): खोज परिणाम पृष्ठ पर पहुंचते हुए, मैंने पृष्ठभूमि में कई टैब खोले, और बाकी लोड होते समय, पहले टैब को पढ़ना पहले से ही संभव था। मामले में जब मुझे एक टैब पर आवश्यक जानकारी मिली, तो बाकी को मैन्युअल रूप से बंद करना पड़ा। यदि यह तुरंत बंद नहीं हुआ, तो टैब लटका रहता है, जो ब्राउज़र में खुले टैब की संख्या को बढ़ाता है, जो, एक नियम के रूप में, शायद ही कभी उसके बाद बंद हो जाता है।

इसके अलावा, यदि आप नई विंडो में खुलने वाले लिंक वाले पेज पर क्लिक करते हैं, तो कई (तार्किक रूप से) टैब्ड टैब बनाए जाते हैं। जब आपको अपनी जरूरत की जानकारी मिल जाती है, तो आप हमेशा याद नहीं रख सकते हैं कि कौन से टैब जुड़े हुए हैं, आप सब कुछ बंद नहीं कर सकते हैं, जिससे ओपन टैब की संख्या भी बढ़ जाती है।

मुझे हमेशा "फाउंड" बटन की आवश्यकता थी , जो खोज के परिणामों के बाद मुझे साफ कर देगा (चलो इसे "मैं भाग्यशाली था" )। ब्राउज़र एक्सटेंशन की दुनिया में उतरने के बाद, मैंने सोचा कि यह कुछ ऐसा था जो इस मामले में मदद कर सकता है। इसलिए मंद तौर पर एक विस्तार लिखने की इच्छा दिखाई देने लगी जो मेरी समस्याओं को हल कर देगा।

मैं आपको अपनी कहानी सुनाऊंगा, मैं कहानी को कालानुक्रमिक क्रम में आगे बढ़ाऊंगा, निष्कर्ष अप्रत्याशित हो सकते हैं।

पहले कदम की ओर


पहली चीज जो मैंने की थी, वह आधारभूत संरचना: वेबपैक + बेबेल थीऔर अभी मैं हर मॉड्यूल में अपने सहायकों के लिए उस बबैल डुप्लिकेट कोड की तरह नहीं था ऑब्जेक्ट का उपयोग करने के लिए इसे कॉन्फ़िगर करना संभव था babelHelper, लेकिन फिर कोड फ़ाइल babelHelperको वेबपैक कॉन्फ़िगरेशन में कनेक्ट करने की आवश्यकता थी इस तरह की फाइल को प्रोजेक्ट में रखना और इसे entryबदसूरत कहना , मैंने वेबपैक के लिए एक प्लग-इन बनाया, जिसने मेरे लिए यह स्वचालित रूप से किया। पहले कदम पर बहुत प्रयास करने और विस्तार के लिए कुछ और कोड लिखने के बाद, मैं थोड़ा धीमा हो गया।

लगाना

आधार


समय बीत गया, और वेबपैक के लिए केवल एक प्लग-इन उपलब्ध था, जिसने मेरी समस्याओं को किसी भी तरह से हल नहीं किया। और हर बार जब मैंने कुछ खोजा और टैब बंद नहीं किया, तो एक विचार था: "उस विस्तार को पूरा करना अच्छा होगा ..." इच्छा बढ़ी और बढ़ी, और अब, एक अच्छा दिन, मात्रा गुणवत्ता में बढ़ी।

यह बताने का समय कि मुख्य विचार क्या था:
उपयोगकर्ता खोज परिणाम पृष्ठ पर जाता है - SICKLE , हम खोज परिणामों को पार्स करते हैं, अपने लिए लिंक पतों को सहेजते हैं, उपयोगकर्ता द्वारा किसी एक पते पर क्लिक करने के बाद, उसे अन्य पतों और "फाउंड" बटन के साथ एक अधिसूचना दिखाएं। टैब बंद करने के लिए।

जब आप पृष्ठ पर जाते हैं तो विभिन्न विकल्प हो सकते हैं। सबसे सरल: एक अनुरोध - सर्वर से एक प्रतिक्रिया ( 200)) सबसे मुश्किल: एक अनुरोध - कई सर्वर पुनर्निर्देश ( 3xx ), जिसके बाद क्लाइंट पुनर्निर्देशन ( <meta/>जावास्क्रिप्ट का उपयोग करके ), इतिहास एपीआई भी शीर्ष पर है और उनके बीच संयोजन, एक नियम के रूप में, अधिकांश साइटें इस श्रेणी में आती हैं।

सरल संक्रमण का मामला:

एक साधारण संक्रमण का मामला (उत्तर 200)

जटिल संक्रमण का मामला:

जटिल संक्रमण का मामला (3xx + ग्राहक पुनर्निर्देशित)

यही है, पृष्ठ के पते को सहेजना और केवल इसकी जांच करना हमेशा पर्याप्त नहीं होता है। इसलिए, आपको एक तार्किक संक्रमण बनाने की आवश्यकता है, जहां रास्ते में आने वाले सभी पतों को लिखना है, और फिर जांचें कि तार्किक संक्रमण में संग्रहीत पता है। कार्य स्पष्ट है, लेकिन निष्पादन में सब कुछ इतना सीधा नहीं है।

Chrome में, नेविगेशन से संबंधित दो API हैं: webNavigation और webRequest - प्रत्येक की अपनी घटनाओं के साथ। पहला - संक्रमण और ब्राउज़र UI को जोड़ता है, बाद वाला - अंतर्निहित नेटवर्क अनुरोध। इसलिए, यदि इतिहास एपीआई के कारण पृष्ठ पर पते में परिवर्तन हुआ है, बाद के लिए कोई घटना नहीं होगी, और यदि नेटवर्क अनुरोध के दौरान रीडायरेक्ट होता है, तो पूर्व इसे रिपोर्ट नहीं करता है। इसलिए, एक तार्किक परिवर्तन बनाने के लिए, प्रत्येक एपीआई की प्रत्येक घटना से एक चुटकी इकट्ठा करना, दोनों एपीआई का उपयोग करना आवश्यक है।

कुछ विवरण
, webNavigation (wN) :

onBeforeNavigate -> onCommitted -> onDOMContentLoaded -> onCompleted

webRequest (wR):

onBeforeRequest -> [onBeforeRedirect -> onBeforeRequest]* -> onCompleted | onErrorOccurred

wR wN ( ), .. - wN.onBeforeNavigate wR.onBeforeRequest, - . .

, , .

विकास


... आइए हम उस क्षण पर लौटते हैं जब मात्रा गुणवत्ता में बढ़ी है। विकास की शुरुआत से इस बिंदु तक एक महत्वपूर्ण समय बीत चुका है: ब्राउज़रों ने एस 6 मॉड्यूल , छाया डोम और अन्य आधुनिक सुविधाओं का समर्थन करना शुरू किया । प्रोजेक्ट बनाने के लिए, मैं रोलअप में चला गया , इस बार मुझे एक प्लगइन लिखने की ज़रूरत नहीं थी। नींव बनाने के बाद - किसी भी टैब में किसी भी संक्रमण के बारे में जानकारी प्राप्त करने की क्षमता, यह समर्थित SICKLES को पार्स करने और संबंधित पृष्ठों पर सूचनाएं प्रदर्शित करने के तर्क को लागू करने के लिए बनी हुई है।

पहला कार्य काफी आदिम है: हम SICKLE के पते को जानते हैं, सामग्री स्क्रिप्ट का उपयोग करके पृष्ठ की सामग्री में चढ़ते हैं, जिस डेटा में हम रुचि रखते हैं उसे प्राप्त करते हैं, इसे सहेजते हैं, उपयोगकर्ता को अन्य पृष्ठों के साथ एक अधिसूचना दिखाने के लिए पृष्ठों में से एक पर जाने की प्रतीक्षा करें।

दूसरे कार्य के लिए, आपको स्वयं अधिसूचना को लागू करने की आवश्यकता है, पृष्ठ पर उपयोगकर्ता को क्या दिखाना है। और यहाँ, सामग्री स्क्रिप्ट भी नहीं कर सकते हैं।

प्रारंभ में, केवल एक हैंडलर (उर्फ एक नियंत्रक) था जो खोज इंजन के साथ उपयोगकर्ता बातचीत के दौरान तर्क के लिए जिम्मेदार था। जिसके बाद यह विचार सामने आया कि जब उपयोगकर्ता नए टैब में खोले गए लिंक पर क्लिक करता है तो संबंधित टैब पर सूचनाएं क्यों नहीं दिखाते। मुझे तर्क को फिर से करना पड़ा, जिससे यह अधिक सार्वभौमिक हो गया। मिडिलवेयर रिएक्ट / रेडक्स के समान, आप कई संक्रमण हैंडलर कनेक्ट कर सकते हैं, जो भविष्य में आपको एक्सटेंशन सेटिंग में विभिन्न हैंडलर को अक्षम / सक्षम करने की क्षमता को लागू करने की अनुमति देगा।

एकांत


चूंकि अधिसूचना स्क्रीन के निचले भाग में पैनल है, और इसे पृष्ठ लेआउट में जोड़ा जाता है, पृष्ठ पर स्क्रिप्ट इस तत्व के साथ-साथ इस पृष्ठ पर किसी भी अन्य तत्व तक पहुंच सकती है। यही है, सैद्धांतिक रूप से, पृष्ठ यह पता लगा सकता है कि आपने किस खोज क्वेरी का उपयोग किया है, जिसमें खोज इंजन और कौन से अन्य पृष्ठ आपके लिए पेश किए गए हैं, जो बहुत अच्छा नहीं है।

बचाव के लिए शैडो डॉम नामक तकनीक आती है । इसे closed modeबनाते समय वेब पर इसका उपयोग करने की अनुशंसा नहीं की जाती है shadowRoot, क्योंकि यह बहुत अधिक समझ में नहीं आता है (आपको अभी भी तत्व को लिंक को shadowRootकहीं स्टोर करना है यदि आप इसे प्रोग्रामेटिक रूप से एक्सेस करना चाहते हैं, तो आप इसे attachShadowबनाने के लिए फ़ंक्शन को फिर से परिभाषित कर सकते हैं;shadowRootखुले मोड में, और फिर पुनर्परिभाषित के बाद भरी हुई स्क्रिप्ट पहले से ही फ़ंक्शन के नए संस्करण का उपयोग करेगी)।

विस्तार के मामले में, ऐसा नहीं है। सामग्री स्क्रिप्ट और पृष्ठ स्क्रिप्ट समानांतर दुनिया में रहते हैं। पृष्ठ की लिपियों में सामग्री स्क्रिप्ट में परिभाषित वस्तुओं तक पहुंच नहीं है, जबकि सामग्री स्क्रिप्ट ऑब्जेक्ट के डोम कार्यों के मूल कार्यान्वयन के साथ काम करती है (पृष्ठ से एक स्क्रिप्ट द्वारा एक ओवरराइड फ़ंक्शन का उस फ़ंक्शन पर कोई प्रभाव नहीं पड़ता है जिसके साथ सामग्री स्क्रिप्ट काम करती है)। इन दोनों स्थितियों को मिलाकर, हम देखते हैं कि shadowRootएक चर में लिंक को संग्रहीत करके एक निजी के साथ एक तत्व बनाना संभव है

इस मामले में, पृष्ठ से स्क्रिप्ट केवल आवरण तत्व तक पहुंचने में सक्षम होगी, जो इसके लिए खाली होगी। वह अनुरोध या प्रस्तावित पृष्ठों का पाठ प्राप्त नहीं कर सकेगा। उत्पन्न घटनाओं में अधिसूचना या सादे पाठ के अंदर किसी भी तत्व का लिंक न देने के लिए ध्यान रखा जाना चाहिए। इसलिए, विस्तार में, उत्पन्न आईडी का उपयोग घटनाओं में किया जाता है, और पृष्ठभूमि स्क्रिप्ट पहले से ही समझती है कि इस आईडी द्वारा इसकी क्या आवश्यकता है। पेज के लिए, यह आईडी काफी अर्थहीन है।

अनुवाद की कठिनाइयाँ


प्रारंभ में, एक्सटेंशन केवल Google Chrome के लिए विकसित किया गया था , लेकिन WebExtensions API के बाद से , कहीं न कहीं मेरे सिर में अन्य ब्राउज़रों में पोर्ट करने की क्षमता बनी रही। और webextension-polyfill की उपस्थिति ने आत्मविश्वास को प्रेरित किया। लेकिन कोई फर्क नहीं पड़ता। इस विस्तार के लिए पॉलीफ़िल केवल वादों के साथ क्रोम एपीआई का उपयोग करने की क्षमता लाया।

फ़ायरफ़ॉक्स वर्ष की निराशा बन गया है। फ़ायरफ़ॉक्स क्रोम एपीआई बेमेल ( बग 1543647 , बग 1595621 ) काम के विस्तार के लिए महत्वपूर्ण निकला, हम कह सकते हैं कि यह इस ब्राउज़र में काम नहीं करता है (जैसा कि अपेक्षित है)।

विवाल्डी निकटतम थी, लेकिन बिना लागत के भी। प्रतिस्पर्धाwN.onCreatedNavigationTargetयह तब नहीं होता है जब उपयोगकर्ता Shift|Ctrlघटना के बजाय मध्य माउस बटन या + बाएं माउस बटन के माध्यम से लिंक खोलता है wN.onCommitted transitionType == 'start_page', जो क्रोम एपीआई में नहीं है , इस वजह से, एक्सटेंशन सभी मामलों में सही ढंग से काम नहीं करता है। इसके अलावा Vivaldi में एक्सटेंशन के लिए हॉटकीज़ काम नहीं करते हैं। क्रोम में इस मामले में एक हत्यारा विशेषता क्या है, इससे आप जल्दी से टैब के माध्यम से नेविगेट कर सकते हैं और उन्हें बंद कर सकते हैं, इसके लिए एक माउस का उपयोग करने की आवश्यकता के बिना।

निष्कर्ष


कोड लिखने के दौरान, सूचनाओं को प्रदर्शित करने का तर्क कई बार बदल गया, प्रत्येक बार सरल हुआ। नतीजतन, यह पता चला कि बगीचे को तार्किक संक्रमणों के साथ बाड़ देना संभव नहीं था, लेकिन उपयोगकर्ता के "संबंधित संक्रमण" को पकड़ने के लिए (इस घटना wN.onCommittedमें एक ध्वज है transitionTypeजो इंगित करता है कि संक्रमण क्या था, कई मामलों में यह "लिंक" है, जिसका अर्थ है कि उपयोगकर्ता स्विच किया गया था) संदर्भ द्वारा), जो कोड को बहुत सरल करेगा और कई मामलों में काम करेगा, लेकिन सभी में नहीं।

इसके अलावा, विषय में नहीं होने के कारण, मुझे webExtensions API के संदर्भ में अधिक अनुकूलता की उम्मीद थीहमेशा की तरह, आधुनिक ब्राउज़र की दुनिया में रहना अच्छा है, जब आपको पुराने संस्करणों के लिए समर्थन की आवश्यकता नहीं होती है। CSS एनिमेशन एक अद्भुत बात है: आपने जिस js लाइब्रेरी का उपयोग किया था, वह अब कुछ पंक्तियों में css पर किया गया है। कस्टम तत्व एक्सटेंशन में काम नहीं करते हैं, लेकिन छाया डोम काम करता है, जिससे आप इसकी सभी विशेषताओं का लाभ उठा सकते हैं।

विस्तार
chrome web store: Handy Search

Source: https://habr.com/ru/post/undefined/


All Articles